@@ -46,6 +46,10 @@ function detectEol(text) {
4646 return text . includes ( "\r\n" ) ? "\r\n" : "\n" ;
4747}
4848
49+ function stripUtf8Bom ( text ) {
50+ return String ( text ?? "" ) . replace ( / ^ \uFEFF / , "" ) ;
51+ }
52+
4953function escapeRegExp ( value ) {
5054 return value . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
5155}
@@ -571,15 +575,16 @@ export function deriveAvailableLenses(itemSummaries, workspaceConfig = { lenses:
571575}
572576
573577export function parseItemText ( text , sourcePath = "item.md" ) {
574- const eol = detectEol ( text ) ;
575- const frontmatterMatch = text . match ( / ^ - - - \r ? \n ( [ \s \S ] * ?) \r ? \n - - - \r ? \n ? / ) ;
578+ const normalizedText = stripUtf8Bom ( text ) ;
579+ const eol = detectEol ( normalizedText ) ;
580+ const frontmatterMatch = normalizedText . match ( / ^ - - - \r ? \n ( [ \s \S ] * ?) \r ? \n - - - \r ? \n ? / ) ;
576581
577582 if ( ! frontmatterMatch ) {
578583 throw new AppError ( `Missing or invalid frontmatter in ${ sourcePath } .` , 422 , "parse_error" ) ;
579584 }
580585
581586 const rawFrontmatter = frontmatterMatch [ 1 ] ;
582- const body = text . slice ( frontmatterMatch [ 0 ] . length ) ;
587+ const body = normalizedText . slice ( frontmatterMatch [ 0 ] . length ) ;
583588 const frontmatterEntries = parseFrontmatterBlock ( rawFrontmatter ) ;
584589 const frontmatter = { } ;
585590 const metadataValues = { } ;
@@ -624,7 +629,7 @@ export function parseItemText(text, sourcePath = "item.md") {
624629
625630 return {
626631 eol,
627- rawText : text ,
632+ rawText : normalizedText ,
628633 prefix,
629634 frontmatter,
630635 metadataValues,
@@ -812,7 +817,7 @@ async function readRoadmapConfig(repoRoot) {
812817 }
813818
814819 try {
815- parsedConfig = JSON . parse ( rawConfig ) ;
820+ parsedConfig = JSON . parse ( stripUtf8Bom ( rawConfig ) ) ;
816821 } catch {
817822 throw new AppError ( "roadmap.config.json must contain valid JSON." , 422 , "config_error" , buildConfigErrorDetails ( resolvedRepoRoot , configPath ) ) ;
818823 }
@@ -921,7 +926,8 @@ export async function resolveRoadmapRoot(repoRoot) {
921926}
922927
923928export function parseBoardText ( text , sourcePath = "board.md" ) {
924- const lines = text . replace ( / \r \n / g, "\n" ) . split ( "\n" ) ;
929+ const normalizedText = stripUtf8Bom ( text ) ;
930+ const lines = normalizedText . replace ( / \r \n / g, "\n" ) . split ( "\n" ) ;
925931 const groups = [ ] ;
926932 let currentGroup = null ;
927933
0 commit comments