import * as Uni from "unist" ; export function unistPredicate < N extends Uni . Node = never > ( node , type ) { return ( node . type === type ) ; } export function unistIsParent ( node ) { return Boolean ( node . children ) ; } export function unistIsStringLiteral ( node ) { return ( typeof node . value === "string" ) ; } enum VisitorAction { /** Continue traversal as normal. */ CONTINUE = 1 , /** Do not traverse this node's children. */ SKIP = 2 , /** Stop traversal immediately. */ EXIT = 3 } /**
 * Invoked when a node (matching test, if given) is found.
 *
 * Visitors are allowed to have the following side-effects:
 *   - Visitors are free to transform `node`.
 *   - Make changes to the parent of `node` (the last of ancestors).
 *
 * Replacing node itself, if `SKIP` is not returned, still causes its descendants to be visited.

 * If adding or removing previous siblings (or next siblings, in case of reverse) of node,
 * visitor should return a new index (number) to specify the sibling to traverse after node is traversed.
 * Adding or removing next siblings of node (or previous siblings, in case of reverse)
 * is handled as expected without needing to return a new index.
 * Removing the children property of an ancestor still results in them being traversed.
 */ export type VisitorAncestors < V extends Uni . Node = Uni . Node > = ( node : V , ancestors : Array < Uni . Parent > ) => VisitorAction | void ; export type Visitor < V extends Uni . Node = Uni . Node > = ( node : V ) => VisitorAction | void ; export function visit ( tree , visitor ) { recurse ( tree ) ; param node param index function recurse ( node ) { let action = visitor ( node ) || VisitorAction . CONTINUE ; if ( action === VisitorAction . EXIT ) { return VisitorAction . EXIT ; } if ( action === VisitorAction . SKIP ) { return VisitorAction . SKIP ; } if ( ! unistIsParent ( node ) ) { return action ; } for ( let childIdx = 0 ; childIdx < node . children . length ; childIdx ++ ) { let subresult = recurse ( node . children [ childIdx ] ) ; if ( subresult === VisitorAction . EXIT ) { return VisitorAction . EXIT ; } } return action ; } } /**
 * Visit a specific type of node.
 */ export function visitNodeType < N extends Uni . Node = never > ( tree , type , visitor ) { function predicate ( node ) { return ( node . type === type ) ; } visit ( tree , node => { if ( predicate ( node ) ) { return visitor ( node ) ; } else { return VisitorAction . CONTINUE ; } } ) ; } returns export const removePositionInfo = ( tree ) : Uni . Node => { visit ( tree , node => { delete node . position ; } ) ; return tree ; } ; typedef { import ( 'vfile' ) . VFile } VFile type PositionalPoint = Pick < Uni . Point , 'line' | 'column' > ; type FullPoint = Required < Uni . Point > ; type Offset = NonNullable < Uni . Point [ 'offset' ] > ; param { string | Uint8Array | VFile } file export function location ( file ) { var value = String ( file ) ; type { Array . < number > } var indices = [ ] ; var search = /\r?\n|\r/g ; while ( search . test ( value ) ) { indices . push ( search . lastIndex ) ; } indices . push ( value . length + 1 ) ; return { toPoint , toOffset } ; param { Offset } offset returns { FullPoint } function toPoint ( offset ) { var index = - 1 ; if ( offset > - 1 && offset < indices [ indices . length - 1 ] ) { while ( ++ index < indices . length ) { if ( indices [ index ] > offset ) { return { line : index + 1 , column : offset - ( indices [ index - 1 ] || 0 ) + 1 , offset } ; } } } return { line : undefined , column : undefined , offset : undefined } ; } param { PositionalPoint } point returns { Offset } function toOffset ( point ) { var line = point && point . line ; var column = point && point . column ; type { number } var offset ; if ( typeof line === 'number' && typeof column === 'number' && ! Number . isNaN ( line ) && ! Number . isNaN ( column ) && line - 1 in indices ) { offset = ( indices [ line - 2 ] || 0 ) + column - 1 || 0 ; } return offset > - 1 && offset < indices [ indices . length - 1 ] ? offset : - 1 ; } } var search = /\r?\n|\r/g ; export function unistSource ( value , file ) { var doc = String ( file ) ; var loc = location ( file ) ; var position = ( value && value . position ) || value || { } ; var startOffset = loc . toOffset ( position . start ) ; var endOffset = loc . toOffset ( position . end ) ; var results = [ ] ; var match ; var end ; if ( startOffset === - 1 || endOffset === - 1 ) { return null ; } while ( startOffset < endOffset ) { search . lastIndex = startOffset ; match = search . exec ( doc ) ; end = match && match . index < endOffset ? match . index : endOffset ; results . push ( doc . slice ( startOffset , end ) ) ; startOffset = end ; if ( match && match . index < endOffset ) { startOffset += match [ 0 ] . length ; results . push ( match [ 0 ] ) ; } } return results . join ( '' ) ; } var own = { } . hasOwnProperty ; /**
 * Stringify one point, a position (start and end points), or a node’s
 * positional information.
 */ export function stringifyPosition ( value ) { if ( ! value || typeof value !== 'object' ) { return '' ; } if ( own . call ( value , 'position' ) || own . call ( value , 'type' ) ) { return position ( value . position ) ; } if ( own . call ( value , 'start' ) || own . call ( value , 'end' ) ) { return position ( value ) ; } if ( own . call ( value , 'line' ) || own . call ( value , 'column' ) ) { return point ( value ) ; } return '' ; } function point ( point ) { return index ( point && point . line ) + ':' + index ( point && point . column ) ; } function position ( pos ) { return point ( pos && pos . start ) + '-' + point ( pos && pos . end ) ; } function index ( value ) { return value && typeof value === 'number' ? value : 1 ; }