internal static List <List <Element> > SimpleGroupBy(List <Element> LinkElements) { Func <List <Element>, int> GetFirstLocation = (elements) => { int result = int.MaxValue; foreach (var item in elements) { if (item.location.openTokenStartIndex < result) { result = item.location.openTokenStartIndex; } } return(result); }; var groupby = LinkElements.GroupBy(o => DomService.getParentPath(o)); List <List <Element> > sortedlist = new List <List <Element> >(); foreach (var item in groupby.OrderBy(o => GetFirstLocation(o.ToList()))) { sortedlist.Add(item.ToList()); } return(sortedlist); }
public static void AssignSubMenu(List <Element> Links, RawMenu ParentMenu) { var commonparent = DomService.FindParent(Links); foreach (var item in Links) { var menu = new RawMenu(); menu.Parent = ParentMenu; menu.LinkElement = item; menu.ContainerElement = FindLinkContainer(item, Links, commonparent); menu.Parent = ParentMenu; ParentMenu.Children.Add(menu); } foreach (var item in ParentMenu.Children) { var sublinks = FindSubLinks(item); if (sublinks != null && sublinks.Count() > 0) { var itemcontainer = DomService.FindParent(sublinks); AssignSubMenu(sublinks, item); } } return; }
public static Element FindLinkContainer(Element Link, List <Element> LinkGroup, Element CommonParent) { var target = Link; var DirectParent = target; while (DirectParent != null && !DirectParent.isEqualNode(CommonParent)) { foreach (var item in LinkGroup) { if (!item.isEqualNode(Link)) { if (DomService.ContainsOrEqualElement(DirectParent, item)) { break; } } } target = DirectParent; DirectParent = target.parentElement; } return(target); }
private static List <Element> GetSameMetaTags(Document dom, HtmlMeta meta) { List <Element> result = new List <Element>(); if (!DomService.HasHeadTag(dom)) { return(null); } var metas = dom.head.getElementsByTagName("meta").item; if (!string.IsNullOrEmpty(meta.name)) { string lowermeta = meta.name.ToLower(); foreach (var item in metas) { var name = item.getAttribute("name"); if (!string.IsNullOrEmpty(name) && name.ToLower() == lowermeta) { result.Add(item); } } } if (result.Any()) { return(result); } if (!string.IsNullOrEmpty(meta.httpequiv)) { string lowermeta = meta.httpequiv.ToLower(); foreach (var item in metas) { var name = item.getAttribute("http-equiv"); if (!string.IsNullOrEmpty(name) && name.ToLower() == lowermeta) { result.Add(item); } } } if (!string.IsNullOrEmpty(meta.charset)) { // string lowermeta = meta.charset.ToLower(); foreach (var item in metas) { var name = item.getAttribute("charset"); if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(meta.charset)) { result.Add(item); } } } return(result); }
/// <summary> /// Convert one group of links into menu, links must be within one group. /// </summary> /// <param name="links"></param> /// <param name="website"></param> /// <param name="IncludeParentInTemplate"></param> /// <param name="maxsiblingindex">if this links group share parents with another link group, should only check sub menu till end of next sibling start. </param> /// <returns></returns> public static Menu ConvertToMenu(List <Element> links, WebSite website) { bool includeparentintemplate = true; int maxsilbingindex = 9999; links = links.OrderBy(o => o.location.openTokenStartIndex).ToList(); Element commonparent = DomService.FindParent(links); var lastlink = links.LastOrDefault(); TestTemplate(ref includeparentintemplate, ref maxsilbingindex, commonparent, lastlink); return(ConvertToMenu(links, commonparent, includeparentintemplate, website, maxsilbingindex)); }
private static Element _GetItemContainer(Document doc, MenuViewModel MenuViewModel) { // find the item container. if (!string.IsNullOrEmpty(MenuViewModel.ItemContainer)) { var itemcontainer = DomService.GetElementByKoobooId(doc, MenuViewModel.ItemContainer) as Element; if (itemcontainer != null) { return(itemcontainer); } } List <Element> containerlist = new List <Element>(); foreach (var item in MenuViewModel.children) { if (!string.IsNullOrEmpty(item.ContainerElement)) { var element = DomService.GetElementByKoobooId(doc, item.ContainerElement) as Element; if (element != null) { containerlist.Add(element); } } } if (containerlist.Count == 0) { foreach (var item in MenuViewModel.children) { var element = DomService.GetElementByKoobooId(doc, item.LinkElement) as Element; if (element != null) { containerlist.Add(element); } } } if (containerlist.Count > 1) { var element = DomService.FindParent(containerlist); if (element != null) { MenuViewModel.ItemContainer = DomService.GetKoobooId(element); } return(element); } return(null); }
internal static List <Element> GetSiblingSubLinks(Element CurrentContainer, Element NextContainer) { List <Node> BetweenNodes = new List <Node>(); int MaxSiblingIndex = 9999; if (NextContainer != null) { MaxSiblingIndex = NextContainer.siblingIndex; var parent = DomService.FindParent(CurrentContainer, NextContainer); var current = CurrentContainer; while (current.depth > parent.depth + 1) { current = current.parentElement; } var next = NextContainer; while (next.depth > parent.depth + 1) { next = next.parentElement; } var NodesInBetween = parent.childNodes.item.Where(o => o.siblingIndex > current.siblingIndex && o.siblingIndex < next.siblingIndex).ToList(); var alllinks = DomService.GetElementsByTagName(NodesInBetween, "a").item; if (alllinks.Count() > 0) { var group = GroupBy(alllinks); return(group[0]); } } else { var parent = CurrentContainer.parentElement; var NodesInBetween = parent.childNodes.item.Where(o => o.siblingIndex > CurrentContainer.siblingIndex).ToList(); var alllinks = DomService.GetElementsByTagName(NodesInBetween, "a").item; if (alllinks.Count() > 0) { var group = GroupBy(alllinks); return(group[0]); } } return(null); }
internal static List <SourceUpdate> GetUpdates(HtmlHeader header, Document dom, string OnlyEnableCulture) { List <SourceUpdate> result; if (DomService.HasHeadTag(dom)) { result = GetUpdateWithDomHeader(header, dom, OnlyEnableCulture); } else { result = GetUpdateWithOutDomHeader(header, dom, OnlyEnableCulture); } return(result); }
public static string DetectKoobooId(Document dom, List <string> SubLinks) { var allinks = dom.getElementsByTagName("a").item; var GroupbyLinks = MenuService.SimpleGroupBy(allinks); bool match = true; bool onetimedismatch = false; foreach (var item in GroupbyLinks) { var allgrouplinks = item.Select(o => o.getAttribute("href")); match = false; foreach (var link in SubLinks) { if (allgrouplinks.Any(o => IsSameUrl(o, link))) { match = true; } else { if (!onetimedismatch) { onetimedismatch = true; } else { match = false; break; } } } if (match) { var commoneparent = DomService.FindParent(item); if (commoneparent != null) { return(DomService.GetKoobooId(commoneparent)); } } } return(null); }
public static string SetBaseHref(string htmlsource, string baseurl) { string strbasetag = "<base href=\"" + baseurl + "\">"; var dom = Kooboo.Dom.DomParser.CreateDom(htmlsource); SourceUpdate update = new SourceUpdate(); update.NewValue = strbasetag; update.EndIndex = -1; if (DomService.HasHeadTag(dom)) { var TagBase = dom.head.getElementsByTagName("base"); if (TagBase != null && TagBase.item.Count() > 0) { var tagElement = TagBase.item[0]; string currentbase = tagElement.getAttribute("href"); if (!string.IsNullOrWhiteSpace(currentbase) && currentbase == strbasetag) { return(htmlsource); } update.StartIndex = tagElement.location.openTokenStartIndex; update.EndIndex = tagElement.location.endTokenEndIndex; } else { var afterheaderlocation = dom.head.location.openTokenEndIndex + 1; update.StartIndex = afterheaderlocation; } } else { var afterHtmlLocation = dom.documentElement.location.openTokenEndIndex + 1; update.StartIndex = afterHtmlLocation; update.NewValue = "<head>" + update.NewValue + "</head>"; } List <SourceUpdate> updates = new List <SourceUpdate>(); updates.Add(update); return(Service.DomService.UpdateSource(htmlsource, updates)); }
public static void AddNewMenu(SiteDb SiteDb, Page page, MenuViewModel NewMenuViewModel) { // menu view can start only with item container. Menu menu = CreateMenu(page.Dom, NewMenuViewModel); if (string.IsNullOrEmpty(menu.Name)) { menu.Name = SiteDb.Menus.GetNewMenuName(); } SiteDb.Menus.AddOrUpdate(menu); var maincontainer = NewMenuViewModel.ItemContainer; var element = DomService.GetElementByKoobooId(page.Dom, maincontainer); string newbody = page.Body.Substring(0, element.location.openTokenStartIndex); newbody += "<menu id='" + menu.Name + "'></menu>"; newbody += page.Body.Substring(element.location.endTokenEndIndex + 1); page.Body = newbody; SiteDb.Pages.AddOrUpdate(page); }
internal static string GetTitle(Dom.Document dom) { var TitleTag = DomService.GetTitleElement(dom); return(TitleTag != null ? TitleTag.InnerHtml : null); }
internal static List <SourceUpdate> GetUpdateWithDomHeader(HtmlHeader header, Document dom, string OnlyEnableCulture) { List <SourceUpdate> updates = new List <SourceUpdate>(); string appendChanges = string.Empty; var titlevalue = GetOnlyOrDefault(header.Titles, OnlyEnableCulture); if (!string.IsNullOrEmpty(titlevalue)) { var titletag = DomService.GetTitleElement(dom); string newtitletag = $"<Title>{titlevalue}</Title>\r\n"; if (titletag == null) { appendChanges += newtitletag; } else { if (titletag.InnerHtml != titlevalue) { updates.Add(new SourceUpdate() { StartIndex = titletag.location.openTokenStartIndex, EndIndex = titletag.location.endTokenEndIndex, NewValue = newtitletag }); } } } foreach (var item in header.Metas) { var checkresult = MetaCheck(item, OnlyEnableCulture); var sametags = GetSameMetaTags(dom, item); string metatag = GenerateMetaTag(item, checkresult.ContentValue); if (sametags != null && sametags.Count() > 0) { var tag = sametags[0]; if (!IsSameMeta(tag, item, checkresult.ContentValue)) { updates.Add(new SourceUpdate() { StartIndex = tag.location.openTokenStartIndex, EndIndex = tag.location.endTokenEndIndex, NewValue = metatag }); } if (sametags.Count() > 1) { int len = sametags.Count(); for (int i = 1; i < len; i++) { updates.Add(new SourceUpdate() { StartIndex = sametags[i].location.openTokenStartIndex, EndIndex = sametags[i].location.endTokenEndIndex, NewValue = null }); } } } else { appendChanges += metatag; } } WriteStyleScript(header, dom, updates, ref appendChanges); if (!string.IsNullOrEmpty(appendChanges)) { var afterheaderlocation = dom.head.location.openTokenEndIndex + 1; updates.Add(new SourceUpdate() { StartIndex = afterheaderlocation, EndIndex = -1, NewValue = appendChanges }); } return(updates); }
/// <summary> /// convert one parent with sub links into a menu.... /// </summary> /// <param name="links"></param> /// <param name="CommonParent"></param> /// <param name="IncludeParentInTemplate"></param> /// <param name="website"></param> /// <returns></returns> public static Menu ConvertToMenu(List <Element> links, Element CommonParent, bool IncludeParentInTemplate, WebSite website, int maxsiblingindex = 9999) { Menu menu = new Menu(); links = links.OrderBy(o => o.location.openTokenStartIndex).ToList(); List <Element> Parents = new List <Element>(); int count = links.Count; for (int i = 0; i < count; i++) { var parent = links[i]; while (!parent.parentElement.isEqualNode(CommonParent) && parent != null) { parent = parent.parentElement; } Parents.Add(parent); } menu.tempdata.StartIndex = Parents[0].location.openTokenStartIndex; menu.tempdata.EndIndex = Parents[count - 1].location.endTokenEndIndex; for (int i = 0; i < count; i++) { var parent = Parents[i]; var linkelement = links[i]; Menu submenu = ConvertToMenu(parent, links[i], website); if (submenu.children.Count == 0) { int nextSiblingEnds = maxsiblingindex; if (i < count - 1) { var nextparent = Parents[i + 1]; nextSiblingEnds = nextparent.siblingIndex; } var tempsublinks = FindLinksAfter(CommonParent, links[i], nextSiblingEnds); /// Check and make sure those sub links are not similar, same level links. List <Element> sublinks = new List <Element>(); if (tempsublinks.Count > 0) { foreach (var item in tempsublinks) { if (isSimiliarLink(item, linkelement)) { break; } sublinks.Add(item); } var groupbylinks = GroupBy(sublinks); foreach (var item in groupbylinks) { var subcommonparent = DomService.FindParent(item); bool SubIncludeParent = false; if (!subcommonparent.isEqualNode(CommonParent) && subcommonparent.depth < CommonParent.depth) { SubIncludeParent = true; } Menu subsubmenu = ConvertToMenu(item, subcommonparent, SubIncludeParent, website); submenu.AddSubMenu(subsubmenu); } } } menu.AddSubMenu(submenu); } string menuitemsstring = CommonParent.ownerDocument.HtmlSource.Substring(menu.tempdata.StartIndex, menu.tempdata.EndIndex - menu.tempdata.StartIndex + 1); if (IncludeParentInTemplate) { string tempTemplate = CommonParent.OuterHtml; menu.Template = tempTemplate.Replace(menuitemsstring, "{items}"); if (CommonParent.location.openTokenStartIndex < menu.tempdata.StartIndex) { menu.tempdata.StartIndex = CommonParent.location.openTokenStartIndex; } if (CommonParent.location.endTokenEndIndex > menu.tempdata.EndIndex) { menu.tempdata.EndIndex = CommonParent.location.endTokenEndIndex; } } else { menu.Template = "{items}"; } return(menu); }
/// <summary> /// Convert one link item with its parent element into one menu item... /// example: Li, a, website..... Convert the a under li tag into one mentu.... /// </summary> /// <param name="parentElement"></param> /// <param name="linkElement"></param> /// <param name="website"></param> /// <returns></returns> public static Menu ConvertToMenu(Element parentElement, Element linkElement, WebSite website) { Menu menu = new Menu(); string template = parentElement.OuterHtml; string anchortext = linkElement.InnerHtml; string href = linkElement.getAttribute("href"); template = template.Replace(linkElement.OuterHtml, ConvertToTemplate(linkElement, href, anchortext)); menu.Template = template; menu.Name = anchortext; menu.Url = href; // Check if there is a submenu.... var alllinks = parentElement.getElementsByTagName("a").item; if (alllinks.Count > 1) { /// there is sub menu... List <Element> sublinks = new List <Element>(); string mainhref = linkElement.getAttribute("href"); foreach (var item in alllinks) { string subhref = item.getAttribute("href"); if (subhref != mainhref) { sublinks.Add(item); } } if (sublinks.Count() > 0) { int SubGroupStartIndex; int SubGroupEndIndex; var groupby = GroupBy(sublinks); if (groupby.Count == 1) { var submenulinks = groupby[0]; SubGroupStartIndex = submenulinks.First().location.openTokenStartIndex; SubGroupEndIndex = submenulinks.Last().location.endTokenEndIndex; var subcommonparent = DomService.FindParent(submenulinks); bool includeparent = true; if (subcommonparent.isEqualNode(linkElement) || subcommonparent.isEqualNode(parentElement)) { includeparent = false; } var submenu = ConvertToMenu(submenulinks, subcommonparent, includeparent, website); if (submenu.tempdata.EndIndex > SubGroupEndIndex) { SubGroupEndIndex = submenu.tempdata.EndIndex; } if (submenu.tempdata.StartIndex < SubGroupStartIndex) { SubGroupStartIndex = submenu.tempdata.StartIndex; } menu.SubItemContainer = submenu.Template; // menu.SubItemSeperator = submenu.SubItemSeperator; menu.children = submenu.children; } else { SubGroupStartIndex = groupby.First().First().location.openTokenStartIndex; SubGroupEndIndex = groupby.Last().Last().location.endTokenEndIndex; foreach (var item in groupby) { var commonparent = DomService.FindParent(item); bool includeparentintemplate = false; if (!commonparent.isEqualNode(parentElement) && commonparent.depth > parentElement.depth) { includeparentintemplate = true; } var submenu = ConvertToMenu(item, commonparent, includeparentintemplate, website); // menu.Template = menu.Template.Replace(submenu.tempdata.TempOriginalText, placeholder); if (submenu.tempdata.EndIndex > SubGroupEndIndex) { SubGroupEndIndex = submenu.tempdata.EndIndex; } if (submenu.tempdata.StartIndex < SubGroupStartIndex) { SubGroupStartIndex = submenu.tempdata.StartIndex; } menu.AddSubMenu(submenu); } // try to find the seperator.... List <Element> parents = new List <Element>(); parents.Add(groupby[0].Last()); parents.Add(groupby[1].First()); //var seperatorparent = FindCommonParent(parents); //var seperator = FindSeperator(parents, seperatorparent); //if (!string.IsNullOrEmpty(seperator)) //{ // menu.SubItemSeperator = seperator; //} } string subgrouptext = parentElement.ownerDocument.HtmlSource.Substring(SubGroupStartIndex, SubGroupEndIndex - SubGroupStartIndex + 1); menu.Template = menu.Template.Replace(subgrouptext, "{items}"); } } return(menu); }
public static Menu CreateMenu(Document doc, MenuViewModel MenuViewModel) { Menu menu = new Menu(); Element LinkElement = null; Element ItemContainer = null; Element ContainerElement = null; int MenuTemplateStart = int.MaxValue; int MenuTemplaetEnd = 0; if (!string.IsNullOrEmpty(MenuViewModel.LinkElement) && !string.IsNullOrEmpty(MenuViewModel.ContainerElement)) { var linkelement = DomService.GetElementByKoobooId(doc, MenuViewModel.LinkElement); if (linkelement != null) { LinkElement = linkelement as Element; } var container = DomService.GetElementByKoobooId(doc, MenuViewModel.ContainerElement); if (container == null && linkelement != null) { container = linkelement; } if (container != null) { ContainerElement = container as Element; MenuTemplateStart = ContainerElement.location.openTokenStartIndex; MenuTemplaetEnd = ContainerElement.location.endTokenEndIndex; } } string SubMenuItemsTemplate = null; string SubMenuItemOrginalString = null; int SubMenuStart = int.MaxValue; int SubMenuEnd = 0; if (MenuViewModel.children.Count > 0) { List <Menu> SubMenus = new List <Menu>(); foreach (var item in MenuViewModel.children) { Menu submenu = CreateMenu(doc, item); if (submenu != null) { SubMenus.Add(submenu); if (submenu.tempdata.StartIndex < SubMenuStart) { SubMenuStart = submenu.tempdata.StartIndex; } if (submenu.tempdata.EndIndex > SubMenuEnd) { SubMenuEnd = submenu.tempdata.EndIndex; } } } ItemContainer = _GetItemContainer(doc, MenuViewModel); string SubMenuString = doc.HtmlSource.Substring(SubMenuStart, SubMenuEnd - SubMenuStart + 1); if (ItemContainer != null) { // 1, sub item within the link element... if (ContainerElement == null || DomService.ContainsOrEqualElement(ContainerElement, ItemContainer)) { SubMenuItemOrginalString = ItemContainer.OuterHtml; SubMenuItemsTemplate = SubMenuItemOrginalString.Replace(SubMenuString, MenuHelper.MarkSubItems); } else if (ContainerElement.isEqualNode(ItemContainer)) { SubMenuItemOrginalString = SubMenuString; SubMenuItemsTemplate = MenuHelper.MarkSubItems; } else { var distance = DomService.GetTreeDistance(ContainerElement, ItemContainer); bool sibling = false; if (distance == 1) { sibling = true; } else if (distance < 5) { var nodes = DomService.GetNodesInBetween(doc, ContainerElement, ItemContainer); if (nodes == null || nodes.Count == 0 || IsPossibleSeperator(nodes)) { sibling = true; } } if (sibling) { if (MenuTemplateStart > ItemContainer.location.openTokenStartIndex) { MenuTemplateStart = ItemContainer.location.openTokenStartIndex; } if (MenuTemplaetEnd < ItemContainer.location.endTokenEndIndex) { MenuTemplaetEnd = ItemContainer.location.endTokenEndIndex; } SubMenuItemOrginalString = ItemContainer.OuterHtml; SubMenuItemsTemplate = SubMenuItemOrginalString.Replace(SubMenuString, MenuHelper.MarkSubItems); } else { //menu.RenderSubMenuSeperated = true; SubMenuItemOrginalString = ItemContainer.OuterHtml; SubMenuItemsTemplate = ItemContainer.OuterHtml.Replace(SubMenuString, MenuHelper.MarkSubItems); } } } if (SubMenus.Count > 0) { menu.children.AddRange(SubMenus); } } if (MenuTemplateStart > 0 && MenuTemplaetEnd > 0) { string menutemplate = doc.HtmlSource.Substring(MenuTemplateStart, MenuTemplaetEnd - MenuTemplateStart + 1); if (!string.IsNullOrEmpty(SubMenuItemOrginalString)) { menutemplate = menutemplate.Replace(SubMenuItemOrginalString, MenuHelper.MarkSubItems); } string OriginalLink = LinkElement.OuterHtml; string NewLInk = DomService.ReplaceLink(LinkElement, MenuHelper.MarkHref, MenuHelper.MarkAnchorText); menutemplate = menutemplate.Replace(OriginalLink, NewLInk); menu.Template = menutemplate; menu.Name = MenuViewModel.text; menu.Url = MenuViewModel.href; } menu.SubItemContainer = SubMenuItemsTemplate; menu.tempdata.StartIndex = MenuTemplateStart; menu.tempdata.EndIndex = MenuTemplaetEnd; if (menu.tempdata.StartIndex == 0 || menu.tempdata.EndIndex == 0) { if (ItemContainer != null) { menu.tempdata.StartIndex = ItemContainer.location.openTokenStartIndex; menu.tempdata.EndIndex = ItemContainer.location.endTokenEndIndex; } } return(menu); }