예제 #1
0
        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);
        }
예제 #2
0
        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);
        }