@@ -924,6 +924,84 @@ export const paragraphizeTextlintAstObject = (
924924 return { nodes : collected , nextIndex : i } ;
925925 } ;
926926
927+ const splitParagraphTermlist = ( paraNode : AstNode ) : Content [ ] => {
928+ if ( ! hasChildren ( paraNode ) ) return [ ] ;
929+ const isBlankStr = ( c : Content ) : boolean =>
930+ c . type === ASTNodeTypes . Str && c . raw ?. trim ( ) === "" ;
931+ const isTermItem = ( c : Content ) : boolean =>
932+ isAstNode ( c ) && isTypstType ( c . type , / ^ M a r k e d : : T e r m I t e m $ / ) ;
933+ const createParagraph = ( nodes : Content [ ] ) : Content => {
934+ const first = nodes [ 0 ] ;
935+ const last = nodes [ nodes . length - 1 ] ;
936+ return {
937+ type : ASTNodeTypes . Paragraph ,
938+ children : nodes ,
939+ loc : { start : first . loc . start , end : last . loc . end } ,
940+ range : [ first . range [ 0 ] , last . range [ 1 ] ] ,
941+ raw : nodes . map ( ( c ) => c . raw ) . join ( "" ) ,
942+ } as Content ;
943+ } ;
944+
945+ const segments : { isTerm : boolean ; nodes : Content [ ] } [ ] = [ ] ;
946+ let current : { isTerm : boolean ; nodes : Content [ ] } | null = null ;
947+ for ( const child of paraNode . children ) {
948+ if ( isBlankStr ( child ) ) {
949+ continue ;
950+ }
951+ const isTerm = isTermItem ( child ) ;
952+ if ( ! current || current . isTerm !== isTerm ) {
953+ if ( current ) segments . push ( current ) ;
954+ current = { isTerm, nodes : [ child ] } ;
955+ } else {
956+ current . nodes . push ( child ) ;
957+ }
958+ }
959+ if ( current ) segments . push ( current ) ;
960+
961+ const results : Content [ ] = [ ] ;
962+ for ( const seg of segments ) {
963+ if ( seg . isTerm ) {
964+ results . push ( ...seg . nodes ) ;
965+ continue ;
966+ }
967+
968+ const nodes = seg . nodes . flatMap ( flattenTypstMarkupChildren ) ;
969+ if ( nodes . length === 0 ) continue ;
970+ results . push ( createParagraph ( nodes ) ) ;
971+ }
972+ return results ;
973+ } ;
974+
975+ const collectConsecutiveRootTermItems = (
976+ arr : Content [ ] ,
977+ startIndex : number ,
978+ ) : { termItems : Content [ ] ; nextIndex : number } => {
979+ const termItems : Content [ ] = [ ] ;
980+ let i = startIndex ;
981+ while ( i < arr . length ) {
982+ const currentNode = arr [ i ] ;
983+ if (
984+ isAstNode ( currentNode ) &&
985+ isTypstType ( currentNode . type , / ^ M a r k e d : : T e r m I t e m $ / )
986+ ) {
987+ termItems . push ( currentNode ) ;
988+ i ++ ;
989+ continue ;
990+ }
991+ if ( currentNode . type === ASTNodeTypes . Str && currentNode . raw === "\n" ) {
992+ if (
993+ i + 1 < arr . length &&
994+ isAstNode ( arr [ i + 1 ] ) &&
995+ isTypstType ( arr [ i + 1 ] . type , / ^ M a r k e d : : T e r m I t e m $ / )
996+ ) {
997+ i ++ ;
998+ continue ;
999+ }
1000+ }
1001+ break ;
1002+ }
1003+ return { termItems, nextIndex : i } ;
1004+ } ;
9271005 const sourceChildren = rootNode . children ;
9281006
9291007 const children : Content [ ] = [ ] ;
@@ -939,6 +1017,16 @@ export const paragraphizeTextlintAstObject = (
9391017
9401018 const node = sourceChildren [ i ] ;
9411019
1020+ if ( isAstNode ( node ) && isTypstType ( node . type , / ^ M a r k e d : : T e r m I t e m $ / ) ) {
1021+ const { termItems, nextIndex } = collectConsecutiveRootTermItems (
1022+ sourceChildren ,
1023+ i ,
1024+ ) ;
1025+ children . push ( ...termItems ) ;
1026+ i = nextIndex ;
1027+ continue ;
1028+ }
1029+
9421030 // Collect consecutive ListItems into a single List node.
9431031 if ( node . type === ASTNodeTypes . ListItem ) {
9441032 const listItems : Content [ ] = [ node ] ;
@@ -1144,7 +1232,6 @@ export const paragraphizeTextlintAstObject = (
11441232 paragraph . push ( node ) ;
11451233 i ++ ;
11461234
1147- // Collect consecutive nodes for paragraph grouping.
11481235 while ( i < sourceChildren . length ) {
11491236 const currentNode = sourceChildren [ i ] ;
11501237
@@ -1164,23 +1251,48 @@ export const paragraphizeTextlintAstObject = (
11641251 if ( paragraph . length > 0 ) {
11651252 const headNode = paragraph [ 0 ] ;
11661253 const lastNode = paragraph [ paragraph . length - 1 ] ;
1167-
1168- // Special handling for hash symbols.
11691254 if (
11701255 [ "Kw::Hash" , "Fn::(Hash: "#")" ] . includes ( headNode . type )
11711256 ) {
11721257 children . push ( ...paragraph ) ;
11731258 } else {
1174- children . push ( {
1175- loc : {
1176- start : headNode . loc . start ,
1177- end : lastNode . loc . end ,
1178- } ,
1179- range : [ headNode . range [ 0 ] , lastNode . range [ 1 ] ] ,
1180- raw : paragraph . map ( ( node ) => node . raw ) . join ( "" ) ,
1181- type : ASTNodeTypes . Paragraph ,
1182- children : paragraph ,
1183- } as Content ) ;
1259+ const isTermItem = ( c : Content ) : boolean =>
1260+ isAstNode ( c ) && isTypstType ( c . type , / ^ M a r k e d : : T e r m I t e m $ / ) ;
1261+ const createParagraph = ( nodes : Content [ ] ) : Content => {
1262+ const first = nodes [ 0 ] ;
1263+ const last = nodes [ nodes . length - 1 ] ;
1264+ return {
1265+ type : ASTNodeTypes . Paragraph ,
1266+ children : nodes ,
1267+ loc : { start : first . loc . start , end : last . loc . end } ,
1268+ range : [ first . range [ 0 ] , last . range [ 1 ] ] ,
1269+ raw : nodes . map ( ( n ) => n . raw ) . join ( "" ) ,
1270+ } as Content ;
1271+ } ;
1272+ const innerParagraphWithTerms : AstNode | undefined = ( ( ) => {
1273+ if ( paragraph . length !== 1 ) return undefined ;
1274+ const only = paragraph [ 0 ] ;
1275+ if ( only . type !== ASTNodeTypes . Paragraph ) return undefined ;
1276+ if ( ! isAstNode ( only ) || ! hasChildren ( only ) ) return undefined ;
1277+ if ( ! only . children . some ( isTermItem ) ) return undefined ;
1278+ return only ;
1279+ } ) ( ) ;
1280+ if ( innerParagraphWithTerms ) {
1281+ children . push ( ...splitParagraphTermlist ( innerParagraphWithTerms ) ) ;
1282+ continue ;
1283+ }
1284+ if ( paragraph . some ( isTermItem ) ) {
1285+ const paraNode : AstNode = {
1286+ type : ASTNodeTypes . Paragraph ,
1287+ children : paragraph as Content [ ] ,
1288+ loc : { start : headNode . loc . start , end : lastNode . loc . end } ,
1289+ range : [ headNode . range [ 0 ] , lastNode . range [ 1 ] ] ,
1290+ raw : paragraph . map ( ( p : Content ) => p . raw ) . join ( "" ) ,
1291+ } ;
1292+ children . push ( ...splitParagraphTermlist ( paraNode ) ) ;
1293+ continue ;
1294+ }
1295+ children . push ( createParagraph ( paragraph ) ) ;
11841296 }
11851297 }
11861298 }
0 commit comments