import { ICrossRefProvider } from "@main/plugins/crossref-plugin" ; import { IDoc , DocMeta , AstParser } from "./doctypes" ; import { IOutlineProvider , IOutlineEntry } from "@main/plugins/outline-plugin" ; import { IMetadataProvider , IMetadata } from "@main/plugins/metadata-plugin" ; import { EditorConfig } from "@common/extensions/editor-config" ; import * as Md from "@common/markdown/markdown-ast" ; import { BlockQuoteExtension , HeadingExtension , HorizontalRuleExtension , ListItemExtension , OrderedListExtension , UnorderedListExtension , CodeBlockExtension , InlineMathExtension , BlockMathExtension , ImageExtension , HardBreakExtension , ParagraphExtension , ContainerDirectiveExtension , CitationExtension , RootExtension , } from "@common/extensions/node-extensions" ; import { BoldExtension , ItalicExtension , CodeExtension , LinkExtension , WikilinkExtension , } from "@common/extensions/mark-extensions" ; import YAML from "yaml" ; import { unistPredicate , visit , visitNodeType } from "@common/markdown/unist-utils" ; import { NwtExtension } from "@common/extensions/extension" ; import { mdastTextContent } from "@common/markdown/mdast-to-string" ; let paragraphExt ; /**
 * Initialize a list of all the default Markdown syntax extensions.
 */ export function makeDefaultMarkdownExtensions ( ) { return [ new RootExtension ( ) , ( paragraphExt = new ParagraphExtension ( ) ) , new BlockQuoteExtension ( ) , new HeadingExtension ( paragraphExt ) , new HorizontalRuleExtension ( ) , new CodeBlockExtension ( ) , new OrderedListExtension ( ) , new UnorderedListExtension ( ) , new ListItemExtension ( ) , new ImageExtension ( ) , new HardBreakExtension ( ) , new InlineMathExtension ( ) , new BlockMathExtension ( ) , new ContainerDirectiveExtension ( ) , new BoldExtension ( ) , new ItalicExtension ( ) , new LinkExtension ( ) , new CodeExtension ( ) , new WikilinkExtension ( ) , new CitationExtension ( ) ] ; } todo export const defaultMarkdownConfig = new EditorConfig ( makeDefaultMarkdownExtensions ( ) , [ ] , { } ) ; export class MarkdownAst implements IDoc , ICrossRefProvider , IOutlineProvider , IMetadataProvider { private readonly _yaml : { [ key ] : string | string [ ] ; } ; param _root constructor ( private readonly _root ) { /** TODO (2021-05-30) YAML/TOML/JSON metadata should be extracted during parsing.
         * At the moment, YAML is only lifted from the doc during the mdast -> prose tree
         * transformation phase.  This function is called by workspace plugins, which work
         * with the AST directly rather than instantiating a ProseMirror document.  So,
         * we have to manually extract the metadata here.
         *
         * We shouldn't need to parse the YAML more than once in different places.  This
         * will also cause trouble when we want to pass TOML/JSON metadata, or extract
         * metadata that might be interspersed throughout the document.
         *
         * Probably, we should do a metadata collection pass on the tree as part of parsing.
         */ if ( this . _root ?. children ?. length > 0 && this . _root . children [ 0 ] . type === "yaml" ) { let parsedYaml = YAML . parse ( this . _root . children [ 0 ] . value ) ; this . _yaml = parsedYaml ; } else { this . _yaml = { } ; } } get root ( ) : Md . Root { return this . _root ; } getMeta ( ) { return this . _yaml ; } static parseAST ( serialized ) { let ast = defaultMarkdownConfig . parseAST ( serialized ) ; if ( ! ast ) { return null ; } return new MarkdownAst ( ast as Md . Root ) ; } public IS_OUTLINE_PROVIDER : true = true ; getOutline ( ) { let entries = [ ] ; visitNodeType < Md . Heading > ( this . _root , "heading" , node => { let headingText = mdastTextContent ( node ) ; entries . push ( { depth : node . depth , label : headingText , uniqueId : headingText , } ) ; } ) ; return entries ; } public IS_METADATA_PROVIDER : true = true ; getMetadata ( ) { todo return this . _yaml ; } public IS_XREF_PROVIDER : true = true ; getTagsDefined ( ) { let tags = [ ] ; let meta = this . getMeta ( ) ; if ( meta . tags_defined ) { todo let defs = meta . tags_defined ; if ( ! Array . isArray ( defs ) ) { defs = defs . split ( /\s*,\s*/g ) ; } tags = tags . concat ( defs ) ; } return tags ; } getTagsMentioned ( ) { let tags = [ ] ; let meta = this . getMeta ( ) ; if ( meta . tags ) { todo let mentioned = meta . tags ; if ( ! Array . isArray ( mentioned ) ) { mentioned = mentioned . split ( /\s*,\s*/g ) ; } tags = tags . concat ( mentioned ) ; } visit ( this . _root , node => { if ( unistPredicate < Md . Wikilink > ( node , "wikiLink" ) ) { tags . push ( node . value ) ; } else if ( unistPredicate < Md . Cite > ( node , "cite" ) ) { node . data . citeItems . forEach ( item => { tags . push ( item . key ) ; } ) ; } } ) ; return tags ; } } export const MarkdownASTParser = new AstParser ( MarkdownAst ) ;