private IList <(string Name, string Book, string Location)> ExtractAffiliations(Node root) { string lastLink = null; var list = new List <(string, string, string)>(); void PushLastLink(string b, string l) { if (lastLink != null) { list.Add((lastLink, b, l)); lastLink = null; } } foreach (var node in root.EnumDescendants()) { if (node is WikiLink link) { PushLastLink(null, null); lastLink = link.Target.ToString().Trim(); } else if (node is Template template && MwParserUtility.NormalizeTitle(template.Name) == "R") { if (lastLink != null) { var b = template.Arguments[1].ToString().Trim(); var l = template.Arguments[2]?.ToString().Trim(); PushLastLink(b, l); } } } return(list); }
public static bool IsTemplateTitle(string title) { if (title == null) { throw new ArgumentNullException(nameof(title)); } Debug.Assert(title == MwParserUtility.NormalizeTitle(title)); return(title.StartsWith("Template:")); }
public SignatureHelp GetSignatureHelp(Position position, PageInfoStore store) { var node = TraceNode(position); Node lastNode = null; while (node != null) { switch (node) { case Template template: var templateName = MwParserUtility.NormalizeTitle(template.Name); if (string.IsNullOrEmpty(templateName)) { return(null); } // i.e. redirect target var redirectSource = store.TryGetTransclusionPageInfo(templateName); if (redirectSource == null) { return(null); } var templateInfo = store.ResolveRedirectTarget(redirectSource); if (templateInfo == null) { templateInfo = redirectSource; redirectSource = null; } var help = new SignatureHelp { Signatures = new[] { templateInfo.ToSignatureInformation(redirectSource) }, ActiveSignature = 0, ActiveParameter = -1, }; if (lastNode is TemplateArgument arg) { // Magic Words are always positional, while it can fake "named arguments" if (templateInfo.Type == PageType.MagicWord) { var pos = template.Arguments.IndexOf(arg); help.ActiveParameter = pos; } else { var argName = arg.ArgumentName(); help.ActiveParameter = templateInfo.Arguments.IndexOf(p => p.Name == argName); } } return(help); case WikiLink wikiLink: return(null); } lastNode = node; node = node.ParentNode; } return(null); }
public void TestTemplate1() { var root = ParseAndAssert( "{{disambig}}\nTest may refer to\n* Test and experiment.\n* The River Test.\n", "P[{{disambig}}\nTest may refer to]*[ Test and experiment.]*[ The River Test.]P[]"); var dab = root.EnumDescendants().OfType <Template>() .First(t => MwParserUtility.NormalizeTitle(t.Name) == "Disambig"); Assert.Empty(dab.Arguments); }
private static string WikiTitleMd(Node node) { var text = node?.ToPlainText(); if (string.IsNullOrEmpty(text)) { return("…"); } return(EscapeMd(MwParserUtility.NormalizeTitle(node))); }
GetCompletionItems(Position position, PageInfoStore store) { var innermostNode = TraceNode(position); var innermostPlainText = innermostNode as PlainText; var node = innermostNode; Node lastNode = null; // ... when the innermostPlainText is also the first node of all parent nodes var isSimpleIdentifier = innermostPlainText != null; var lastNodeIsSimpleIdentifier = isSimpleIdentifier; // Trace the node from innermost to outermost. while (node != null) { lastNodeIsSimpleIdentifier = isSimpleIdentifier; isSimpleIdentifier = isSimpleIdentifier && (node is PlainText || lastNode.PreviousNode == null); switch (node) { case Template template: if (lastNodeIsSimpleIdentifier && lastNode == template.Name) { var enteredName = MwParserUtility.NormalizeTitle(GetTypedLhsText(innermostPlainText, position)); return(store.GetTransclusionCompletionItems(enteredName), true); } return(null, false); case TemplateArgument argument: // Do not show auto-completion for obvious argument values. if (lastNodeIsSimpleIdentifier && ( lastNode == argument.Name || // | abc$ = def argument.Name == null && lastNode == argument.Value // Anonymous argument, or unfinished argument name )) { var template = (Template)argument.ParentNode; var templateInfo = store.TryGetTransclusionPageInfo(MwParserUtility.NormalizeTitle(template.Name)); return(templateInfo.Arguments .Select(a => new CompletionItem(a.Name, CompletionItemKind.Property, a.Summary, a.Name + "=")), false); } return(null, false); case WikiLink wikiLink: if (lastNodeIsSimpleIdentifier && lastNode == wikiLink.Target) { var enteredName = MwParserUtility.NormalizeTitle(GetTypedLhsText(innermostPlainText, position)); return(store.GetWikiLinkCompletionItems(enteredName), true); } return(null, false); } lastNode = node; node = node.ParentNode; } return(null, false); }
public void TemplateArgumentsTest2() { var root = ParseWikitext("{{\ttest_T |A=1|B=2| c\n=3}}"); var t = root.EnumDescendants().OfType <Template>().First(); var arg2 = t.Arguments.ElementAt(2); Assert.Equal("Test T", MwParserUtility.NormalizeTitle(t.Name)); Assert.Equal("c", MwParserUtility.NormalizeTemplateArgumentName(arg2.Name)); t.Arguments["B"].Remove(); Assert.Equal(2, t.Arguments.Count); Assert.Equal(arg2, t.Arguments.ElementAt(1)); }
public void TestTemplate2() { var root = ParseAndAssert( "{{Translating|[[:en:Test]]|\ntpercent=20}}\n{{T|Translating|source|3=tpercent=percentage of completion}}", "P[{{Translating|P[[[:en:Test]]]|P[\ntpercent]=P[20]}}\n{{T|P[Translating]|P[source]|P[3]=P[tpercent=percentage of completion]}}]"); var trans = root.EnumDescendants().OfType <Template>() .First(t => MwParserUtility.NormalizeTitle(t.Name) == "Translating"); Assert.Equal(2, trans.Arguments.Count); Assert.Equal("[[:en:Test]]", trans.Arguments[1].Value.ToString()); Assert.Equal("20", trans.Arguments[" tpercent "].Value.ToString()); }
static async Task WorkAsync(IAsyncEnumerable <WikiPage> pages) { const string templateName = "WbClientLite/SiteLinks"; var parser = new WikitextParser(); var counter = 0; using (var ie = pages.GetEnumerator()) { while (await ie.MoveNext()) { var page = ie.Current; counter++; Console.Write("{0}: {1} ", counter, page); var root = parser.Parse(page.Content); if (root.EnumDescendants().OfType <Template>().Any(t => MwParserUtility.NormalizeTitle(t.Name) == templateName)) { Console.WriteLine("Skipped"); continue; } var langLinks = root.EnumDescendants().OfType <WikiLink>().Where(l => { var wl = WikiClientLibrary.WikiLink.Parse(page.Site, l.Target.ToString()); return(wl.InterwikiPrefix != null); }).ToList(); // Remove old language links. foreach (var link in langLinks) { if (link.PreviousNode is PlainText pt1 && string.IsNullOrWhiteSpace(pt1.Content)) { pt1.Remove(); } if (link.NextNode is PlainText pt2 && string.IsNullOrWhiteSpace(pt2.Content)) { pt2.Remove(); } var parent = link.ParentNode; link.Remove(); if (!parent.EnumChildren().Any()) { parent.Remove(); } } // Insert new template. root.Lines.Add(new Paragraph(new PlainText("\n"), new Template(new Run(new PlainText(templateName))))); page.Content = root.ToString(); await page.UpdateContentAsync("使用CrystalPool提供的语言链接。", true, true); Console.WriteLine("Done"); } } }
/// <summary> /// Expands Abc as in {{Abc}} to Template:Abc. /// </summary> public static string ExpandTransclusionTitle(string title) { if (title == null) { throw new ArgumentNullException(nameof(title)); } Debug.Assert(title == MwParserUtility.NormalizeTitle(title)); if (title.StartsWith(":")) { return(title.Substring(1)); } if (!title.Contains(':')) { return("Template:" + title); } // Something like {{Test:abcd}}, here we treat it as is with namespace name return(title); }
public static string EntityFromZhSiteLink(string link) { var query = CreateQuery(@" SELECT ?item { ?link schema:isPartOf <https://warriors.huijiwiki.com/>; schema:about ?item; schema:name @title. }"); query.SetLiteral("title", MwParserUtility.NormalizeTitle(link), "zh"); var result = ExecuteQuery(query); var uri = ((IUriNode)result.FirstOrDefault()?.Value("item"))?.Uri; if (uri == null) { return(null); } return(StripEntityUri(uri)); }
private void CheckNode(Template template, DiagnosticEmitter e) { if (((IWikitextParsingInfo)template).InferredClosingMark) { e.TransclusionNotClosed(template.ToRange(), MwParserUtility.NormalizeTitle(template.Name)); } if (string.IsNullOrWhiteSpace(template.Name?.ToString())) { e.EmptyTransclusionTarget(template.ToRange()); } var names = new HashSet <string>(); foreach (var p in template.Arguments.EnumNameArgumentPairs()) { if (!names.Add(p.Key)) { e.DuplicateTemplateArgument(p.Value.ToRange(), p.Key, MwParserUtility.NormalizeTitle(template.Name)); } } }
public IEnumerable <string> FactsFromPage(WikiPage page) { var root = wikiParser.Parse(page.Content); var infoboxCat = root.EnumDescendants().OfType <Template>() .FirstOrDefault(t => MwParserUtility.NormalizeTitle(t.Name) == "Charcat"); if (infoboxCat == null) { Console.WriteLine("No {{Charcat}} found."); yield return("% No {{Charcat}} found."); yield break; } var atom = AtomExpr(page.Title.Trim()); yield return($"name({atom}, \"{StripDabTitle(page.Title)}\")."); switch (EnWikiHelper.IsTom(root)) { case true: yield return($"male({atom})."); break; case false: yield return($"female({atom})."); break; default: break; } var affie = infoboxCat.Arguments["affie"]; if (affie != null) { foreach (var aff in affie.EnumDescendants().OfType <WikiLink>()) { yield return($"belongsto({atom}, {AtomExpr(aff.Target.ToPlainText().Trim())})."); } } var familyt = infoboxCat.Arguments["familyt"]; var familyl = infoboxCat.Arguments["familyl"]; if (familyt != null && familyl != null) { var familyDict = EnWikiHelper.ParseFamily(familyt.Value, familyl.Value); familyDict.TryGetValue("mother", out var mothers); familyDict.TryGetValue("father", out var fathers); var mother = mothers?.FirstOrDefault(); var father = fathers?.FirstOrDefault(); if (mother != null || father != null) { Debug.Assert(mothers == null || mothers.Count <= 1); Debug.Assert(fathers == null || fathers.Count <= 1); yield return($"child({atom}, {AtomExpr(father ?? "x")}, {AtomExpr(mother ?? "x")})."); } else { yield return("% No parent found."); } } else { Console.WriteLine("No familyt/familyl."); yield return("% No {{Charcat |familyl= |familyt= }} found."); } var apps = infoboxCat.Arguments["mentor"]; if (apps != null) { foreach (var appr in apps.EnumDescendants().OfType <WikiLink>()) { yield return($"apprentice({atom}, {AtomExpr(appr.Target.ToPlainText().Trim())})."); } } }
public void NormalizeTitleTest1() { Assert.AreEqual("Test", MwParserUtility.NormalizeTitle(" \r\ntest\r\n ")); Assert.AreEqual("Test test", MwParserUtility.NormalizeTitle(" \r\ntest test _ ")); }
// TODO Apply patch to MwParserFromScratch. public static string NormalizeTitle(Node title) { return(MwParserUtility.NormalizeTitle(title).Trim()); }
public static IEnumerable <Template> TemplatesWithTitle(this IEnumerable <Node> nodes, string name) { return(nodes.OfType <Template>().Where(t => MwParserUtility.NormalizeTitle(t.Name) == name)); }
/// <summary> /// Infers linked/transcluded pages information, and stores it into global store. /// </summary> public int InferTemplateInformation(PageInfoStore store) { if (store == null) { throw new ArgumentNullException(nameof(store)); } // template, argument var dict = new Dictionary <string, Dictionary <string, TemplateArgumentInfo> >(); foreach (var template in _Root.EnumDescendants().OfType <Template>()) { if (template.IsMagicWord) { continue; } var name = template.Name?.ToString(); if (string.IsNullOrEmpty(name)) { continue; } name = MwParserUtility.NormalizeTitle(name); if (name.Contains('{') || name.Contains('}')) { continue; } name = Utility.ExpandTransclusionTitle(name); // Start to infer it. if (!dict.TryGetValue(name, out var parameters)) { if (store.ContainsPageInfo(name)) { continue; } parameters = new Dictionary <string, TemplateArgumentInfo>(); dict.Add(name, parameters); } foreach (var p in template.Arguments.EnumNameArgumentPairs()) { if (parameters.ContainsKey(p.Key)) { continue; } // TODO: Insert documentation here. parameters.Add(p.Key, new TemplateArgumentInfo(p.Key, null)); } } foreach (var p in dict) { var isTemplate = Utility.IsTemplateTitle(p.Key); string transclusionName; if (isTemplate) { Debug.Assert(p.Key.StartsWith("Template:")); transclusionName = p.Key.Substring(9); } else { transclusionName = ":" + p.Key; } store.UpdatePageInfo(new PageInfo(p.Key, transclusionName, null, Prompts.InferredPageInfo, p.Value.OrderBy(p1 => p1.Key, TemplateArgumentNameComparer.Default) .Select(p1 => p1.Value).ToArray(), isTemplate ? PageType.Template : PageType.Page, true)); } return(dict.Count); }