@unified-latex/unified-latex-util-catcode 1.7.1 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../libs/find-region.ts","../libs/regions.ts","../libs/reparse-macro-names.ts","../libs/special-regions.ts"],"sourcesContent":["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],"names":["match","visit","EXIT","SKIP"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../libs/find-region.ts","../libs/regions.ts","../libs/reparse-macro-names.ts","../libs/special-regions.ts"],"sourcesContent":["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],"names":["match","visit","EXIT","SKIP"],"mappings":"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"}
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../libs/find-region.ts","../libs/regions.ts","../libs/reparse-macro-names.ts","../libs/special-regions.ts"],"sourcesContent":["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],"names":["match"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../libs/find-region.ts","../libs/regions.ts","../libs/reparse-macro-names.ts","../libs/special-regions.ts"],"sourcesContent":["import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { Region } from \"./regions\";\n\n/**\n * Find all contiguous segments in the array that are between start and end blocks.\n * The `start` and `end` are functions that determine when a region starts and ends.\n */\nexport function findRegionInArray(\n tree: Ast.Node[],\n start: (node: Ast.Node) => boolean,\n end: (node: Ast.Node) => boolean\n): Region[] {\n const ret: Region[] = [];\n let currRegion: Region = { start: undefined as any, end: tree.length };\n for (let i = 0; i < tree.length; i++) {\n const node = tree[i];\n if (start(node)) {\n currRegion.start = i;\n }\n if (end(node)) {\n currRegion.end = i + 1;\n ret.push(currRegion);\n currRegion = { start: undefined as any, end: tree.length };\n }\n }\n\n if (currRegion.start != null) {\n // Regions don't necessarily have to encounter an `end` to end.\n ret.push(currRegion);\n }\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\n\nexport type Region = { start: number; end: number };\n\n/**\n * Given `regions`, a list of `Region`s (not necessarily ordered, possibly overlapping), return a list of in-order,\n * non-overlapping regions and a corresponding list containing a set of the original `Region`s that the new region\n * is a subset of.\n */\nexport function refineRegions(regions: Region[]): {\n regions: Region[];\n regionsContainedIn: Set<Region>[];\n} {\n const _regions = [...regions];\n _regions.sort((a, b) => a.start - b.start);\n const cutPointsSet = new Set(_regions.flatMap((r) => [r.start, r.end]));\n const cutPoints = Array.from(cutPointsSet);\n cutPoints.sort((a, b) => a - b);\n\n const retRegions: Region[] = [];\n const retRegionsContainedIn: Set<Region>[] = [];\n\n // We will be checking what regions we are completely contained in.\n // Because `_regions` is sorted by start, `seekIndex` will be incremented\n // by end, so that we don't do too much array testing.\n let seekIndex = 0;\n for (let i = 0; i < cutPoints.length - 1; i++) {\n const start = cutPoints[i];\n const end = cutPoints[i + 1];\n const region = { start, end };\n const regionContainedIn: Set<Region> = new Set();\n\n let encounteredEndPastStart = false;\n for (let j = seekIndex; j < _regions.length; j++) {\n const superRegion = _regions[j];\n if (superRegion.end >= region.start) {\n encounteredEndPastStart = true;\n }\n if (!encounteredEndPastStart && superRegion.end < region.start) {\n // In this case, the region (and all regions that came before)\n // end before the region we are testing, so we may safely skip past it\n // from here on out.\n seekIndex = j + 1;\n continue;\n }\n\n if (superRegion.start > end) {\n // Because `_regions` is sorted, we can stop here\n break;\n }\n if (\n superRegion.start <= region.start &&\n superRegion.end >= region.end\n ) {\n encounteredEndPastStart = true;\n regionContainedIn.add(superRegion);\n }\n }\n\n if (regionContainedIn.size > 0) {\n // We only count if we are contained in a subregion\n retRegions.push(region);\n retRegionsContainedIn.push(regionContainedIn);\n }\n }\n\n return { regions: retRegions, regionsContainedIn: retRegionsContainedIn };\n}\n\n/**\n * Split an array up into the disjoint regions specified by `regionRecord`.\n * Returned is a list of tuples, the first item being the key of `regionRecord` if there\n * was a corresponding region, or `null` if there was no corresponding region.\n *\n * This function assumes that the regions in `regionRecord` are disjoint and fully contained\n * within the bounds of `array`.\n */\nexport function splitByRegions<\n T,\n RegionRecord extends Record<string, Region[]>\n>(array: T[], regionsRecord: RegionRecord) {\n const ret: [keyof RegionRecord | null, T[]][] = [];\n\n const indices = [0, array.length];\n const reverseMap: Record<string, keyof RegionRecord> = {};\n for (const [key, records] of Object.entries(regionsRecord)) {\n indices.push(\n ...records.flatMap((r) => {\n reverseMap[\"\" + [r.start, r.end]] = key;\n return [r.start, r.end];\n })\n );\n }\n indices.sort((a, b) => a - b);\n\n for (let i = 0; i < indices.length - 1; i++) {\n const start = indices[i];\n const end = indices[i + 1];\n if (start === end) {\n continue;\n }\n const regionKey = reverseMap[\"\" + [start, end]];\n\n ret.push([regionKey || null, array.slice(start, end)]);\n }\n\n return ret;\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { EXIT, visit } from \"@unified-latex/unified-latex-util-visit\";\n\n/**\n * Escape a string so that it can be used to build a regular expression.\n *\n * From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n */\nfunction escapeRegExp(str: string) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"); // $& means the whole matched string\n}\n\n/**\n * Build a regular expression that matches everything up to the first non-allowed symbol.\n */\nfunction buildWordRegex(allowedSet: Set<string>): RegExp {\n // /\\p{L}/ matches all letters, including unicode letters. We join this with\n // everything allowed in our set to form a regexp like\n // /(\\p{L}|_|:)*/u\n // The `u` at the end allows unicode characters to be matched.\n const regexpStr = `^(${[\"\\\\p{L}\"]\n .concat(Array.from(allowedSet).map(escapeRegExp))\n .join(\"|\")})*`;\n return new RegExp(regexpStr, \"u\");\n}\n\n/**\n * Checks whether the array has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n): boolean {\n for (let i = 0; i < tree.length; i++) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (match.anyMacro(macro) && match.anyString(string)) {\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n if (\n allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0))\n ) {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Checks whether `tree` has a macro that could be reparsed given the `allowedTokens` but\n * do not do any reparsing. This function can be used in auto-detection schemes to determine if\n * macro names should actually be reparsed.\n */\nexport function hasReparsableMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n): boolean {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n let ret = false;\n visit(\n tree,\n (nodes) => {\n if (hasReparsableMacroNamesInArray(nodes, _allowedTokens)) {\n ret = true;\n return EXIT;\n }\n },\n { includeArrays: true, test: Array.isArray }\n );\n return ret;\n}\n\n/**\n * Reparses all macro names in the array so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name).\n */\nexport function reparseMacroNamesInArray(\n tree: Ast.Node[],\n allowedTokens: Set<string>\n) {\n const regex = buildWordRegex(allowedTokens);\n let i = 0;\n while (i < tree.length) {\n const macro = tree[i];\n const string = tree[i + 1];\n if (\n match.anyMacro(macro) &&\n // The _^ macros in math mode should not be extended no-matter what;\n // So we check to make sure that the macro we're dealing with has the default escape token.\n (macro.escapeToken == null || macro.escapeToken === \"\\\\\") &&\n match.anyString(string) &&\n // There are two options. Either the macro ends with the special character,\n // e.g. `\\@foo` or the special character starts the next string, e.g. `\\foo@`.\n (allowedTokens.has(\n macro.content.charAt(macro.content.length - 1)\n ) ||\n allowedTokens.has(string.content.charAt(0)))\n ) {\n // There might be a number somewhere in the string. If so, we should\n // break the string apart at that number\n const match = string.content.match(regex);\n const takeable = match ? match[0] : \"\";\n if (takeable.length > 0) {\n if (takeable.length === string.content.length) {\n // The whole string can be appended to the macro name\n macro.content += string.content;\n tree.splice(i + 1, 1);\n\n // Preserve the source location if available\n if (macro.position && string.position?.end) {\n macro.position.end = string.position.end;\n }\n } else {\n // Only part of the string can be appended to the macro name\n macro.content += takeable;\n string.content = string.content.slice(takeable.length);\n\n // Preserve the source location if available\n if (macro.position?.end) {\n macro.position.end.offset += takeable.length;\n macro.position.end.column += takeable.length;\n }\n if (string.position?.start) {\n string.position.start.offset += takeable.length;\n string.position.start.column += takeable.length;\n }\n }\n } else {\n i++;\n }\n } else {\n ++i;\n }\n }\n}\n\n/**\n * Reparses all macro names so that they may optionally include characters listed in `allowedTokens`.\n * This is used, for example, when parsing expl3 syntax which allows `_` to be used in a macro name (even though\n * `_` is normally stops the parsing for a macro name). Thus, a macro `\\foo_bar:Nn` would be parsed as having\n * the name `foo_bar:Nn` rather than as `foo` followed by the strings `_`, `bar`, `:`, `Nn`.\n */\nexport function reparseMacroNames(\n tree: Ast.Ast,\n allowedTokens: string | Set<string>\n) {\n if (typeof allowedTokens === \"string\") {\n allowedTokens = new Set(allowedTokens.split(\"\"));\n }\n // Recast so typescript doesn't complain\n const _allowedTokens = allowedTokens;\n for (const v of _allowedTokens) {\n if (v.length > 1) {\n throw new Error(\n `Only single characters are allowed as \\`allowedTokens\\` when reparsing macro names, not \\`${v}\\`.`\n );\n }\n }\n\n visit(\n tree,\n (nodes) => {\n reparseMacroNamesInArray(nodes, _allowedTokens);\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n","import * as Ast from \"@unified-latex/unified-latex-types\";\nimport { match } from \"@unified-latex/unified-latex-util-match\";\nimport { findRegionInArray } from \"./find-region\";\nimport { refineRegions, Region, splitByRegions } from \"./regions\";\nimport { SKIP, visit } from \"@unified-latex/unified-latex-util-visit\";\nimport { reparseMacroNames } from \"./reparse-macro-names\";\n\nconst expl3Find = {\n start: match.createMacroMatcher([\"ExplSyntaxOn\"]),\n end: match.createMacroMatcher([\"ExplSyntaxOff\"]),\n};\nconst atLetterFind = {\n start: match.createMacroMatcher([\"makeatletter\"]),\n end: match.createMacroMatcher([\"makeatother\"]),\n};\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`.\n * Returns an object containing regions where one or both syntax's apply.\n */\nexport function findExpl3AndAtLetterRegionsInArray(tree: Ast.Node[]): {\n explOnly: Region[];\n atLetterOnly: Region[];\n both: Region[];\n} {\n const expl3 = findRegionInArray(tree, expl3Find.start, expl3Find.end);\n const atLetter = findRegionInArray(\n tree,\n atLetterFind.start,\n atLetterFind.end\n );\n\n const regionMap = new Map([\n ...(expl3.map((x) => [x, \"expl\"]) as [Region, \"expl\"][]),\n ...(atLetter.map((x) => [x, \"atLetter\"]) as [Region, \"atLetter\"][]),\n ]);\n const all = refineRegions([...expl3, ...atLetter]);\n\n const ret = {\n explOnly: [] as Region[],\n atLetterOnly: [] as Region[],\n both: [] as Region[],\n };\n\n for (let i = 0; i < all.regions.length; i++) {\n const region = all.regions[i];\n const containedIn = all.regionsContainedIn[i];\n if (containedIn.size === 2) {\n ret.both.push(region);\n continue;\n }\n for (const v of containedIn.values()) {\n if (regionMap.get(v) === \"expl\") {\n ret.explOnly.push(region);\n }\n if (regionMap.get(v) === \"atLetter\") {\n ret.atLetterOnly.push(region);\n }\n }\n }\n\n // Regions of size 1 only contain the starting/stopping macro, so they should be discarded\n ret.explOnly = ret.explOnly.filter((r) => r.end - r.start > 1);\n ret.atLetterOnly = ret.atLetterOnly.filter((r) => r.end - r.start > 1);\n ret.both = ret.both.filter((r) => r.end - r.start > 1);\n\n return ret;\n}\n\nconst atLetterSet = new Set([\"@\"]);\nconst explSet = new Set([\"_\", \":\"]);\nconst bothSet = new Set([\"_\", \":\", \"@\"]);\n\n/**\n * Find regions between `\\ExplSyntaxOn...\\ExplSyntaxOff` and `\\makeatletter...\\makeatother`\n * and reparse their contents so that the relevant characters (e.g., `@`, `_`, and `:`) become\n * part of the macro names.\n */\nexport function reparseExpl3AndAtLetterRegions(tree: Ast.Ast) {\n visit(\n tree,\n {\n leave: (nodes) => {\n const regions = findExpl3AndAtLetterRegionsInArray(nodes);\n // In all likelihood, we don't need to do any reparsing, so bail early here\n const totalNumRegions =\n regions.both.length +\n regions.atLetterOnly.length +\n regions.explOnly.length;\n if (totalNumRegions === 0) {\n return;\n }\n\n const splits = splitByRegions(nodes, regions);\n const processed: typeof nodes = [];\n for (const [key, slice] of splits) {\n switch (key) {\n case null:\n processed.push(...slice);\n continue;\n case \"atLetterOnly\":\n reparseMacroNames(slice, atLetterSet);\n processed.push(...slice);\n continue;\n case \"explOnly\":\n reparseMacroNames(slice, explSet);\n processed.push(...slice);\n continue;\n case \"both\":\n reparseMacroNames(slice, bothSet);\n processed.push(...slice);\n continue;\n default:\n throw new Error(\n `Unexpected case when splitting ${key}`\n );\n }\n }\n\n nodes.length = 0;\n nodes.push(...processed);\n return SKIP;\n },\n },\n { includeArrays: true, test: Array.isArray }\n );\n}\n"],"names":["match"],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@unified-latex/unified-latex-util-catcode",
3
- "version": "1.7.1",
3
+ "version": "1.8.2",
4
4
  "description": "Tools for manipulating unified-latex ASTs",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "dependencies": {
8
- "@unified-latex/unified-latex-types": "^1.7.1",
9
- "@unified-latex/unified-latex-util-match": "^1.7.1",
10
- "@unified-latex/unified-latex-util-visit": "^1.7.1"
8
+ "@unified-latex/unified-latex-types": "^1.8.0",
9
+ "@unified-latex/unified-latex-util-match": "^1.8.0",
10
+ "@unified-latex/unified-latex-util-visit": "^1.8.2"
11
11
  },
12
12
  "repository": {
13
13
  "type": "git",