public async Task <IWikiContainer <IWikiArticle> > GetContainerAsync(IWikiArticle wikiArticle, Wikitext astRoot) { var wikiData = _wikiContentFactory.CreateWikiData(astRoot.ToPlainText(), ContentModel.WikiText); // Create the root of WikiComponent tree. var articleContainer = _wikiComponentFactory.CreateArticleContainer(wikiData, wikiArticle, astRoot, astRoot); var firstChild = astRoot.Lines.FirstNode; // Compose WikiComponent tree. var rootChildren = await _astTranslator.TranslateNodesAsync(firstChild); if (rootChildren.Any()) { articleContainer.AddChildren(rootChildren); } else { _logger.LogWarning("AST translator returned empty list of article descendants."); } return(articleContainer); }
// RULE: One component has one node or multiple nodes that are adjacent siblings, one node belongs to zero or one component. public bool ParseNode(Node startNode, out PatternMatchComponent?outMatchComponent) { PatternMatch?match = null; if (startNode is Template template) { match = RunPatternEnumeration( _templateSpecifications.Select( pattern => pattern.Expression(template))); } //else if (startNode is InlineNode inlineNode) //{ // match = RunPatternEnumeration( // _inlinePatterns.Select( // pattern => pattern(inlineNode))); //} //else //{ // match = RunPatternEnumeration( // _patterns.Select( // pattern => pattern(startNode))); //} if (match == null) { outMatchComponent = null; return(false); } // We have a match here, create component. if (match.WikiComponentType == WikiComponentType.Image) { // TODO: Must figure out lazy loading of data like images here. // Probably change the T IWikiContainer.Content member to something like T LoadContentAsync(). // Then the container will load the content itself when asked to, which means it will need an instance of IArchive and IIdProvider. // So maybe create a service to wrap all that and pass it to the IWikiContainerFactory? throw new NotImplementedException(); } var rawDataSb = new StringBuilder(); Node exportNode = startNode; // TODO: This way, raw data of nested components will overlap. Is that OK? Shall there be a config for this? while (true) { rawDataSb.Append(exportNode.ToPlainText()); if (exportNode == match.EndNode) { break; } else { // Assuming that there is a non-null node behind one that was not the end node. exportNode = exportNode.NextNode; } } var rawData = _wikiContentFactory.CreateWikiData(rawDataSb.ToString(), ContentModel.WikiText); outMatchComponent = new PatternMatchComponent(match, _wikiComponentFactory.CreateComponent(rawData, match.WikiComponentType, startNode, match.EndNode)); #region Log match var startNodeString = startNode.ToString() ?? ""; var startNodeSubstring = startNodeString.Substring(0, Math.Min(50, startNodeString.Length)); _logger.LogDebug($"Found {match.WikiComponentType}.{Environment.NewLine}" + $"Starts with: {startNodeSubstring}.{Environment.NewLine}" + $"Has length of: {startNodeString.Length}.{Environment.NewLine}" + $"Has hash: {startNodeString.GetHashCode()}"); #endregion return(true); }