import { HTMLText } from '@hugsmidjan/regulations-editor/types' ; import { Regulation , RegulationMaybeDiff } from '@island.is/regulations/web' ; import { NamespaceGetter } from '@island.is/web/hooks' ; import { useMemo } from 'react' ; type ItemType = 'document' | 'section' | 'chapter' | 'subchapter' | 'article' ; type IndexItem = { title : string ; id : string ; type : ItemType ; } ; type FlatIndex = Array < IndexItem > ; export type IndexTree = Array < IndexItem & { subItems ? : IndexTree ; } > ; type IndexTreeItem = IndexTree [ 0 ] ; const getSubitems = ( item ) : IndexTree => { if ( ! item . subItems ) { item . subItems = [ ] ; } return item . subItems ; } ; const levels = { document : 1 , section : 2 , chapter : 3 , subchapter : 4 , article : 5 , } as const ; const flatIndexToTree = ( flatIndex ) : IndexTree => { const tree = [ ] ; const crumbs = [ ] ; const handleItem = ( item ) : void => { const { title , id , type } = item ; const newItem = { title , id , type } ; const lastCrumb = crumbs [ crumbs . length - 1 ] ; if ( ! lastCrumb ) { tree . push ( newItem ) ; crumbs . push ( newItem ) ; return ; } const lastLevel = levels [ lastCrumb . type ] ; const currentLevel = levels [ type ] ; if ( currentLevel <= lastLevel ) { crumbs . pop ( ) ; handleItem ( item ) ; return ; } const subItems = getSubitems ( lastCrumb ) ; subItems . push ( newItem ) ; crumbs . push ( newItem ) ; return ; } ; flatIndex . forEach ( handleItem ) ; return tree ; } ; const insertIds = ( flatIndex , html , idPrefix = '' ) : HTMLText => { const DIVIDER = '__' ; const foundIds = { } ; return html . replace ( / class="(section|chapter|subchapter|article)__title"\s*>(([^<]+)(?:.[^/][^]*?)?)<\/[hH]\d/g , ( htmlSnippet , _type , longTitle , shortTitle ) => { const type = _type as ItemType ; let id = idPrefix + shortTitle . toLowerCase ( ) . replace ( /\s/g , '' ) ; if ( ! foundIds [ id ] ) { foundIds [ id ] = 1 ; } else { let count = foundIds [ id ] + 1 ; while ( foundIds [ id + DIVIDER + count ] ) count ++ ; const newId = id + DIVIDER + count ; foundIds [ id ] = count ; foundIds [ newId ] = 1 ; id = newId ; } const title = longTitle . replace ( /<[^]+?>/g , '' ) . trim ( ) ; flatIndex . push ( { title , type , id , } ) ; return ` id="${ id }" ${ htmlSnippet }` ; } ) as HTMLText ; } ; type IndexerRet < Reg extends RegulationMaybeDiff > = { index ? : IndexTree ; text : HTMLText ; appendixes : Reg [ 'appendixes' ] ; comments : HTMLText ; } ; function useRegulationIndexer < Reg extends RegulationMaybeDiff > ( regulation , txt ) { return useMemo ( ( ) => { if ( regulation . showingDiff ) { return { text : regulation . text , appendixes : regulation . appendixes , comments : regulation . comments , } ; } const flatIndex = [ ] ; if ( regulation . appendixes . length ) { flatIndex . push ( { title : txt ( 'indexItem_regulation' ) , id : '' , type : 'document' , } ) ; } const text = insertIds ( flatIndex , regulation . text ) ; const appendixes = ( regulation as Regulation ) . appendixes . map ( ( { title , text } , i ) => { const id = `v${ i + 1 }` ; flatIndex . push ( { title , id , type : 'document' , } ) ; return { title , text , } ; } ) ; if ( regulation . comments ) { flatIndex . push ( { title : txt ( 'indexItem_comments' ) , id : 'aths_ritstjora' , type : 'document' , } ) ; } const doRenderIndex = flatIndex . length > 5 ; return { text , appendixes , comments : regulation . comments , index : doRenderIndex ? flatIndexToTree ( flatIndex ) : undefined , } ; } , [ regulation ] ) ; } export { useRegulationIndexer } ;