import { Color , RedBlackTree , PageContent } from "../pageModel" ; import { SENTINEL_INDEX , inorderTreeTraversal , NodePosition , nextNode , } from "../tree/tree" ; import { StructureNode , TagType } from "./structureModel" ; export const SENTINEL_STRUCTURE = { color : Color . Black , id : "SENTINEL" , left : SENTINEL_INDEX , leftSubTreeLength : 0 , length : 0 , parent : SENTINEL_INDEX , right : SENTINEL_INDEX , tag : "" as keyof HTMLElementTagNameMap , tagType : TagType . StartEndTag , } ; param tree param index export function calculateLengthCount ( tree , index ) { if ( index === SENTINEL_INDEX ) { return 0 ; } const node = tree . nodes [ index ] ; return 1 + node . leftSubTreeLength + calculateLengthCount ( tree , node . right ) ; } param tree export function resetSentinelStructure ( tree ) { SENTINEL_STRUCTURE . color = Color . Black ; SENTINEL_STRUCTURE . id = "SENTINEL" ; SENTINEL_STRUCTURE . left = SENTINEL_INDEX ; SENTINEL_STRUCTURE . leftSubTreeLength = 0 ; SENTINEL_STRUCTURE . parent = SENTINEL_INDEX ; SENTINEL_STRUCTURE . right = SENTINEL_INDEX ; SENTINEL_STRUCTURE . tag = "" as keyof HTMLElementTagNameMap ; SENTINEL_STRUCTURE . tagType = TagType . StartEndTag ; tree . nodes [ 0 ] = SENTINEL_STRUCTURE ; } param tree param x param lengthDelta export function updateStructureTreeMetadata ( tree , x , lengthDelta ) { while ( x !== tree . root && x !== SENTINEL_INDEX ) { if ( tree . nodes [ tree . nodes [ x ] . parent ] . left === x ) { tree . nodes [ tree . nodes [ x ] . parent ] . leftSubTreeLength = tree . nodes [ tree . nodes [ x ] . parent ] . leftSubTreeLength + lengthDelta ; } x = tree . nodes [ x ] . parent ; } } param id param startIndex export function findEndNode ( tree , id , startIndex ) { const { index : indexAfterStart } = nextNode ( tree . nodes , startIndex ) ; for ( const { index , node } of inorderTreeTraversal ( tree , indexAfterStart ) ) { if ( node . id === id ) { return { index , node } ; } } return null ; } /**
 * Generates a new `id` for a `StructureNode`. This is only to be used
 * locally, and will not be synced to the Microsoft Graph.
 */ export function generateNewId ( tag ) { return `local:${ tag }:{${ Date . now ( ) }}` ; } param page param nodeIndex param newTag export function updateNodePairTag ( page , nodeIndex , newTag ) { const startNode = page . structure . nodes [ nodeIndex ] ; startNode . tag = newTag ; const endNodePosition = findEndNode ( page . structure , startNode . id , nodeIndex ) ; if ( endNodePosition ) { endNodePosition . node . tag = newTag ; } }