private static async Task <WikiLink> ParseInternalAsync(WikiSite site, IWikiFamily family, string text, int defaultNamespaceId, bool exceptionOnFailure) { if (site == null) { throw new ArgumentNullException(nameof(site)); } if (text == null) { throw new ArgumentNullException(nameof(text)); } var link = new WikiLink(site, text); //preprocess text (these changes aren't site-dependent) //First remove anchor, which is stored unchanged, if there is one var parts = text.Split(new[] { '|' }, 2); var title = parts[0]; link.Anchor = parts.Length > 1 ? parts[1] : null; //This code was adapted from Title.php : secureAndSplit() if (title.IndexOf('\ufffd') >= 0) { if (exceptionOnFailure) { throw new ArgumentException("Title contains illegal char (\\uFFFD 'REPLACEMENT CHARACTER')", nameof(text)); } return(null); } parts = title.Split(new[] { '#' }, 2); title = parts[0]; link.Section = parts.Length > 1 ? parts[1] : null; var match = IllegalTitlesPattern.Match(title); if (match.Success) { if (exceptionOnFailure) { throw new ArgumentException($"Title contains illegal char sequence: {match.Value} ."); } return(null); } //Parse title parts. var parsedTitle = await TitlePartitionAsync(site, family, title, defaultNamespaceId); link.InterwikiPrefix = parsedTitle.Item1; link.NamespaceName = parsedTitle.Item2; link.Title = parsedTitle.Item3; link.FullTitle = link.Title; if (link.InterwikiPrefix == null) { link.TargetSite = link.Site; } else if (family != null) { link.TargetSite = await family.GetSiteAsync(link.InterwikiPrefix); Debug.Assert(link.TargetSite != null); } else { // If we do not have wiki family information, and there IS an interwiki prefix, // subsequent namespace will not be parsed and will be left as a part of Name Debug.Assert(parsedTitle.Item2 == null); } link.Namespace = parsedTitle.Item2 == null ? null : link.TargetSite.Namespaces[parsedTitle.Item2]; //Format expression. var sb = new StringBuilder(); if (link.InterwikiPrefix != null) { sb.Append(link.InterwikiPrefix); sb.Append(':'); } if (!string.IsNullOrEmpty(link.NamespaceName)) { sb.Append(link.NamespaceName); sb.Append(':'); link.FullTitle = link.NamespaceName + ":" + link.Title; } sb.Append(link.Title); if (link.Section != null) { sb.Append('#'); sb.Append(link.Section); } if (link.Anchor != null) { sb.Append('|'); sb.Append(link.Anchor); } link._FormattedText = sb.ToString(); return(link); }
private static async Task <WikiLink> ParseInternalAsync(WikiSite site, IWikiFamily family, string text, int defaultNamespaceId, bool exceptionOnFailure) { if (site == null && family == null) { throw new ArgumentNullException(nameof(site) + "/" + nameof(family)); } if (text == null) { throw new ArgumentNullException(nameof(text)); } //preprocess text (these changes aren't site-dependent) //First remove anchor, which is stored unchanged, if there is one var pipePos = text.IndexOf('|'); var title = pipePos >= 0 ? text.Substring(0, pipePos) : text; var anchor = pipePos >= 0 ? text.Substring(pipePos + 1) : null; //This code was adapted from Title.php : secureAndSplit() if (title.IndexOf('\ufffd') >= 0) { if (exceptionOnFailure) { throw new ArgumentException(string.Format(Prompts.ExceptionTitleIllegalCharacter1, "\uFFFD 'REPLACEMENT CHARACTER'"), nameof(text)); } return(null); } var hashPos = title.IndexOf('#'); var section = hashPos >= 0 ? title.Substring(hashPos + 1) : null; title = hashPos >= 0 ? title.Substring(0, hashPos) : title; var match = IllegalTitlesPattern.Match(title); if (match.Success) { if (exceptionOnFailure) { throw new ArgumentException(string.Format(Prompts.ExceptionTitleIllegalCharacterSequence1, match.Value)); } return(null); } //Parse title parts. var parsedTitle = await TitlePartitionAsync(site, family, title, defaultNamespaceId); if (parsedTitle == null) { if (exceptionOnFailure) { throw new ArgumentException(string.Format(Prompts.ExceptionTitleIsEmpty1, title)); } return(null); } var targetSite = parsedTitle.Item1; var interwikiPrefix = parsedTitle.Item2; var nsPrefix = parsedTitle.Item3; var localTitle = parsedTitle.Item4; if (targetSite == null) { if (interwikiPrefix == null) { // No interwiki prefix // This means we are parsing WikiLink without originating WikiSite. Debug.Assert(site == null); if (exceptionOnFailure) { throw new ArgumentException(Prompts.ExceptionWikiLinkRequireInterwikiPrefix, nameof(text)); } return(null); } // If we do not have wiki family information, and there IS an interwiki prefix, // subsequent namespace will not be parsed and will be left as a part of Name Debug.Assert(nsPrefix == null); Debug.Assert(localTitle != null); } var link = new WikiLink(site, text) { Anchor = anchor, Section = section, InterwikiPrefix = interwikiPrefix, NamespaceName = nsPrefix, Title = localTitle, FullTitle = localTitle, TargetSite = targetSite }; link.Namespace = nsPrefix != null && link.TargetSite != null ? link.TargetSite.Namespaces[nsPrefix] : null; //Format expression. var sb = new StringBuilder(); if (link.InterwikiPrefix != null) { sb.Append(link.InterwikiPrefix); sb.Append(':'); } var fullTitleStartsAt = sb.Length; if (!string.IsNullOrEmpty(link.NamespaceName)) { sb.Append(link.NamespaceName); sb.Append(':'); link.FullTitle = link.NamespaceName + ":" + link.Title; } sb.Append(link.Title); if (link.Section != null) { sb.Append('#'); sb.Append(link.Section); } link.Target = sb.ToString(); link.FullTitleAndSection = fullTitleStartsAt == 0 ? link.Target : sb.ToString(fullTitleStartsAt, sb.Length - fullTitleStartsAt); if (link.Anchor != null) { sb.Append('|'); sb.Append(link.Anchor); } link._FormattedText = sb.ToString(); return(link); }