import unist from "unist" ; import mdast from "mdast" ; import unified from "unified" ; import { headingRange } from "mdast-util-heading-range" ; import * as unistUtilSelect from "unist-util-select" ; import { NoteLinkNode , noteLinkNodeType } from "./noteLinkProcessorPlugin" ; export const backlinksNodeType = "backlinksNode" ; export interface BacklinksNode extends unist . Parent { type : typeof backlinksNodeType ; children : BacklinkSourceNode [ ] ; } interface BacklinkSourceNode extends unist . Parent { type : "backlinkSourceNode" ; sourceNodeLink : NoteLinkNode ; children : mdast . BlockContent [ ] ; } export default function backlinksPlugin ( this ) { return extractBacklinksBlock ; } function getBacklinkSourceNodes ( listNode ) { return listNode . children . map ( ( listItem ) => { const sourceReference = listItem . children [ 0 ] as mdast . Paragraph ; if ( ! sourceReference || sourceReference . type !== "paragraph" ) { throw new Error ( `Unexpected backlinks source node: ${ JSON . stringify ( sourceReference ) } ${ JSON . stringify ( listItem ) }` ) ; } const sourceNodeLink = unistUtilSelect . select ( noteLinkNodeType , sourceReference ) as NoteLinkNode ; if ( ! sourceNodeLink ) { throw new Error ( `Couldn't find source node link ${ JSON . stringify ( sourceReference ) } ${ JSON . stringify ( listItem ) }` ) ; } const excerptList = listItem . children [ 1 ] as mdast . List | undefined ; if ( excerptList && excerptList . type !== "list" ) { throw new Error ( `Unexpected backlinks excerpt list node: ${ JSON . stringify ( excerptList ) } ${ JSON . stringify ( listItem ) }` ) ; } const excerpts = excerptList ? excerptList . children . map ( ( excerptListItem ) => { if ( excerptListItem . type !== "listItem" ) { throw new Error ( `Unexpected backlinks excerpt list item: ${ JSON . stringify ( excerptListItem , null , "\t" ) }
              
Inside backlinks node: ${ JSON . stringify ( listItem , null , "\t" ) }` ) ; } if ( excerptListItem . children . length > 1 ) { throw new Error ( `Backlinks excerpt list item has too many children: ${ JSON . stringify ( excerptListItem , null , "\t" ) }
              
Inside backlinks node: ${ JSON . stringify ( listItem , null , "\t" ) }` ) ; } return excerptListItem . children [ 0 ] as mdast . BlockContent ; } ) : [ ] ; const backlinkSourceNode = { type : "backlinkSourceNode" , sourceNodeLink , children : excerpts , } ; return backlinkSourceNode ; } ) ; } function extractBacklinksBlock ( node ) { headingRange ( node , "Backlinks" , ( start , nodes , end , { parent , start : startIndex , end : endIndex } ) => { if ( ! parent ) { return nodes ; } const listNode = nodes [ 0 ] as mdast . List ; const defaultResult = parent . children . slice ( startIndex , endIndex ?? undefined ) ; if ( ! listNode || listNode . type !== "list" ) { console . warn ( `Unexpected node in backlinks node:` , listNode ) ; return defaultResult ; } const remainingNodes = nodes . slice ( 1 ) ; const nonCommentNodes = remainingNodes . filter ( ( n ) => n . type !== "html" || ! ( n as mdast . HTML ) . value . startsWith ( "<!--" ) ) ; if ( nonCommentNodes . length > 0 ) { console . warn ( `Unexpected nodes in backlinks node: ${ JSON . stringify ( nonCommentNodes , null , "\t" ) }` ) ; return defaultResult ; } try { const sourceNodes = getBacklinkSourceNodes ( listNode ) ; return [ { type : backlinksNodeType , children : sourceNodes , } as BacklinksNode , ... remainingNodes , ... ( end ? [ end ] : [ ] ) , ] ; } catch ( error ) { console . warn ( error ) ; return defaultResult ; } } ) ; return node ; }