import { Node as ProseNode , Mark as ProseMark } from "prosemirror-model" ; import * as Uni from "unist" ; import * as Md from "@common/markdown/markdown-ast" ; import { Processor } from "unified" ; import { ProseMapper , ProseMarkMap , ProseMarkTest , ProseNodeMap } from "@common/extensions/editor-config" ; /**
 * Creates a single Unist `Node` of the given `type`
 * with the specified children.  Performs no validation.
 */ export const nodeMapDefault = ( type ) => ( node , children ) : Uni . Node [ ] => { return [ { type : type , children : children } ] ; } ; /**
 * Ignores the input node/children and creates an empty Unist
 * `Node` of the specified type, with no children and no content.
 */ export const nodeMapEmpty = ( type ) => ( node , children ) : Uni . Node [ ] => { return [ { type : type } ] ; } ; /**
 * Used to "unwrap" text nodes.  Expects `children` to contain a
 * single Unist `Literal`, whose `value` will be used to create
 * a new `Literal` node of the desired type.
 */ export const nodeMapLiftLiteral = ( type ) => ( node , children ) : Uni . Node [ ] => { if ( children . length !== 1 ) { throw new Error ( `[prose2mdast] expected exactly one child, found ${ children . length }` ) ; } if ( children [ 0 ] . children !== undefined ) { throw new Error ( "[prose2mdast] expected leaf literal node" ) ; } if ( ! children [ 0 ] . value ) { throw new Error ( "[prose2mdast] expected non-empty literal node" ) ; } return [ { type : type , value : children [ 0 ] . value || "" } ] ; } ; /**
 * Wraps the given Unist `node` in a Unist Node representing the ProseMirror `mark`.
 */ export const markMapDefault = ( type ) => ( mark , node ) : Uni . Node => { return { type : type , children : [ node ] } ; } ; /**
 * Used for ProseMirror marks which should be rendered as childless
 * Unist `Literal` nodes.
 */ export const markMapLiteral = ( type ) => ( mark , node ) : Uni . Node => { if ( node . value === undefined ) { throw new Error ( `[prose2mdast] expected Unist.Literal node when wrapping with mark '${ mark . type . name }'` ) ; } return { type : type , value : ( node . value as string ) || "" } ; } ; export type MdSerializer = ( doc : ProseNode ) => string ; /**
 * Uses the given configuration to create a serializer capable of converting
 * ProseMirror documents to markdown strings.
 */ export const makeSerializer = ( prose2mdast , mdProcessor ) : MdSerializer => { return ( doc ) : string => { let result = proseTreeMap ( doc , prose2mdast ) ; if ( result . length > 1 ) { throw new Error ( "multiple top-level nodes" ) ; } if ( result . length == 0 ) { throw new Error ( "empty document" ) ; } let ast = result [ 0 ] ; console . log ( "\n-----------\nPROSE2MDAST\n-----------\n" ) ; console . log ( JSON . stringify ( ast , undefined , 2 ) ) ; console . log ( "\n-----------\n" ) ; return mdProcessor . stringify ( ast ) ; } ; } ; export function proseTreeMap < Ctx = void , St = void > ( node , prose2mdast ) { if ( node . isText && node . type . name === "text" ) { let textNode = { type : "text" , value : node . text || "" } ; let markedNode = textNode ; for ( let idx = 0 ; idx < node . marks . length ; idx ++ ) { let mark = node . marks [ idx ] ; let markHandler = prose2mdast . marks . get ( mark . type . name ) . find ( handler => ! handler . test || handler . test ( mark ) ) ; if ( ! markHandler ) { console . error ( `proseTreeMap :: handler for mark type ${ mark . type . name } not found ; node=` , node ) ; continue ; } markedNode = markHandler . map ( mark , markedNode ) ; } return [ markedNode ] ; } let nodeContents = [ ] ; if ( ! node . isText && node . childCount > 0 ) { for ( let idx = 0 ; idx < node . childCount ; idx ++ ) { let child = proseTreeMap ( node . child ( idx ) , prose2mdast ) ; if ( child !== null ) { nodeContents = nodeContents . concat ( child ) ; } } } let nodeFn = null ; for ( let test of prose2mdast . nodes . get ( node . type . name ) ) { if ( ! test . test || test . test ( node ) ) { nodeFn = test . map ; } } if ( ! nodeFn ) { console . error ( "proseTreeMap :: missing handler for node" , node ) ; throw new Error ( `proseTreeMap :: handler for node type ${ node . type . name } not found` ) ; } let result = nodeFn ( node , nodeContents , { } as Ctx , { } as St ) ; return result ; }