@dev-pi2pie/word-counter 0.1.4 → 0.1.5-canary.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.
@@ -1 +1 @@
1
- {"version":3,"file":"count-worker.mjs","names":["wordCounter","wordCounter"],"sources":["../../../src/markdown/toml/arrays.ts","../../../src/markdown/toml/keys.ts","../../../src/markdown/toml/strings.ts","../../../src/markdown/toml/values.ts","../../../src/markdown/toml/parse-frontmatter.ts","../../../src/markdown/parse-markdown.ts","../../../src/wc/segmenter.ts","../../../src/utils/append-all.ts","../../../src/wc/non-words.ts","../../../src/wc/analyze.ts","../../../src/wc/mode.ts","../../../src/wc/latin-hints.ts","../../../src/wc/locale-detect.ts","../../../src/wc/segment.ts","../../../src/wc/wc.ts","../../../src/wc/index.ts","../../../src/markdown/section-count.ts","../../../src/cli/batch/aggregate.ts","../../../src/cli/path/load.ts","../../../src/cli/batch/jobs/worker/count-worker.ts"],"sourcesContent":["export function ensureArrayContainer(\n result: Record<string, unknown>,\n key: string,\n): Record<string, unknown>[] {\n const existing = result[key];\n if (Array.isArray(existing)) {\n return existing as Record<string, unknown>[];\n }\n const list: Record<string, unknown>[] = [];\n result[key] = list;\n return list;\n}\n\nexport function flattenArrayTables(result: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(result)) {\n if (!Array.isArray(value)) {\n continue;\n }\n const flattened = value\n .map((entry) =>\n Object.entries(entry)\n .map(([entryKey, entryValue]) => `${entryKey}=${entryValue}`)\n .join(\", \"),\n )\n .join(\" | \");\n result[key] = flattened;\n }\n}\n","function stripKeyQuotes(key: string): string {\n const trimmed = key.trim();\n if (\n (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nexport function normalizeKeyPath(key: string): string | null {\n const trimmed = key.trim();\n if (!trimmed) {\n return null;\n }\n\n if (\n (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n const unquoted = stripKeyQuotes(trimmed);\n return unquoted ? unquoted : null;\n }\n\n const segments = trimmed.split(\".\").map((segment) => segment.trim());\n if (segments.some((segment) => !segment)) {\n return null;\n }\n return segments.join(\".\");\n}\n","export function stripInlineComment(line: string): string {\n let inString: \"single\" | \"double\" | null = null;\n let escaped = false;\n\n for (let i = 0; i < line.length; i += 1) {\n const char = line[i] ?? \"\";\n\n if (inString) {\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\" && inString === \"double\") {\n escaped = true;\n continue;\n }\n\n if (inString === \"double\" && char === \"\\\"\") {\n inString = null;\n continue;\n }\n\n if (inString === \"single\" && char === \"'\") {\n inString = null;\n continue;\n }\n\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = \"double\";\n continue;\n }\n\n if (char === \"'\") {\n inString = \"single\";\n continue;\n }\n\n if (char === \"#\") {\n return line.slice(0, i).trimEnd();\n }\n }\n\n return line;\n}\n\nfunction unescapeBasic(input: string): string {\n return input\n .replace(/\\\\\\\\/g, \"\\\\\")\n .replace(/\\\\\"/g, \"\\\"\")\n .replace(/\\\\n/g, \"\\n\")\n .replace(/\\\\t/g, \"\\t\")\n .replace(/\\\\r/g, \"\\r\");\n}\n\nexport function parseStringLiteral(value: string): string | null {\n if (value.startsWith('\"\"\"') && value.endsWith('\"\"\"')) {\n const inner = value.slice(3, -3);\n return unescapeBasic(inner);\n }\n\n if (value.startsWith(\"'''\") && value.endsWith(\"'''\")) {\n return value.slice(3, -3);\n }\n\n if (value.startsWith(\"\\\"\") && value.endsWith(\"\\\"\")) {\n return unescapeBasic(value.slice(1, -1));\n }\n\n if (value.startsWith(\"'\") && value.endsWith(\"'\")) {\n return value.slice(1, -1);\n }\n\n return null;\n}\n","import { normalizeKeyPath } from \"./keys\";\nimport { parseStringLiteral } from \"./strings\";\nimport type { TomlValue } from \"./types\";\n\nfunction parsePrimitive(raw: string): string | number | boolean | null {\n const value = raw.trim();\n if (!value) {\n return null;\n }\n\n const stringLiteral = parseStringLiteral(value);\n if (stringLiteral !== null) {\n return stringLiteral;\n }\n\n if (value === \"true\") {\n return true;\n }\n\n if (value === \"false\") {\n return false;\n }\n\n if (/^[+-]?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(value)) {\n return Number(value);\n }\n\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n return value;\n }\n\n return value;\n}\n\nfunction parseArray(raw: string): Array<string | number | boolean> | null {\n const value = raw.trim();\n if (!value.startsWith(\"[\") || !value.endsWith(\"]\")) {\n return null;\n }\n\n const inner = value.slice(1, -1).trim();\n if (!inner) {\n return [];\n }\n\n const items: Array<string | number | boolean> = [];\n let current = \"\";\n let inString: \"single\" | \"double\" | null = null;\n let escaped = false;\n\n for (let i = 0; i < inner.length; i += 1) {\n const char = inner[i] ?? \"\";\n\n if (inString) {\n current += char;\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\" && inString === \"double\") {\n escaped = true;\n continue;\n }\n\n if (inString === \"double\" && char === \"\\\"\") {\n inString = null;\n } else if (inString === \"single\" && char === \"'\") {\n inString = null;\n }\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = \"double\";\n current += char;\n continue;\n }\n\n if (char === \"'\") {\n inString = \"single\";\n current += char;\n continue;\n }\n\n if (char === \",\") {\n const item = parsePrimitive(current);\n if (item === null) {\n return null;\n }\n items.push(item);\n current = \"\";\n continue;\n }\n\n current += char;\n }\n\n const finalItem = parsePrimitive(current);\n if (finalItem === null) {\n return null;\n }\n items.push(finalItem);\n\n return items;\n}\n\nfunction parseInlineTable(raw: string): Record<string, TomlValue> | null {\n const trimmed = raw.trim();\n if (!trimmed.startsWith(\"{\") || !trimmed.endsWith(\"}\")) {\n return null;\n }\n\n const inner = trimmed.slice(1, -1).trim();\n if (!inner) {\n return {};\n }\n\n const pairs: string[] = [];\n let current = \"\";\n let inString: \"single\" | \"double\" | null = null;\n let escaped = false;\n let bracketDepth = 0;\n let braceDepth = 0;\n\n for (let i = 0; i < inner.length; i += 1) {\n const char = inner[i] ?? \"\";\n\n if (inString) {\n current += char;\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\" && inString === \"double\") {\n escaped = true;\n continue;\n }\n\n if (inString === \"double\" && char === \"\\\"\") {\n inString = null;\n } else if (inString === \"single\" && char === \"'\") {\n inString = null;\n }\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = \"double\";\n current += char;\n continue;\n }\n\n if (char === \"'\") {\n inString = \"single\";\n current += char;\n continue;\n }\n\n if (char === \"[\") {\n bracketDepth += 1;\n current += char;\n continue;\n }\n\n if (char === \"]\") {\n if (bracketDepth > 0) {\n bracketDepth -= 1;\n }\n current += char;\n continue;\n }\n\n if (char === \"{\") {\n braceDepth += 1;\n current += char;\n continue;\n }\n\n if (char === \"}\") {\n if (braceDepth > 0) {\n braceDepth -= 1;\n }\n current += char;\n continue;\n }\n\n if (char === \",\" && bracketDepth === 0 && braceDepth === 0) {\n pairs.push(current);\n current = \"\";\n continue;\n }\n\n current += char;\n }\n\n if (current.trim()) {\n pairs.push(current);\n }\n\n const output: Record<string, TomlValue> = {};\n for (const pair of pairs) {\n const separatorIndex = pair.indexOf(\"=\");\n if (separatorIndex === -1) {\n return null;\n }\n const key = normalizeKeyPath(pair.slice(0, separatorIndex));\n if (!key) {\n return null;\n }\n const valueRaw = pair.slice(separatorIndex + 1).trim();\n if (!valueRaw) {\n return null;\n }\n if (valueRaw.startsWith(\"{\")) {\n return null;\n }\n const normalized = normalizeValue(valueRaw);\n if (normalized === null) {\n return null;\n }\n if (typeof normalized === \"object\" && !Array.isArray(normalized)) {\n return null;\n }\n output[key] = normalized;\n }\n\n return output;\n}\n\nexport function normalizeValue(value: string): TomlValue | null {\n if (!value) {\n return null;\n }\n\n const trimmed = value.trim();\n if (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) {\n return parseInlineTable(trimmed);\n }\n\n const array = parseArray(trimmed);\n if (array) {\n return array;\n }\n\n if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n return null;\n }\n\n return parsePrimitive(trimmed);\n}\n\nexport function toPlainText(value: unknown): string {\n if (value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item)).join(\", \");\n }\n return String(value);\n}\n","import { ensureArrayContainer, flattenArrayTables } from \"./arrays\";\nimport { normalizeKeyPath } from \"./keys\";\nimport { stripInlineComment } from \"./strings\";\nimport { normalizeValue, toPlainText } from \"./values\";\n\nexport function parseTomlFrontmatter(frontmatter: string): Record<string, unknown> | null {\n const result: Record<string, unknown> = {};\n const lines = frontmatter.split(\"\\n\");\n let tablePrefix = \"\";\n let tableTarget: Record<string, unknown> | null = null;\n let tablePrefixInList = false;\n\n for (let index = 0; index < lines.length; index += 1) {\n const rawLine = lines[index] ?? \"\";\n const trimmedLine = rawLine.trim();\n if (!trimmedLine || trimmedLine.startsWith(\"#\")) {\n continue;\n }\n\n if (trimmedLine.startsWith(\"[[\")) {\n const match = trimmedLine.match(/^\\[\\[([^\\]]+)]]$/);\n if (!match) {\n return null;\n }\n const normalizedTable = normalizeKeyPath(match[1] ?? \"\");\n if (!normalizedTable) {\n return null;\n }\n const list = ensureArrayContainer(result, normalizedTable);\n const newEntry: Record<string, unknown> = {};\n list.push(newEntry);\n tableTarget = newEntry;\n tablePrefix = normalizedTable;\n tablePrefixInList = true;\n continue;\n }\n\n const tableMatch = trimmedLine.match(/^\\[([^\\]]+)]$/);\n if (tableMatch) {\n const normalizedTable = normalizeKeyPath(tableMatch[1] ?? \"\");\n if (!normalizedTable) {\n return null;\n }\n tablePrefix = normalizedTable;\n tablePrefixInList = false;\n tableTarget = null;\n continue;\n }\n\n const lineForParsing = /(\"\"\"|''')/.test(rawLine) ? rawLine : stripInlineComment(rawLine);\n const separatorIndex = lineForParsing.indexOf(\"=\");\n if (separatorIndex === -1) {\n return null;\n }\n\n const keyRaw = lineForParsing.slice(0, separatorIndex);\n const key = normalizeKeyPath(keyRaw);\n let valueRaw = lineForParsing.slice(separatorIndex + 1).trim();\n if (!key) {\n return null;\n }\n\n const tripleDelimiter = valueRaw.startsWith('\"\"\"') ? '\"\"\"' : valueRaw.startsWith(\"'''\") ? \"'''\" : null;\n if (tripleDelimiter) {\n const closingIndex = valueRaw.indexOf(tripleDelimiter, tripleDelimiter.length);\n if (closingIndex !== -1) {\n const after = valueRaw.slice(closingIndex + tripleDelimiter.length);\n const strippedAfter = stripInlineComment(after);\n valueRaw = `${valueRaw.slice(0, closingIndex + tripleDelimiter.length)}${strippedAfter}`;\n } else {\n const delimiter = tripleDelimiter;\n let combined = valueRaw;\n let closed = false;\n while (index + 1 < lines.length) {\n index += 1;\n const nextLine = lines[index] ?? \"\";\n combined += `\\n${nextLine}`;\n if (new RegExp(`${delimiter}\\\\s*$`).test(nextLine)) {\n closed = true;\n break;\n }\n }\n if (!closed) {\n return null;\n }\n valueRaw = combined;\n }\n }\n\n const normalized = normalizeValue(valueRaw);\n if (normalized === null) {\n return null;\n }\n\n const fullKey = tablePrefix ? `${tablePrefix}.${key}` : key;\n if (typeof normalized === \"object\" && !Array.isArray(normalized)) {\n for (const [inlineKey, inlineValue] of Object.entries(normalized)) {\n const entryKey = tablePrefixInList ? `${key}.${inlineKey}` : `${fullKey}.${inlineKey}`;\n if (tablePrefixInList && tableTarget) {\n tableTarget[entryKey] = toPlainText(inlineValue);\n } else {\n result[entryKey] = toPlainText(inlineValue);\n }\n }\n continue;\n }\n\n if (tablePrefixInList && tableTarget) {\n tableTarget[key] = toPlainText(normalized);\n continue;\n }\n\n result[fullKey] = toPlainText(normalized);\n }\n\n flattenArrayTables(result);\n\n return result;\n}\n","import { parseDocument } from \"yaml\";\nimport { parseTomlFrontmatter } from \"./toml-simple\";\nimport type { FrontmatterType, ParsedMarkdown } from \"./types\";\n\nconst FENCE_TO_TYPE: Record<string, FrontmatterType> = {\n \"---\": \"yaml\",\n \"+++\": \"toml\",\n \";;;\": \"json\",\n};\n\nfunction normalizeNewlines(input: string): string {\n return input.replace(/\\r\\n/g, \"\\n\");\n}\n\nfunction stripBom(line: string): string {\n return line.startsWith(\"\\uFEFF\") ? line.slice(1) : line;\n}\n\nfunction getFenceType(line: string): FrontmatterType | null {\n const match = line.match(/^[\\t ]*(---|\\+\\+\\+|;;;)[\\t ]*$/);\n if (!match) {\n return null;\n }\n return FENCE_TO_TYPE[match[1] ?? \"\"] ?? null;\n}\n\nfunction parseFrontmatter(frontmatter: string, type: FrontmatterType | null): Record<string, unknown> | null {\n if (!type) {\n return null;\n }\n\n if (type === \"json\") {\n try {\n return JSON.parse(frontmatter) as Record<string, unknown>;\n } catch {\n return null;\n }\n }\n\n if (type === \"yaml\") {\n const doc = parseDocument(frontmatter, { prettyErrors: false });\n if (doc.errors.length > 0) {\n return null;\n }\n const data = doc.toJSON();\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n return null;\n }\n return data as Record<string, unknown>;\n }\n\n if (type === \"toml\") {\n return parseTomlFrontmatter(frontmatter);\n }\n\n return null;\n}\n\nfunction extractJsonBlock(text: string, startIndex: number): { jsonText: string; endIndex: number } | null {\n let depth = 0;\n let inString = false;\n let escaped = false;\n\n for (let i = startIndex; i < text.length; i += 1) {\n const char = text[i] ?? \"\";\n\n if (inString) {\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\") {\n escaped = true;\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = false;\n }\n\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = true;\n continue;\n }\n\n if (char === \"{\") {\n depth += 1;\n continue;\n }\n\n if (char === \"}\") {\n depth -= 1;\n if (depth === 0) {\n const jsonText = text.slice(startIndex, i + 1);\n return { jsonText, endIndex: i };\n }\n }\n }\n\n return null;\n}\n\nexport function parseMarkdown(input: string): ParsedMarkdown {\n const normalized = normalizeNewlines(input);\n const lines = normalized.split(\"\\n\");\n if (lines.length === 0) {\n return { frontmatter: null, content: normalized, data: null, frontmatterType: null };\n }\n\n lines[0] = stripBom(lines[0] ?? \"\");\n const normalizedWithoutBom = lines.join(\"\\n\");\n\n const openingType = getFenceType(lines[0] ?? \"\");\n if (!openingType) {\n const leadingWhitespace = normalizedWithoutBom.match(/^[\\t \\n]*/)?.[0] ?? \"\";\n const jsonStart = leadingWhitespace.length;\n if (normalizedWithoutBom[jsonStart] !== \"{\") {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n const jsonBlock = extractJsonBlock(normalizedWithoutBom, jsonStart);\n if (!jsonBlock) {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n const frontmatter = jsonBlock.jsonText;\n let content = normalizedWithoutBom.slice(jsonBlock.endIndex + 1);\n if (content.startsWith(\"\\n\")) {\n content = content.slice(1);\n }\n const data = parseFrontmatter(frontmatter, \"json\");\n if (!data) {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n return {\n frontmatter,\n content,\n data,\n frontmatterType: \"json\",\n };\n }\n\n let closingIndex = -1;\n for (let i = 1; i < lines.length; i += 1) {\n if (getFenceType(lines[i] ?? \"\") === openingType) {\n closingIndex = i;\n break;\n }\n }\n\n if (closingIndex === -1) {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n const frontmatter = lines.slice(1, closingIndex).join(\"\\n\");\n const content = lines.slice(closingIndex + 1).join(\"\\n\");\n const data = parseFrontmatter(frontmatter, openingType);\n\n return {\n frontmatter,\n content,\n data,\n frontmatterType: openingType,\n };\n}\n","const segmenterCache = new Map<string, Intl.Segmenter>();\nconst graphemeSegmenterCache = new Map<string, Intl.Segmenter>();\n\nexport function getSegmenter(locale: string): Intl.Segmenter {\n const cached = segmenterCache.get(locale);\n if (cached) {\n return cached;\n }\n const segmenter = new Intl.Segmenter(locale, { granularity: \"word\" });\n segmenterCache.set(locale, segmenter);\n return segmenter;\n}\n\nexport function getGraphemeSegmenter(locale: string): Intl.Segmenter {\n const cached = graphemeSegmenterCache.get(locale);\n if (cached) {\n return cached;\n }\n const segmenter = new Intl.Segmenter(locale, { granularity: \"grapheme\" });\n graphemeSegmenterCache.set(locale, segmenter);\n return segmenter;\n}\n\nfunction supportsSegmenter(): boolean {\n return typeof Intl !== \"undefined\" && typeof Intl.Segmenter === \"function\";\n}\n\nexport function countWordsForLocale(text: string, locale: string): number {\n const segmenter = getSegmenter(locale);\n let count = 0;\n for (const segment of segmenter.segment(text)) {\n if (segment.isWordLike) {\n count++;\n }\n }\n return count;\n}\n\nexport function countCharsForLocale(text: string, locale: string): number {\n if (!supportsSegmenter()) {\n return Array.from(text).length;\n }\n const segmenter = getGraphemeSegmenter(locale);\n let count = 0;\n for (const _segment of segmenter.segment(text)) {\n count++;\n }\n return count;\n}\n","export function appendAll<T>(target: T[], source: readonly T[]): void {\n for (const item of source) {\n target.push(item);\n }\n}\n","import type { NonWordCollection, WhitespaceCounts } from \"./types\";\nimport { appendAll } from \"../utils/append-all\";\n\nconst emojiRegex = /(?:\\p{Extended_Pictographic}|\\p{Emoji_Presentation})/u;\nconst emojiPresentationRegex = /\\p{Emoji_Presentation}/u;\nconst keycapEmojiRegex = /[0-9#*]\\uFE0F?\\u20E3/u;\nconst symbolRegex = /\\p{S}/u;\nconst punctuationRegex = /\\p{P}/u;\nconst whitespaceRegex = /\\s/u;\nconst newlineChars = new Set([\"\\n\", \"\\r\", \"\\u2028\", \"\\u2029\"]);\n\nexport function createNonWordCollection(): NonWordCollection {\n return {\n emoji: [],\n symbols: [],\n punctuation: [],\n counts: {\n emoji: 0,\n symbols: 0,\n punctuation: 0,\n },\n };\n}\n\nexport function addNonWord(\n collection: NonWordCollection,\n category: \"emoji\" | \"symbol\" | \"punctuation\",\n segment: string,\n): void {\n if (category === \"emoji\") {\n collection.emoji.push(segment);\n collection.counts.emoji += 1;\n return;\n }\n if (category === \"symbol\") {\n collection.symbols.push(segment);\n collection.counts.symbols += 1;\n return;\n }\n collection.punctuation.push(segment);\n collection.counts.punctuation += 1;\n}\n\nexport function addWhitespace(\n collection: NonWordCollection,\n segment: string,\n): number {\n let whitespace = collection.whitespace;\n let count = 0;\n for (const char of segment) {\n if (char === \" \") {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.spaces += 1;\n count += 1;\n continue;\n }\n if (char === \"\\t\") {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.tabs += 1;\n count += 1;\n continue;\n }\n if (newlineChars.has(char)) {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.newlines += 1;\n count += 1;\n continue;\n }\n if (whitespaceRegex.test(char)) {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.other += 1;\n count += 1;\n }\n }\n\n if (count > 0) {\n collection.whitespace = whitespace ?? createWhitespaceCounts();\n collection.counts.whitespace = (collection.counts.whitespace ?? 0) + count;\n }\n\n return count;\n}\n\nexport function classifyNonWordSegment(\n segment: string,\n): \"emoji\" | \"symbol\" | \"punctuation\" | null {\n const hasEmojiVariationSelector = segment.includes(\"\\uFE0F\");\n if (\n keycapEmojiRegex.test(segment) ||\n emojiPresentationRegex.test(segment) ||\n (hasEmojiVariationSelector && emojiRegex.test(segment))\n ) {\n return \"emoji\";\n }\n if (symbolRegex.test(segment)) {\n return \"symbol\";\n }\n if (punctuationRegex.test(segment)) {\n return \"punctuation\";\n }\n return null;\n}\n\nexport function mergeNonWordCollections(\n target: NonWordCollection,\n source: NonWordCollection,\n): NonWordCollection {\n if (source.counts.emoji > 0) {\n appendAll(target.emoji, source.emoji);\n target.counts.emoji += source.counts.emoji;\n }\n if (source.counts.symbols > 0) {\n appendAll(target.symbols, source.symbols);\n target.counts.symbols += source.counts.symbols;\n }\n if (source.counts.punctuation > 0) {\n appendAll(target.punctuation, source.punctuation);\n target.counts.punctuation += source.counts.punctuation;\n }\n if (source.counts.whitespace && source.counts.whitespace > 0 && source.whitespace) {\n const whitespace = target.whitespace ?? createWhitespaceCounts();\n whitespace.spaces += source.whitespace.spaces;\n whitespace.tabs += source.whitespace.tabs;\n whitespace.newlines += source.whitespace.newlines;\n whitespace.other += source.whitespace.other;\n target.whitespace = whitespace;\n target.counts.whitespace = (target.counts.whitespace ?? 0) + source.counts.whitespace;\n }\n return target;\n}\n\nfunction createWhitespaceCounts(): WhitespaceCounts {\n return { spaces: 0, tabs: 0, newlines: 0, other: 0 };\n}\n","import { countCharsForLocale, getSegmenter } from \"./segmenter\";\nimport {\n addNonWord,\n addWhitespace,\n classifyNonWordSegment,\n createNonWordCollection,\n mergeNonWordCollections,\n} from \"./non-words\";\nimport { appendAll } from \"../utils/append-all\";\nimport type {\n CharCollectorBreakdown,\n ChunkAnalysis,\n CollectorBreakdown,\n LocaleChunk,\n NonWordCollection,\n} from \"./types\";\n\ntype CharAnalysis = LocaleChunk & { chars: number; nonWords?: NonWordCollection };\ntype CharChunkAnalysis = CharAnalysis & { wordChars: number; nonWordChars: number };\n\nexport function analyzeChunk(\n chunk: LocaleChunk,\n collectNonWords?: boolean,\n includeWhitespace?: boolean,\n): ChunkAnalysis {\n const segmenter = getSegmenter(chunk.locale);\n const segments: string[] = [];\n const nonWords: NonWordCollection | null = collectNonWords\n ? createNonWordCollection()\n : null;\n for (const part of segmenter.segment(chunk.text)) {\n if (part.isWordLike) {\n segments.push(part.segment);\n } else if (collectNonWords && nonWords) {\n if (includeWhitespace) {\n addWhitespace(nonWords, part.segment);\n }\n const category = classifyNonWordSegment(part.segment);\n if (category) {\n addNonWord(nonWords, category, part.segment);\n }\n }\n }\n return {\n locale: chunk.locale,\n text: chunk.text,\n segments,\n words: segments.length,\n nonWords: nonWords ?? undefined,\n };\n}\n\nexport function analyzeCharChunk(\n chunk: LocaleChunk,\n collectNonWords?: boolean,\n includeWhitespace?: boolean,\n): CharChunkAnalysis {\n const segmenter = getSegmenter(chunk.locale);\n const nonWords: NonWordCollection | null = collectNonWords\n ? createNonWordCollection()\n : null;\n let chars = 0;\n let wordChars = 0;\n let nonWordChars = 0;\n\n for (const part of segmenter.segment(chunk.text)) {\n if (part.isWordLike) {\n const count = countCharsForLocale(part.segment, chunk.locale);\n chars += count;\n wordChars += count;\n continue;\n }\n\n if (collectNonWords && nonWords) {\n let whitespaceCount = 0;\n if (includeWhitespace) {\n whitespaceCount = addWhitespace(nonWords, part.segment);\n }\n const category = classifyNonWordSegment(part.segment);\n if (category) {\n addNonWord(nonWords, category, part.segment);\n }\n if (category || whitespaceCount > 0) {\n const count = countCharsForLocale(part.segment, chunk.locale);\n chars += count;\n nonWordChars += count;\n }\n }\n }\n\n return {\n locale: chunk.locale,\n text: chunk.text,\n chars,\n wordChars,\n nonWordChars,\n nonWords: nonWords ?? undefined,\n };\n}\n\nexport function aggregateCharsByLocale(\n chunks: CharChunkAnalysis[],\n): Array<CharCollectorBreakdown & { wordChars: number; nonWordChars: number }> {\n const order: string[] = [];\n const map = new Map<\n string,\n CharCollectorBreakdown & { wordChars: number; nonWordChars: number }\n >();\n\n for (const chunk of chunks) {\n const existing = map.get(chunk.locale);\n if (existing) {\n existing.chars += chunk.chars;\n existing.wordChars += chunk.wordChars;\n existing.nonWordChars += chunk.nonWordChars;\n if (chunk.nonWords) {\n if (!existing.nonWords) {\n existing.nonWords = createNonWordCollection();\n }\n mergeNonWordCollections(existing.nonWords, chunk.nonWords);\n }\n continue;\n }\n\n order.push(chunk.locale);\n map.set(chunk.locale, {\n locale: chunk.locale,\n chars: chunk.chars,\n wordChars: chunk.wordChars,\n nonWordChars: chunk.nonWordChars,\n nonWords: chunk.nonWords\n ? mergeNonWordCollections(createNonWordCollection(), chunk.nonWords)\n : undefined,\n });\n }\n\n return order.map((locale) => map.get(locale)!);\n}\n\nexport function aggregateByLocale(\n chunks: ChunkAnalysis[]\n): CollectorBreakdown[] {\n const order: string[] = [];\n const map = new Map<string, CollectorBreakdown>();\n\n for (const chunk of chunks) {\n const existing = map.get(chunk.locale);\n if (existing) {\n existing.words += chunk.words;\n appendAll(existing.segments, chunk.segments);\n continue;\n }\n\n order.push(chunk.locale);\n map.set(chunk.locale, {\n locale: chunk.locale,\n words: chunk.words,\n segments: [...chunk.segments],\n });\n }\n\n return order.map((locale) => map.get(locale)!);\n}\n","import type { WordCounterMode } from \"./types\";\n\nconst MODE_ALIASES: Record<string, WordCounterMode> = {\n chunk: \"chunk\",\n chunks: \"chunk\",\n segments: \"segments\",\n segment: \"segments\",\n seg: \"segments\",\n collector: \"collector\",\n collect: \"collector\",\n colle: \"collector\",\n char: \"char\",\n chars: \"char\",\n character: \"char\",\n characters: \"char\",\n \"char-collector\": \"char-collector\",\n};\n\nconst CHAR_MODE_ALIASES = new Set([\"char\", \"chars\", \"character\", \"characters\"]);\nconst COLLECTOR_MODE_ALIASES = new Set([\"collector\", \"collect\", \"colle\", \"col\"]);\n\nfunction collapseSeparators(value: string): string {\n return value.replace(/[-_\\s]+/g, \"\");\n}\n\nfunction isComposedCharCollectorFromTokens(value: string): boolean {\n const tokens = value\n .split(/[-_\\s]+/)\n .map((token) => token.trim())\n .filter((token) => token.length > 0);\n if (tokens.length < 2) {\n return false;\n }\n\n let hasCharAlias = false;\n let hasCollectorAlias = false;\n for (const token of tokens) {\n if (CHAR_MODE_ALIASES.has(token)) {\n hasCharAlias = true;\n continue;\n }\n if (COLLECTOR_MODE_ALIASES.has(token)) {\n hasCollectorAlias = true;\n continue;\n }\n return false;\n }\n\n return hasCharAlias && hasCollectorAlias;\n}\n\nfunction isComposedCharCollectorCompact(value: string): boolean {\n for (const charAlias of CHAR_MODE_ALIASES) {\n for (const collectorAlias of COLLECTOR_MODE_ALIASES) {\n if (value === `${charAlias}${collectorAlias}` || value === `${collectorAlias}${charAlias}`) {\n return true;\n }\n }\n }\n return false;\n}\n\nexport function normalizeMode(input?: string | null): WordCounterMode | null {\n if (!input) {\n return null;\n }\n const normalized = input.trim().toLowerCase();\n const direct = MODE_ALIASES[normalized];\n if (direct) {\n return direct;\n }\n\n if (isComposedCharCollectorFromTokens(normalized)) {\n return \"char-collector\";\n }\n\n const compact = collapseSeparators(normalized);\n if (isComposedCharCollectorCompact(compact)) {\n return \"char-collector\";\n }\n\n return MODE_ALIASES[compact] ?? null;\n}\n\nexport function resolveMode(\n input?: string | null,\n fallback: WordCounterMode = \"chunk\",\n): WordCounterMode {\n return normalizeMode(input) ?? fallback;\n}\n","import type { LatinHintRule } from \"./types\";\n\nconst DEFAULT_LATIN_HINT_RULES_SOURCE = [\n { tag: \"de\", pattern: \"[äöüÄÖÜß]\" },\n { tag: \"es\", pattern: \"[ñÑ¿¡]\" },\n { tag: \"pt\", pattern: \"[ãõÃÕ]\" },\n { tag: \"fr\", pattern: \"[œŒæÆ]\" },\n { tag: \"pl\", pattern: \"[ąćęłńśźżĄĆĘŁŃŚŹŻ]\" },\n { tag: \"tr\", pattern: \"[ıİğĞşŞ]\" },\n { tag: \"ro\", pattern: \"[ăĂâÂîÎșȘțȚ]\" },\n { tag: \"hu\", pattern: \"[őŐűŰ]\" },\n { tag: \"is\", pattern: \"[ðÐþÞ]\" },\n] satisfies LatinHintRule[];\n\nexport const DEFAULT_LATIN_HINT_RULES: ReadonlyArray<Readonly<LatinHintRule>> = Object.freeze(\n DEFAULT_LATIN_HINT_RULES_SOURCE.map((rule) => Object.freeze({ ...rule })),\n);\n","import type { LatinHintRule } from \"./types\";\nimport { DEFAULT_LATIN_HINT_RULES } from \"./latin-hints\";\n\nexport const DEFAULT_LOCALE = \"und-Latn\";\nexport const DEFAULT_HAN_TAG = \"und-Hani\";\n\nconst MAX_LATIN_HINT_PATTERN_LENGTH = 256;\n\nexport interface LocaleDetectOptions {\n latinLanguageHint?: string;\n latinTagHint?: string;\n latinLocaleHint?: string;\n latinHintRules?: LatinHintRule[];\n useDefaultLatinHints?: boolean;\n hanLanguageHint?: string;\n hanTagHint?: string;\n}\n\ntype ResolvedLatinHintRule = {\n tag: string;\n pattern: RegExp;\n priority: number;\n order: number;\n};\n\nexport type LocaleDetectContext = {\n latinHint?: string;\n hanHint?: string;\n latinHintRules: ResolvedLatinHintRule[];\n latinLocales: Set<string>;\n};\n\nconst regex = {\n hiragana: /\\p{Script=Hiragana}/u,\n katakana: /\\p{Script=Katakana}/u,\n hangul: /\\p{Script=Hangul}/u,\n han: /\\p{Script=Han}/u,\n latin: /\\p{Script=Latin}/u,\n arabic: /\\p{Script=Arabic}/u,\n cyrillic: /\\p{Script=Cyrillic}/u,\n devanagari: /\\p{Script=Devanagari}/u,\n thai: /\\p{Script=Thai}/u,\n};\n\nconst defaultLatinLocales = new Set<string>([\n DEFAULT_LOCALE,\n ...DEFAULT_LATIN_HINT_RULES.map((hint) => hint.tag),\n]);\n\nexport function isLatinLocale(locale: string, context?: LocaleDetectContext): boolean {\n if (context) {\n return context.latinLocales.has(locale);\n }\n return defaultLatinLocales.has(locale);\n}\n\nfunction resolveLatinHint(options: LocaleDetectOptions): string | undefined {\n const latinTagHint = options.latinTagHint?.trim();\n if (latinTagHint) {\n return latinTagHint;\n }\n\n const latinLanguageHint = options.latinLanguageHint?.trim();\n if (latinLanguageHint) {\n return latinLanguageHint;\n }\n\n const latinLocaleHint = options.latinLocaleHint?.trim();\n if (latinLocaleHint) {\n return latinLocaleHint;\n }\n\n return undefined;\n}\n\nfunction resolveHanHint(options: LocaleDetectOptions): string | undefined {\n const hanTagHint = options.hanTagHint?.trim();\n if (hanTagHint) {\n return hanTagHint;\n }\n\n const hanLanguageHint = options.hanLanguageHint?.trim();\n if (hanLanguageHint) {\n return hanLanguageHint;\n }\n\n return undefined;\n}\n\nfunction compileLatinHintPattern(\n pattern: string | RegExp,\n label: string,\n): RegExp {\n const source = typeof pattern === \"string\" ? pattern : pattern.source;\n const hasUnicodeMode =\n typeof pattern !== \"string\" &&\n (pattern.flags.includes(\"u\") || pattern.flags.includes(\"v\"));\n const flags =\n typeof pattern === \"string\"\n ? \"u\"\n : hasUnicodeMode\n ? pattern.flags\n : `${pattern.flags}u`;\n if (source.length === 0) {\n throw new Error(`${label}: pattern must not be empty.`);\n }\n if (source.length > MAX_LATIN_HINT_PATTERN_LENGTH) {\n throw new Error(\n `${label}: pattern must be at most ${MAX_LATIN_HINT_PATTERN_LENGTH} characters.`,\n );\n }\n try {\n return new RegExp(source, flags);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`${label}: invalid Unicode regex pattern (${message}).`);\n }\n}\n\nfunction normalizeLatinHintPriority(priority: unknown, label: string): number {\n if (priority === undefined) {\n return 0;\n }\n if (typeof priority !== \"number\" || !Number.isFinite(priority)) {\n throw new Error(`${label}: priority must be a finite number when provided.`);\n }\n return priority;\n}\n\nfunction compileLatinHintRule(\n rule: Readonly<LatinHintRule>,\n order: number,\n label: string,\n): ResolvedLatinHintRule {\n const tag = typeof rule.tag === \"string\" ? rule.tag.trim() : \"\";\n if (!tag) {\n throw new Error(`${label}: tag must be a non-empty string.`);\n }\n const pattern = compileLatinHintPattern(rule.pattern, label);\n const priority = normalizeLatinHintPriority(rule.priority, label);\n return {\n tag,\n pattern,\n priority,\n order,\n };\n}\n\nfunction resolveLatinHintRules(options: LocaleDetectOptions): ResolvedLatinHintRule[] {\n const useDefaultLatinHints = options.useDefaultLatinHints !== false;\n const customRules = options.latinHintRules ?? [];\n const combinedRules: Array<{ rule: Readonly<LatinHintRule>; label: string }> = [];\n\n for (let index = 0; index < customRules.length; index += 1) {\n const rule = customRules[index];\n if (!rule) {\n continue;\n }\n combinedRules.push({\n rule,\n label: `Invalid custom Latin hint rule at index ${index}`,\n });\n }\n\n if (useDefaultLatinHints) {\n for (let index = 0; index < DEFAULT_LATIN_HINT_RULES.length; index += 1) {\n const rule = DEFAULT_LATIN_HINT_RULES[index];\n if (!rule) {\n continue;\n }\n combinedRules.push({\n rule,\n label: `Invalid default Latin hint rule at index ${index}`,\n });\n }\n }\n\n const resolvedRules = combinedRules.map((entry, index) =>\n compileLatinHintRule(entry.rule, index, entry.label),\n );\n\n resolvedRules.sort((left, right) => {\n if (left.priority !== right.priority) {\n return right.priority - left.priority;\n }\n return left.order - right.order;\n });\n\n return resolvedRules;\n}\n\nexport function resolveLocaleDetectContext(\n options: LocaleDetectOptions = {},\n): LocaleDetectContext {\n const latinHint = resolveLatinHint(options);\n const latinHintRules = resolveLatinHintRules(options);\n const latinLocales = new Set<string>([DEFAULT_LOCALE]);\n for (const rule of latinHintRules) {\n latinLocales.add(rule.tag);\n }\n if (latinHint) {\n latinLocales.add(latinHint);\n }\n\n return {\n latinHint,\n hanHint: resolveHanHint(options),\n latinHintRules,\n latinLocales,\n };\n}\n\nfunction detectLatinLocale(char: string, context: LocaleDetectContext): string {\n for (const hint of context.latinHintRules) {\n hint.pattern.lastIndex = 0;\n if (hint.pattern.test(char)) {\n return hint.tag;\n }\n }\n return DEFAULT_LOCALE;\n}\n\nexport function detectLocaleForChar(\n char: string,\n previousLocale?: string | null,\n options: LocaleDetectOptions = {},\n context: LocaleDetectContext = resolveLocaleDetectContext(options),\n allowLatinLocaleCarry = true,\n allowJapaneseHanCarry = true,\n): string | null {\n if (regex.hiragana.test(char) || regex.katakana.test(char)) {\n return \"ja\";\n }\n if (regex.hangul.test(char)) {\n return \"ko\";\n }\n if (regex.arabic.test(char)) {\n return \"ar\";\n }\n if (regex.cyrillic.test(char)) {\n return \"ru\";\n }\n if (regex.devanagari.test(char)) {\n return \"hi\";\n }\n if (regex.thai.test(char)) {\n return \"th\";\n }\n\n if (regex.han.test(char)) {\n if (allowJapaneseHanCarry && previousLocale && previousLocale.startsWith(\"ja\")) {\n return previousLocale;\n }\n return context.hanHint ?? DEFAULT_HAN_TAG;\n }\n\n if (regex.latin.test(char)) {\n const hintedLocale = detectLatinLocale(char, context);\n if (hintedLocale !== DEFAULT_LOCALE) {\n return hintedLocale;\n }\n if (\n allowLatinLocaleCarry &&\n previousLocale &&\n isLatinLocale(previousLocale, context) &&\n previousLocale !== DEFAULT_LOCALE\n ) {\n return previousLocale;\n }\n if (context.latinHint) {\n return context.latinHint;\n }\n return DEFAULT_LOCALE;\n }\n\n return null;\n}\n","import {\n DEFAULT_LOCALE,\n detectLocaleForChar,\n isLatinLocale,\n resolveLocaleDetectContext,\n type LocaleDetectOptions,\n} from \"./locale-detect\";\nimport type { LocaleChunk } from \"./types\";\n\nconst HARD_BOUNDARY_REGEX = /[\\r\\n,.!?;:,、。!?;:.。、]/u;\nconst LATIN_PROMOTION_BREAK_REGEX = /[\\s,.!?;:,、。!?;:.。、]/u;\n\nexport function segmentTextByLocale(\n text: string,\n options: LocaleDetectOptions = {}\n): LocaleChunk[] {\n const context = resolveLocaleDetectContext(options);\n const chunks: LocaleChunk[] = [];\n // Keep currentLocale as a non-null string to simplify type-narrowing.\n let currentLocale: string = DEFAULT_LOCALE;\n let buffer = \"\";\n let bufferHasScript = false;\n let sawCarryBoundary = false;\n\n const updateCarryBoundaryState = (detected: string | null, char: string): void => {\n if (detected !== null) {\n sawCarryBoundary = false;\n return;\n }\n if (HARD_BOUNDARY_REGEX.test(char)) {\n sawCarryBoundary = true;\n }\n };\n\n for (const char of text) {\n const detected = detectLocaleForChar(\n char,\n currentLocale,\n options,\n context,\n !sawCarryBoundary,\n !sawCarryBoundary,\n );\n const targetLocale = detected ?? currentLocale;\n\n // If buffer is empty, this is the first character for a new chunk.\n if (buffer === \"\") {\n currentLocale = targetLocale;\n buffer = char;\n bufferHasScript = detected !== null;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n if (detected !== null && !bufferHasScript) {\n currentLocale = targetLocale;\n buffer += char;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n if (targetLocale !== currentLocale && detected !== null) {\n if (currentLocale === DEFAULT_LOCALE && isLatinLocale(targetLocale, context)) {\n const promotionBreakIndex = findLastLatinPromotionBreakIndex(buffer);\n if (promotionBreakIndex === -1) {\n currentLocale = targetLocale;\n buffer += char;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n const prefix = buffer.slice(0, promotionBreakIndex + 1);\n const suffix = buffer.slice(promotionBreakIndex + 1);\n if (prefix.length > 0) {\n chunks.push({ locale: currentLocale, text: prefix });\n }\n currentLocale = targetLocale;\n buffer = `${suffix}${char}`;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n // currentLocale is guaranteed to be a string here.\n chunks.push({ locale: currentLocale, text: buffer });\n currentLocale = targetLocale;\n buffer = char;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n buffer += char;\n if (detected !== null) {\n bufferHasScript = true;\n }\n updateCarryBoundaryState(detected, char);\n }\n\n if (buffer.length > 0) {\n chunks.push({ locale: currentLocale, text: buffer });\n }\n\n return mergeAdjacentChunks(chunks);\n}\n\nfunction findLastLatinPromotionBreakIndex(buffer: string): number {\n for (let index = buffer.length - 1; index >= 0; index -= 1) {\n const char = buffer[index];\n if (!char) {\n continue;\n }\n if (LATIN_PROMOTION_BREAK_REGEX.test(char)) {\n return index;\n }\n }\n return -1;\n}\n\nfunction mergeAdjacentChunks(chunks: LocaleChunk[]): LocaleChunk[] {\n if (chunks.length === 0) {\n return chunks;\n }\n\n const merged: LocaleChunk[] = [];\n // We already returned for empty arrays above, so the first element is present.\n let last = chunks[0]!;\n\n for (let i = 1; i < chunks.length; i++) {\n const chunk = chunks[i]!;\n if (chunk.locale === last.locale) {\n last = { locale: last.locale, text: last.text + chunk.text };\n } else {\n merged.push(last);\n last = chunk;\n }\n }\n\n merged.push(last);\n return merged;\n}\n","import {\n analyzeCharChunk,\n analyzeChunk,\n aggregateByLocale,\n aggregateCharsByLocale,\n} from \"./analyze\";\nimport { resolveMode } from \"./mode\";\nimport { segmentTextByLocale } from \"./segment\";\nimport { countCharsForLocale, countWordsForLocale } from \"./segmenter\";\nimport { createNonWordCollection, mergeNonWordCollections } from \"./non-words\";\nimport type {\n CharBreakdown,\n CharCollectorBreakdown,\n ChunkBreakdown,\n ChunkWithSegments,\n NonWordCollection,\n WordCounterMode,\n WordCounterOptions,\n WordCounterResult,\n} from \"./types\";\n\nexport type {\n LatinHintRule,\n NonWordCollection,\n WordCounterMode,\n WordCounterOptions,\n WordCounterResult,\n WordCounterBreakdown,\n} from \"./types\";\n\nexport { countCharsForLocale, countWordsForLocale, segmentTextByLocale };\nexport { DEFAULT_LATIN_HINT_RULES } from \"./latin-hints\";\n\nexport function wordCounter(\n text: string,\n options: WordCounterOptions = {}\n): WordCounterResult {\n const mode: WordCounterMode = resolveMode(options.mode, \"chunk\");\n const collectNonWords = Boolean(options.nonWords);\n const includeWhitespace = Boolean(options.includeWhitespace);\n const chunks = segmentTextByLocale(text, {\n latinLanguageHint: options.latinLanguageHint,\n latinTagHint: options.latinTagHint,\n latinLocaleHint: options.latinLocaleHint,\n latinHintRules: options.latinHintRules,\n useDefaultLatinHints: options.useDefaultLatinHints,\n hanLanguageHint: options.hanLanguageHint,\n hanTagHint: options.hanTagHint,\n });\n\n if (mode === \"char\" || mode === \"char-collector\") {\n const analyzed = chunks.map((chunk) =>\n analyzeCharChunk(chunk, collectNonWords, includeWhitespace),\n );\n const total = analyzed.reduce((sum, chunk) => sum + chunk.chars, 0);\n const counts = collectNonWords\n ? {\n words: analyzed.reduce((sum, chunk) => sum + chunk.wordChars, 0),\n nonWords: analyzed.reduce((sum, chunk) => sum + chunk.nonWordChars, 0),\n total,\n }\n : undefined;\n\n if (mode === \"char\") {\n const items: CharBreakdown[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n chars: chunk.chars,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n const aggregated = aggregateCharsByLocale(analyzed);\n const items: CharCollectorBreakdown[] = aggregated.map((chunk) => ({\n locale: chunk.locale,\n chars: chunk.chars,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n const analyzed = chunks.map((chunk) =>\n analyzeChunk(chunk, collectNonWords, includeWhitespace),\n );\n const wordsTotal = analyzed.reduce((sum, chunk) => sum + chunk.words, 0);\n const nonWordsTotal = collectNonWords\n ? analyzed.reduce((sum, chunk) => {\n if (!chunk.nonWords) {\n return sum;\n }\n return sum + getNonWordTotal(chunk.nonWords);\n }, 0)\n : 0;\n const total = analyzed.reduce((sum, chunk) => {\n let chunkTotal = chunk.words;\n if (collectNonWords && chunk.nonWords) {\n chunkTotal += getNonWordTotal(chunk.nonWords);\n }\n return sum + chunkTotal;\n }, 0);\n\n const counts = collectNonWords ? { words: wordsTotal, nonWords: nonWordsTotal, total } : undefined;\n\n if (mode === \"segments\") {\n const items: ChunkWithSegments[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n words: chunk.words,\n segments: chunk.segments,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n if (mode === \"collector\") {\n const items = aggregateByLocale(analyzed);\n const nonWords = collectNonWordsAggregate(analyzed, collectNonWords);\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n nonWords,\n },\n };\n }\n\n const items: ChunkBreakdown[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n words: chunk.words,\n nonWords: chunk.nonWords,\n }));\n\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n}\n\nfunction getNonWordTotal(nonWords: NonWordCollection): number {\n return (\n nonWords.counts.emoji +\n nonWords.counts.symbols +\n nonWords.counts.punctuation +\n (nonWords.counts.whitespace ?? 0)\n );\n}\n\n\nfunction collectNonWordsAggregate(\n analyzed: Array<{ nonWords?: NonWordCollection }>,\n enabled: boolean,\n): NonWordCollection | undefined {\n if (!enabled) {\n return undefined;\n }\n const collection = createNonWordCollection();\n for (const chunk of analyzed) {\n if (!chunk.nonWords) {\n continue;\n }\n mergeNonWordCollections(collection, chunk.nonWords);\n }\n return collection;\n}\n","import { wordCounter } from \"./wc\";\n\nexport default wordCounter;\nexport { countCharsForLocale, countWordsForLocale, segmentTextByLocale } from \"./wc\";\nexport { DEFAULT_LATIN_HINT_RULES } from \"./wc\";\nexport type {\n LatinHintRule,\n NonWordCollection,\n WordCounterMode,\n WordCounterOptions,\n WordCounterResult,\n WordCounterBreakdown,\n} from \"./wc\";\n","import type { WordCounterMode, WordCounterOptions, WordCounterResult } from \"../wc/types\";\nimport wordCounter from \"../wc\";\nimport { parseMarkdown } from \"./parse-markdown\";\nimport type { SectionMode, SectionedResult } from \"./types\";\n\nfunction normalizeText(value: unknown): string {\n if (value == null) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction buildPerKeyItems(\n data: Record<string, unknown> | null,\n mode: WordCounterMode,\n options: WordCounterOptions,\n): Array<{ name: string; source: \"frontmatter\"; result: WordCounterResult }> {\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n return [];\n }\n\n return Object.entries(data).map(([key, value]) => {\n const valueText = normalizeText(value);\n const text = valueText ? `${key}: ${valueText}` : key;\n return {\n name: key,\n source: \"frontmatter\",\n result: wordCounter(text, options),\n };\n });\n}\n\nfunction buildSingleItem(\n name: string,\n text: string,\n mode: WordCounterMode,\n options: WordCounterOptions,\n source: \"frontmatter\" | \"content\",\n) {\n return [{ name, source, result: wordCounter(text, options) }];\n}\n\nfunction sumTotals(items: Array<{ result: WordCounterResult }>): number {\n return items.reduce((sum, item) => sum + item.result.total, 0);\n}\n\nexport function countSections(\n input: string,\n section: SectionMode,\n options: WordCounterOptions = {},\n): SectionedResult {\n const mode: WordCounterMode = options.mode ?? \"chunk\";\n if (section === \"all\") {\n const result = wordCounter(input, options);\n return {\n section,\n total: result.total,\n frontmatterType: null,\n items: [{ name: \"all\", source: \"content\", result }],\n };\n }\n\n const parsed = parseMarkdown(input);\n const frontmatterText = parsed.frontmatter ?? \"\";\n const contentText = parsed.content ?? \"\";\n\n let items: Array<{ name: string; source: \"frontmatter\" | \"content\"; result: WordCounterResult }> = [];\n\n if (section === \"frontmatter\") {\n items = buildSingleItem(\"frontmatter\", frontmatterText, mode, options, \"frontmatter\");\n } else if (section === \"content\") {\n items = buildSingleItem(\"content\", contentText, mode, options, \"content\");\n } else if (section === \"split\") {\n items = [\n ...buildSingleItem(\"frontmatter\", frontmatterText, mode, options, \"frontmatter\"),\n ...buildSingleItem(\"content\", contentText, mode, options, \"content\"),\n ];\n } else if (section === \"per-key\") {\n items = buildPerKeyItems(parsed.data, mode, options);\n } else if (section === \"split-per-key\") {\n items = [\n ...buildPerKeyItems(parsed.data, mode, options),\n ...buildSingleItem(\"content\", contentText, mode, options, \"content\"),\n ];\n }\n\n return {\n section,\n total: sumTotals(items),\n frontmatterType: parsed.frontmatterType,\n items,\n };\n}\n","import { countSections } from \"../../markdown\";\nimport type { SectionMode, SectionedResult } from \"../../markdown\";\nimport { appendAll } from \"../../utils/append-all\";\nimport wordCounter, { type NonWordCollection, type WordCounterResult } from \"../../wc\";\nimport { createNonWordCollection, mergeNonWordCollections } from \"../../wc/non-words\";\nimport type { BatchFileInput, BatchFileResult, BatchSummary } from \"../types\";\nimport type { BatchProgressSnapshot } from \"../progress/reporter\";\n\ntype BuildBatchSummaryOptions = {\n onFileCounted?: (snapshot: BatchProgressSnapshot) => void;\n onFinalizeStart?: () => void;\n preserveCollectorSegments?: boolean;\n};\n\ntype FinalizeBatchSummaryFromFileResultsOptions = {\n onFinalizeStart?: () => void;\n preserveCollectorSegments?: boolean;\n};\n\nfunction mergeWordCounterResult(\n left: WordCounterResult,\n right: WordCounterResult,\n preserveCollectorSegments: boolean,\n): WordCounterResult {\n if (left.breakdown.mode !== right.breakdown.mode) {\n throw new Error(\"Cannot merge different breakdown modes.\");\n }\n\n const total = left.total + right.total;\n const counts =\n left.counts || right.counts\n ? {\n words: (left.counts?.words ?? 0) + (right.counts?.words ?? 0),\n nonWords: (left.counts?.nonWords ?? 0) + (right.counts?.nonWords ?? 0),\n total: (left.counts?.total ?? 0) + (right.counts?.total ?? 0),\n }\n : undefined;\n\n if (left.breakdown.mode === \"chunk\" && right.breakdown.mode === \"chunk\") {\n return {\n total,\n counts,\n breakdown: {\n mode: \"chunk\",\n items: [...left.breakdown.items, ...right.breakdown.items],\n },\n };\n }\n\n if (left.breakdown.mode === \"segments\" && right.breakdown.mode === \"segments\") {\n return {\n total,\n counts,\n breakdown: {\n mode: \"segments\",\n items: [...left.breakdown.items, ...right.breakdown.items],\n },\n };\n }\n\n if (left.breakdown.mode === \"char\" && right.breakdown.mode === \"char\") {\n return {\n total,\n counts,\n breakdown: {\n mode: \"char\",\n items: [...left.breakdown.items, ...right.breakdown.items],\n },\n };\n }\n\n if (\n left.breakdown.mode === \"char-collector\" &&\n right.breakdown.mode === \"char-collector\"\n ) {\n const localeOrder: string[] = [];\n const mergedByLocale = new Map<\n string,\n {\n locale: string;\n chars: number;\n nonWords?: NonWordCollection;\n }\n >();\n\n const addItems = (items: typeof left.breakdown.items): void => {\n for (const item of items) {\n const existing = mergedByLocale.get(item.locale);\n if (existing) {\n existing.chars += item.chars;\n if (item.nonWords) {\n if (!existing.nonWords) {\n existing.nonWords = createNonWordCollection();\n }\n mergeNonWordCollections(existing.nonWords, item.nonWords);\n }\n continue;\n }\n\n localeOrder.push(item.locale);\n mergedByLocale.set(item.locale, {\n locale: item.locale,\n chars: item.chars,\n nonWords: item.nonWords\n ? mergeNonWordCollections(createNonWordCollection(), item.nonWords)\n : undefined,\n });\n }\n };\n\n addItems(left.breakdown.items);\n addItems(right.breakdown.items);\n\n return {\n total,\n counts,\n breakdown: {\n mode: \"char-collector\",\n items: localeOrder.map((locale) => {\n const value = mergedByLocale.get(locale);\n if (!value) {\n throw new Error(`Missing char-collector entry for locale: ${locale}`);\n }\n return value;\n }),\n },\n };\n }\n\n if (left.breakdown.mode === \"collector\" && right.breakdown.mode === \"collector\") {\n const localeOrder: string[] = [];\n const mergedByLocale = new Map<\n string,\n {\n locale: string;\n words: number;\n segments: string[];\n }\n >();\n\n const addItems = (items: typeof left.breakdown.items): void => {\n for (const item of items) {\n const existing = mergedByLocale.get(item.locale);\n if (existing) {\n existing.words += item.words;\n if (preserveCollectorSegments) {\n appendAll(existing.segments, item.segments);\n }\n continue;\n }\n\n localeOrder.push(item.locale);\n mergedByLocale.set(item.locale, {\n locale: item.locale,\n words: item.words,\n segments: preserveCollectorSegments ? [...item.segments] : [],\n });\n }\n };\n\n addItems(left.breakdown.items);\n addItems(right.breakdown.items);\n\n let mergedNonWords: NonWordCollection | undefined;\n if (left.breakdown.nonWords || right.breakdown.nonWords) {\n mergedNonWords = createNonWordCollection();\n if (left.breakdown.nonWords) {\n mergeNonWordCollections(mergedNonWords, left.breakdown.nonWords);\n }\n if (right.breakdown.nonWords) {\n mergeNonWordCollections(mergedNonWords, right.breakdown.nonWords);\n }\n }\n\n return {\n total,\n counts,\n breakdown: {\n mode: \"collector\",\n items: localeOrder.map((locale) => {\n const value = mergedByLocale.get(locale);\n if (!value) {\n throw new Error(`Missing collector entry for locale: ${locale}`);\n }\n return value;\n }),\n nonWords: mergedNonWords,\n },\n };\n }\n\n return {\n total,\n counts,\n breakdown: left.breakdown,\n };\n}\n\nfunction aggregateWordCounterResults(\n results: WordCounterResult[],\n preserveCollectorSegments: boolean,\n): WordCounterResult {\n if (results.length === 0) {\n return wordCounter(\"\", { mode: \"chunk\" });\n }\n\n const first = results[0];\n if (!first) {\n return wordCounter(\"\", { mode: \"chunk\" });\n }\n\n let aggregate = first;\n for (let index = 1; index < results.length; index += 1) {\n const current = results[index];\n if (!current) {\n continue;\n }\n aggregate = mergeWordCounterResult(aggregate, current, preserveCollectorSegments);\n }\n\n return aggregate;\n}\n\nfunction buildSectionKey(name: string, source: \"frontmatter\" | \"content\"): string {\n return `${source}:${name}`;\n}\n\nfunction aggregateSectionedResults(\n results: SectionedResult[],\n preserveCollectorSegments: boolean,\n): SectionedResult {\n if (results.length === 0) {\n return {\n section: \"all\",\n total: 0,\n frontmatterType: null,\n items: [],\n };\n }\n\n const section = results[0]?.section ?? \"all\";\n const grouped = new Map<\n string,\n {\n name: string;\n source: \"frontmatter\" | \"content\";\n items: WordCounterResult[];\n }\n >();\n let total = 0;\n let frontmatterType = results[0]?.frontmatterType ?? null;\n\n for (const result of results) {\n total += result.total;\n\n if (result.section !== section) {\n throw new Error(\"Cannot aggregate section results with different section modes.\");\n }\n\n if (frontmatterType !== result.frontmatterType) {\n frontmatterType = null;\n }\n\n for (const item of result.items) {\n const key = buildSectionKey(item.name, item.source);\n const existing = grouped.get(key);\n if (!existing) {\n grouped.set(key, {\n name: item.name,\n source: item.source,\n items: [item.result],\n });\n continue;\n }\n\n existing.items.push(item.result);\n }\n }\n\n const sourceOrder = new Map<\"frontmatter\" | \"content\", number>([\n [\"frontmatter\", 0],\n [\"content\", 1],\n ]);\n\n const items = [...grouped.values()]\n .sort((left, right) => {\n const sourceDiff = (sourceOrder.get(left.source) ?? 0) - (sourceOrder.get(right.source) ?? 0);\n if (sourceDiff !== 0) {\n return sourceDiff;\n }\n return left.name.localeCompare(right.name);\n })\n .map((entry) => ({\n name: entry.name,\n source: entry.source,\n result: aggregateWordCounterResults(entry.items, preserveCollectorSegments),\n }));\n\n return {\n section,\n total,\n frontmatterType,\n items,\n };\n}\n\nfunction stripCollectorSegmentsFromWordCounterResult(result: WordCounterResult): void {\n if (result.breakdown.mode !== \"collector\") {\n return;\n }\n\n for (const item of result.breakdown.items) {\n item.segments = [];\n }\n}\n\nfunction stripCollectorSegmentsFromSectionedResult(result: SectionedResult): void {\n for (const item of result.items) {\n stripCollectorSegmentsFromWordCounterResult(item.result);\n }\n}\n\nexport function compactCollectorSegmentsInCountResult(\n result: WordCounterResult | SectionedResult,\n): void {\n if (\"section\" in result) {\n stripCollectorSegmentsFromSectionedResult(result);\n return;\n }\n\n stripCollectorSegmentsFromWordCounterResult(result);\n}\n\nexport async function buildBatchSummary(\n inputs: BatchFileInput[],\n section: SectionMode,\n wcOptions: Parameters<typeof wordCounter>[1],\n options: BuildBatchSummaryOptions = {},\n): Promise<BatchSummary> {\n const preserveCollectorSegments = options.preserveCollectorSegments ?? true;\n const files: BatchFileResult[] = [];\n\n for (const input of inputs) {\n const result =\n section === \"all\"\n ? wordCounter(input.content, wcOptions)\n : countSections(input.content, section, wcOptions);\n\n if (!preserveCollectorSegments) {\n compactCollectorSegmentsInCountResult(result);\n }\n\n files.push({\n path: input.path,\n result,\n });\n\n options.onFileCounted?.({\n completed: files.length,\n total: inputs.length,\n });\n }\n\n return finalizeBatchSummaryFromFileResults(files, section, wcOptions, {\n onFinalizeStart: options.onFinalizeStart,\n preserveCollectorSegments: options.preserveCollectorSegments,\n });\n}\n\nexport function finalizeBatchSummaryFromFileResults(\n files: BatchFileResult[],\n section: SectionMode,\n wcOptions: Parameters<typeof wordCounter>[1],\n options: FinalizeBatchSummaryFromFileResultsOptions = {},\n): BatchSummary {\n const preserveCollectorSegments = options.preserveCollectorSegments ?? true;\n if (!preserveCollectorSegments) {\n for (const file of files) {\n compactCollectorSegmentsInCountResult(file.result);\n }\n }\n\n options.onFinalizeStart?.();\n if (files.length === 0) {\n return {\n files,\n skipped: [],\n aggregate:\n section === \"all\"\n ? wordCounter(\"\", wcOptions)\n : {\n section,\n total: 0,\n frontmatterType: null,\n items: [],\n },\n };\n }\n\n const aggregate =\n section === \"all\"\n ? aggregateWordCounterResults(\n files.map((file) => file.result as WordCounterResult),\n preserveCollectorSegments,\n )\n : aggregateSectionedResults(\n files.map((file) => file.result as SectionedResult),\n preserveCollectorSegments,\n );\n\n return {\n files,\n skipped: [],\n aggregate,\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { BatchFileInput, BatchSkip } from \"../types\";\n\nexport function isProbablyBinary(buffer: Buffer): boolean {\n if (buffer.length === 0) {\n return false;\n }\n\n const sampleSize = Math.min(buffer.length, 1024);\n let suspicious = 0;\n\n for (let index = 0; index < sampleSize; index += 1) {\n const byte = buffer[index] ?? 0;\n\n if (byte === 0) {\n return true;\n }\n\n if (byte === 9 || byte === 10 || byte === 13) {\n continue;\n }\n\n if (byte >= 32 && byte <= 126) {\n continue;\n }\n\n if (byte >= 128) {\n continue;\n }\n\n suspicious += 1;\n }\n\n return suspicious / sampleSize > 0.3;\n}\n\nexport async function loadBatchInputs(\n filePaths: string[],\n): Promise<{ files: BatchFileInput[]; skipped: BatchSkip[] }> {\n const files: BatchFileInput[] = [];\n const skipped: BatchSkip[] = [];\n\n for (const filePath of filePaths) {\n let buffer: Buffer;\n try {\n buffer = await readFile(filePath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n skipped.push({ path: filePath, reason: `not readable: ${message}` });\n continue;\n }\n\n if (isProbablyBinary(buffer)) {\n skipped.push({ path: filePath, reason: \"binary file\" });\n continue;\n }\n\n files.push({\n path: filePath,\n content: buffer.toString(\"utf8\"),\n });\n }\n\n return { files, skipped };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport { countSections } from \"../../../../markdown\";\nimport wordCounter from \"../../../../wc\";\nimport { compactCollectorSegmentsInCountResult } from \"../../aggregate\";\nimport { isProbablyBinary } from \"../../../path/load\";\nimport type {\n WorkerConfig,\n WorkerRequestMessage,\n WorkerResponseMessage,\n} from \"./protocol\";\n\nconst config = workerData as WorkerConfig;\n\nif (!parentPort) {\n throw new Error(\"Worker protocol init failed: missing parentPort.\");\n}\n\nparentPort.on(\"message\", async (message: WorkerRequestMessage) => {\n if (message.type === \"shutdown\") {\n parentPort?.close();\n return;\n }\n\n const path = message.path;\n\n let buffer: Buffer;\n try {\n buffer = await readFile(path);\n } catch (error) {\n const code =\n typeof error === \"object\" && error !== null && \"code\" in error\n ? String(error.code)\n : undefined;\n const messageText = error instanceof Error ? error.message : String(error);\n\n if (code === \"EMFILE\" || code === \"ENFILE\") {\n const response: WorkerResponseMessage = {\n type: \"fatal\",\n taskId: message.taskId,\n index: message.index,\n path,\n code,\n message: messageText,\n };\n parentPort?.postMessage(response);\n return;\n }\n\n const response: WorkerResponseMessage = {\n type: \"result\",\n taskId: message.taskId,\n index: message.index,\n payload: {\n kind: \"skip\",\n skip: { path, reason: `not readable: ${messageText}` },\n },\n };\n parentPort?.postMessage(response);\n return;\n }\n\n if (isProbablyBinary(buffer)) {\n const response: WorkerResponseMessage = {\n type: \"result\",\n taskId: message.taskId,\n index: message.index,\n payload: {\n kind: \"skip\",\n skip: { path, reason: \"binary file\" },\n },\n };\n parentPort?.postMessage(response);\n return;\n }\n\n try {\n const content = buffer.toString(\"utf8\");\n const result =\n config.section === \"all\"\n ? wordCounter(content, config.wcOptions)\n : countSections(content, config.section, config.wcOptions);\n\n if (!config.preserveCollectorSegments) {\n compactCollectorSegmentsInCountResult(result);\n }\n\n const response: WorkerResponseMessage = {\n type: \"result\",\n taskId: message.taskId,\n index: message.index,\n payload: {\n kind: \"file\",\n file: {\n path,\n result,\n },\n },\n };\n parentPort?.postMessage(response);\n } catch (error) {\n const code =\n typeof error === \"object\" && error !== null && \"code\" in error\n ? String(error.code)\n : undefined;\n const messageText = error instanceof Error ? error.message : String(error);\n const response: WorkerResponseMessage = {\n type: \"fatal\",\n taskId: message.taskId,\n index: message.index,\n path,\n code,\n message: messageText,\n };\n parentPort?.postMessage(response);\n }\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"count-worker.mjs","names":["getNonWordTotal","collectNonWordsAggregate","normalizeText","buildPerKeyItems","wordCounter","buildSingleItem","sumTotals","wordCounter","wordCounter"],"sources":["../../../src/markdown/toml/arrays.ts","../../../src/markdown/toml/keys.ts","../../../src/markdown/toml/strings.ts","../../../src/markdown/toml/values.ts","../../../src/markdown/toml/parse-frontmatter.ts","../../../src/markdown/parse-markdown.ts","../../../src/wc/segmenter.ts","../../../src/utils/append-all.ts","../../../src/wc/non-words.ts","../../../src/wc/analyze.ts","../../../src/wc/mode.ts","../../../src/wc/latin-hints.ts","../../../src/wc/locale-detect.ts","../../../src/wc/segment.ts","../../../src/wc/wc.ts","../../../src/wc/index.ts","../../../src/markdown/section-count.ts","../../../src/detector/none.ts","../../../src/detector/result-builder.ts","../../../src/detector/sections.ts","../../../src/detector/policy.ts","../../../src/detector/whatlang-wasm.ts","../../../src/detector/whatlang-map.ts","../../../src/detector/wasm.ts","../../../src/detector/index.ts","../../../src/cli/batch/aggregate.ts","../../../src/cli/path/load.ts","../../../src/cli/batch/jobs/worker/count-worker.ts"],"sourcesContent":["export function ensureArrayContainer(\n result: Record<string, unknown>,\n key: string,\n): Record<string, unknown>[] {\n const existing = result[key];\n if (Array.isArray(existing)) {\n return existing as Record<string, unknown>[];\n }\n const list: Record<string, unknown>[] = [];\n result[key] = list;\n return list;\n}\n\nexport function flattenArrayTables(result: Record<string, unknown>): void {\n for (const [key, value] of Object.entries(result)) {\n if (!Array.isArray(value)) {\n continue;\n }\n const flattened = value\n .map((entry) =>\n Object.entries(entry)\n .map(([entryKey, entryValue]) => `${entryKey}=${entryValue}`)\n .join(\", \"),\n )\n .join(\" | \");\n result[key] = flattened;\n }\n}\n","function stripKeyQuotes(key: string): string {\n const trimmed = key.trim();\n if (\n (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nexport function normalizeKeyPath(key: string): string | null {\n const trimmed = key.trim();\n if (!trimmed) {\n return null;\n }\n\n if (\n (trimmed.startsWith(\"\\\"\") && trimmed.endsWith(\"\\\"\")) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\"))\n ) {\n const unquoted = stripKeyQuotes(trimmed);\n return unquoted ? unquoted : null;\n }\n\n const segments = trimmed.split(\".\").map((segment) => segment.trim());\n if (segments.some((segment) => !segment)) {\n return null;\n }\n return segments.join(\".\");\n}\n","export function stripInlineComment(line: string): string {\n let inString: \"single\" | \"double\" | null = null;\n let escaped = false;\n\n for (let i = 0; i < line.length; i += 1) {\n const char = line[i] ?? \"\";\n\n if (inString) {\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\" && inString === \"double\") {\n escaped = true;\n continue;\n }\n\n if (inString === \"double\" && char === \"\\\"\") {\n inString = null;\n continue;\n }\n\n if (inString === \"single\" && char === \"'\") {\n inString = null;\n continue;\n }\n\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = \"double\";\n continue;\n }\n\n if (char === \"'\") {\n inString = \"single\";\n continue;\n }\n\n if (char === \"#\") {\n return line.slice(0, i).trimEnd();\n }\n }\n\n return line;\n}\n\nfunction unescapeBasic(input: string): string {\n return input\n .replace(/\\\\\\\\/g, \"\\\\\")\n .replace(/\\\\\"/g, \"\\\"\")\n .replace(/\\\\n/g, \"\\n\")\n .replace(/\\\\t/g, \"\\t\")\n .replace(/\\\\r/g, \"\\r\");\n}\n\nexport function parseStringLiteral(value: string): string | null {\n if (value.startsWith('\"\"\"') && value.endsWith('\"\"\"')) {\n const inner = value.slice(3, -3);\n return unescapeBasic(inner);\n }\n\n if (value.startsWith(\"'''\") && value.endsWith(\"'''\")) {\n return value.slice(3, -3);\n }\n\n if (value.startsWith(\"\\\"\") && value.endsWith(\"\\\"\")) {\n return unescapeBasic(value.slice(1, -1));\n }\n\n if (value.startsWith(\"'\") && value.endsWith(\"'\")) {\n return value.slice(1, -1);\n }\n\n return null;\n}\n","import { normalizeKeyPath } from \"./keys\";\nimport { parseStringLiteral } from \"./strings\";\nimport type { TomlValue } from \"./types\";\n\nfunction parsePrimitive(raw: string): string | number | boolean | null {\n const value = raw.trim();\n if (!value) {\n return null;\n }\n\n const stringLiteral = parseStringLiteral(value);\n if (stringLiteral !== null) {\n return stringLiteral;\n }\n\n if (value === \"true\") {\n return true;\n }\n\n if (value === \"false\") {\n return false;\n }\n\n if (/^[+-]?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?$/.test(value)) {\n return Number(value);\n }\n\n if (/^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n return value;\n }\n\n return value;\n}\n\nfunction parseArray(raw: string): Array<string | number | boolean> | null {\n const value = raw.trim();\n if (!value.startsWith(\"[\") || !value.endsWith(\"]\")) {\n return null;\n }\n\n const inner = value.slice(1, -1).trim();\n if (!inner) {\n return [];\n }\n\n const items: Array<string | number | boolean> = [];\n let current = \"\";\n let inString: \"single\" | \"double\" | null = null;\n let escaped = false;\n\n for (let i = 0; i < inner.length; i += 1) {\n const char = inner[i] ?? \"\";\n\n if (inString) {\n current += char;\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\" && inString === \"double\") {\n escaped = true;\n continue;\n }\n\n if (inString === \"double\" && char === \"\\\"\") {\n inString = null;\n } else if (inString === \"single\" && char === \"'\") {\n inString = null;\n }\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = \"double\";\n current += char;\n continue;\n }\n\n if (char === \"'\") {\n inString = \"single\";\n current += char;\n continue;\n }\n\n if (char === \",\") {\n const item = parsePrimitive(current);\n if (item === null) {\n return null;\n }\n items.push(item);\n current = \"\";\n continue;\n }\n\n current += char;\n }\n\n const finalItem = parsePrimitive(current);\n if (finalItem === null) {\n return null;\n }\n items.push(finalItem);\n\n return items;\n}\n\nfunction parseInlineTable(raw: string): Record<string, TomlValue> | null {\n const trimmed = raw.trim();\n if (!trimmed.startsWith(\"{\") || !trimmed.endsWith(\"}\")) {\n return null;\n }\n\n const inner = trimmed.slice(1, -1).trim();\n if (!inner) {\n return {};\n }\n\n const pairs: string[] = [];\n let current = \"\";\n let inString: \"single\" | \"double\" | null = null;\n let escaped = false;\n let bracketDepth = 0;\n let braceDepth = 0;\n\n for (let i = 0; i < inner.length; i += 1) {\n const char = inner[i] ?? \"\";\n\n if (inString) {\n current += char;\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\" && inString === \"double\") {\n escaped = true;\n continue;\n }\n\n if (inString === \"double\" && char === \"\\\"\") {\n inString = null;\n } else if (inString === \"single\" && char === \"'\") {\n inString = null;\n }\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = \"double\";\n current += char;\n continue;\n }\n\n if (char === \"'\") {\n inString = \"single\";\n current += char;\n continue;\n }\n\n if (char === \"[\") {\n bracketDepth += 1;\n current += char;\n continue;\n }\n\n if (char === \"]\") {\n if (bracketDepth > 0) {\n bracketDepth -= 1;\n }\n current += char;\n continue;\n }\n\n if (char === \"{\") {\n braceDepth += 1;\n current += char;\n continue;\n }\n\n if (char === \"}\") {\n if (braceDepth > 0) {\n braceDepth -= 1;\n }\n current += char;\n continue;\n }\n\n if (char === \",\" && bracketDepth === 0 && braceDepth === 0) {\n pairs.push(current);\n current = \"\";\n continue;\n }\n\n current += char;\n }\n\n if (current.trim()) {\n pairs.push(current);\n }\n\n const output: Record<string, TomlValue> = {};\n for (const pair of pairs) {\n const separatorIndex = pair.indexOf(\"=\");\n if (separatorIndex === -1) {\n return null;\n }\n const key = normalizeKeyPath(pair.slice(0, separatorIndex));\n if (!key) {\n return null;\n }\n const valueRaw = pair.slice(separatorIndex + 1).trim();\n if (!valueRaw) {\n return null;\n }\n if (valueRaw.startsWith(\"{\")) {\n return null;\n }\n const normalized = normalizeValue(valueRaw);\n if (normalized === null) {\n return null;\n }\n if (typeof normalized === \"object\" && !Array.isArray(normalized)) {\n return null;\n }\n output[key] = normalized;\n }\n\n return output;\n}\n\nexport function normalizeValue(value: string): TomlValue | null {\n if (!value) {\n return null;\n }\n\n const trimmed = value.trim();\n if (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) {\n return parseInlineTable(trimmed);\n }\n\n const array = parseArray(trimmed);\n if (array) {\n return array;\n }\n\n if (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\")) {\n return null;\n }\n\n return parsePrimitive(trimmed);\n}\n\nexport function toPlainText(value: unknown): string {\n if (value == null) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return value.map((item) => String(item)).join(\", \");\n }\n return String(value);\n}\n","import { ensureArrayContainer, flattenArrayTables } from \"./arrays\";\nimport { normalizeKeyPath } from \"./keys\";\nimport { stripInlineComment } from \"./strings\";\nimport { normalizeValue, toPlainText } from \"./values\";\n\nexport function parseTomlFrontmatter(frontmatter: string): Record<string, unknown> | null {\n const result: Record<string, unknown> = {};\n const lines = frontmatter.split(\"\\n\");\n let tablePrefix = \"\";\n let tableTarget: Record<string, unknown> | null = null;\n let tablePrefixInList = false;\n\n for (let index = 0; index < lines.length; index += 1) {\n const rawLine = lines[index] ?? \"\";\n const trimmedLine = rawLine.trim();\n if (!trimmedLine || trimmedLine.startsWith(\"#\")) {\n continue;\n }\n\n if (trimmedLine.startsWith(\"[[\")) {\n const match = trimmedLine.match(/^\\[\\[([^\\]]+)]]$/);\n if (!match) {\n return null;\n }\n const normalizedTable = normalizeKeyPath(match[1] ?? \"\");\n if (!normalizedTable) {\n return null;\n }\n const list = ensureArrayContainer(result, normalizedTable);\n const newEntry: Record<string, unknown> = {};\n list.push(newEntry);\n tableTarget = newEntry;\n tablePrefix = normalizedTable;\n tablePrefixInList = true;\n continue;\n }\n\n const tableMatch = trimmedLine.match(/^\\[([^\\]]+)]$/);\n if (tableMatch) {\n const normalizedTable = normalizeKeyPath(tableMatch[1] ?? \"\");\n if (!normalizedTable) {\n return null;\n }\n tablePrefix = normalizedTable;\n tablePrefixInList = false;\n tableTarget = null;\n continue;\n }\n\n const lineForParsing = /(\"\"\"|''')/.test(rawLine) ? rawLine : stripInlineComment(rawLine);\n const separatorIndex = lineForParsing.indexOf(\"=\");\n if (separatorIndex === -1) {\n return null;\n }\n\n const keyRaw = lineForParsing.slice(0, separatorIndex);\n const key = normalizeKeyPath(keyRaw);\n let valueRaw = lineForParsing.slice(separatorIndex + 1).trim();\n if (!key) {\n return null;\n }\n\n const tripleDelimiter = valueRaw.startsWith('\"\"\"') ? '\"\"\"' : valueRaw.startsWith(\"'''\") ? \"'''\" : null;\n if (tripleDelimiter) {\n const closingIndex = valueRaw.indexOf(tripleDelimiter, tripleDelimiter.length);\n if (closingIndex !== -1) {\n const after = valueRaw.slice(closingIndex + tripleDelimiter.length);\n const strippedAfter = stripInlineComment(after);\n valueRaw = `${valueRaw.slice(0, closingIndex + tripleDelimiter.length)}${strippedAfter}`;\n } else {\n const delimiter = tripleDelimiter;\n let combined = valueRaw;\n let closed = false;\n while (index + 1 < lines.length) {\n index += 1;\n const nextLine = lines[index] ?? \"\";\n combined += `\\n${nextLine}`;\n if (new RegExp(`${delimiter}\\\\s*$`).test(nextLine)) {\n closed = true;\n break;\n }\n }\n if (!closed) {\n return null;\n }\n valueRaw = combined;\n }\n }\n\n const normalized = normalizeValue(valueRaw);\n if (normalized === null) {\n return null;\n }\n\n const fullKey = tablePrefix ? `${tablePrefix}.${key}` : key;\n if (typeof normalized === \"object\" && !Array.isArray(normalized)) {\n for (const [inlineKey, inlineValue] of Object.entries(normalized)) {\n const entryKey = tablePrefixInList ? `${key}.${inlineKey}` : `${fullKey}.${inlineKey}`;\n if (tablePrefixInList && tableTarget) {\n tableTarget[entryKey] = toPlainText(inlineValue);\n } else {\n result[entryKey] = toPlainText(inlineValue);\n }\n }\n continue;\n }\n\n if (tablePrefixInList && tableTarget) {\n tableTarget[key] = toPlainText(normalized);\n continue;\n }\n\n result[fullKey] = toPlainText(normalized);\n }\n\n flattenArrayTables(result);\n\n return result;\n}\n","import { parseDocument } from \"yaml\";\nimport { parseTomlFrontmatter } from \"./toml-simple\";\nimport type { FrontmatterType, ParsedMarkdown } from \"./types\";\n\nconst FENCE_TO_TYPE: Record<string, FrontmatterType> = {\n \"---\": \"yaml\",\n \"+++\": \"toml\",\n \";;;\": \"json\",\n};\n\nfunction normalizeNewlines(input: string): string {\n return input.replace(/\\r\\n/g, \"\\n\");\n}\n\nfunction stripBom(line: string): string {\n return line.startsWith(\"\\uFEFF\") ? line.slice(1) : line;\n}\n\nfunction getFenceType(line: string): FrontmatterType | null {\n const match = line.match(/^[\\t ]*(---|\\+\\+\\+|;;;)[\\t ]*$/);\n if (!match) {\n return null;\n }\n return FENCE_TO_TYPE[match[1] ?? \"\"] ?? null;\n}\n\nfunction parseFrontmatter(frontmatter: string, type: FrontmatterType | null): Record<string, unknown> | null {\n if (!type) {\n return null;\n }\n\n if (type === \"json\") {\n try {\n return JSON.parse(frontmatter) as Record<string, unknown>;\n } catch {\n return null;\n }\n }\n\n if (type === \"yaml\") {\n const doc = parseDocument(frontmatter, { prettyErrors: false });\n if (doc.errors.length > 0) {\n return null;\n }\n const data = doc.toJSON();\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n return null;\n }\n return data as Record<string, unknown>;\n }\n\n if (type === \"toml\") {\n return parseTomlFrontmatter(frontmatter);\n }\n\n return null;\n}\n\nfunction extractJsonBlock(text: string, startIndex: number): { jsonText: string; endIndex: number } | null {\n let depth = 0;\n let inString = false;\n let escaped = false;\n\n for (let i = startIndex; i < text.length; i += 1) {\n const char = text[i] ?? \"\";\n\n if (inString) {\n if (escaped) {\n escaped = false;\n continue;\n }\n\n if (char === \"\\\\\") {\n escaped = true;\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = false;\n }\n\n continue;\n }\n\n if (char === \"\\\"\") {\n inString = true;\n continue;\n }\n\n if (char === \"{\") {\n depth += 1;\n continue;\n }\n\n if (char === \"}\") {\n depth -= 1;\n if (depth === 0) {\n const jsonText = text.slice(startIndex, i + 1);\n return { jsonText, endIndex: i };\n }\n }\n }\n\n return null;\n}\n\nexport function parseMarkdown(input: string): ParsedMarkdown {\n const normalized = normalizeNewlines(input);\n const lines = normalized.split(\"\\n\");\n if (lines.length === 0) {\n return { frontmatter: null, content: normalized, data: null, frontmatterType: null };\n }\n\n lines[0] = stripBom(lines[0] ?? \"\");\n const normalizedWithoutBom = lines.join(\"\\n\");\n\n const openingType = getFenceType(lines[0] ?? \"\");\n if (!openingType) {\n const leadingWhitespace = normalizedWithoutBom.match(/^[\\t \\n]*/)?.[0] ?? \"\";\n const jsonStart = leadingWhitespace.length;\n if (normalizedWithoutBom[jsonStart] !== \"{\") {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n const jsonBlock = extractJsonBlock(normalizedWithoutBom, jsonStart);\n if (!jsonBlock) {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n const frontmatter = jsonBlock.jsonText;\n let content = normalizedWithoutBom.slice(jsonBlock.endIndex + 1);\n if (content.startsWith(\"\\n\")) {\n content = content.slice(1);\n }\n const data = parseFrontmatter(frontmatter, \"json\");\n if (!data) {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n return {\n frontmatter,\n content,\n data,\n frontmatterType: \"json\",\n };\n }\n\n let closingIndex = -1;\n for (let i = 1; i < lines.length; i += 1) {\n if (getFenceType(lines[i] ?? \"\") === openingType) {\n closingIndex = i;\n break;\n }\n }\n\n if (closingIndex === -1) {\n return { frontmatter: null, content: normalizedWithoutBom, data: null, frontmatterType: null };\n }\n\n const frontmatter = lines.slice(1, closingIndex).join(\"\\n\");\n const content = lines.slice(closingIndex + 1).join(\"\\n\");\n const data = parseFrontmatter(frontmatter, openingType);\n\n return {\n frontmatter,\n content,\n data,\n frontmatterType: openingType,\n };\n}\n","const segmenterCache = new Map<string, Intl.Segmenter>();\nconst graphemeSegmenterCache = new Map<string, Intl.Segmenter>();\n\nexport function getSegmenter(locale: string): Intl.Segmenter {\n const cached = segmenterCache.get(locale);\n if (cached) {\n return cached;\n }\n const segmenter = new Intl.Segmenter(locale, { granularity: \"word\" });\n segmenterCache.set(locale, segmenter);\n return segmenter;\n}\n\nexport function getGraphemeSegmenter(locale: string): Intl.Segmenter {\n const cached = graphemeSegmenterCache.get(locale);\n if (cached) {\n return cached;\n }\n const segmenter = new Intl.Segmenter(locale, { granularity: \"grapheme\" });\n graphemeSegmenterCache.set(locale, segmenter);\n return segmenter;\n}\n\nfunction supportsSegmenter(): boolean {\n return typeof Intl !== \"undefined\" && typeof Intl.Segmenter === \"function\";\n}\n\nexport function countWordsForLocale(text: string, locale: string): number {\n const segmenter = getSegmenter(locale);\n let count = 0;\n for (const segment of segmenter.segment(text)) {\n if (segment.isWordLike) {\n count++;\n }\n }\n return count;\n}\n\nexport function countCharsForLocale(text: string, locale: string): number {\n if (!supportsSegmenter()) {\n return Array.from(text).length;\n }\n const segmenter = getGraphemeSegmenter(locale);\n let count = 0;\n for (const _segment of segmenter.segment(text)) {\n count++;\n }\n return count;\n}\n","export function appendAll<T>(target: T[], source: readonly T[]): void {\n for (const item of source) {\n target.push(item);\n }\n}\n","import type { NonWordCollection, WhitespaceCounts } from \"./types\";\nimport { appendAll } from \"../utils/append-all\";\n\nconst emojiRegex = /(?:\\p{Extended_Pictographic}|\\p{Emoji_Presentation})/u;\nconst emojiPresentationRegex = /\\p{Emoji_Presentation}/u;\nconst keycapEmojiRegex = /[0-9#*]\\uFE0F?\\u20E3/u;\nconst symbolRegex = /\\p{S}/u;\nconst punctuationRegex = /\\p{P}/u;\nconst whitespaceRegex = /\\s/u;\nconst newlineChars = new Set([\"\\n\", \"\\r\", \"\\u2028\", \"\\u2029\"]);\n\nexport function createNonWordCollection(): NonWordCollection {\n return {\n emoji: [],\n symbols: [],\n punctuation: [],\n counts: {\n emoji: 0,\n symbols: 0,\n punctuation: 0,\n },\n };\n}\n\nexport function addNonWord(\n collection: NonWordCollection,\n category: \"emoji\" | \"symbol\" | \"punctuation\",\n segment: string,\n): void {\n if (category === \"emoji\") {\n collection.emoji.push(segment);\n collection.counts.emoji += 1;\n return;\n }\n if (category === \"symbol\") {\n collection.symbols.push(segment);\n collection.counts.symbols += 1;\n return;\n }\n collection.punctuation.push(segment);\n collection.counts.punctuation += 1;\n}\n\nexport function addWhitespace(\n collection: NonWordCollection,\n segment: string,\n): number {\n let whitespace = collection.whitespace;\n let count = 0;\n for (const char of segment) {\n if (char === \" \") {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.spaces += 1;\n count += 1;\n continue;\n }\n if (char === \"\\t\") {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.tabs += 1;\n count += 1;\n continue;\n }\n if (newlineChars.has(char)) {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.newlines += 1;\n count += 1;\n continue;\n }\n if (whitespaceRegex.test(char)) {\n whitespace = whitespace ?? createWhitespaceCounts();\n whitespace.other += 1;\n count += 1;\n }\n }\n\n if (count > 0) {\n collection.whitespace = whitespace ?? createWhitespaceCounts();\n collection.counts.whitespace = (collection.counts.whitespace ?? 0) + count;\n }\n\n return count;\n}\n\nexport function classifyNonWordSegment(\n segment: string,\n): \"emoji\" | \"symbol\" | \"punctuation\" | null {\n const hasEmojiVariationSelector = segment.includes(\"\\uFE0F\");\n if (\n keycapEmojiRegex.test(segment) ||\n emojiPresentationRegex.test(segment) ||\n (hasEmojiVariationSelector && emojiRegex.test(segment))\n ) {\n return \"emoji\";\n }\n if (symbolRegex.test(segment)) {\n return \"symbol\";\n }\n if (punctuationRegex.test(segment)) {\n return \"punctuation\";\n }\n return null;\n}\n\nexport function mergeNonWordCollections(\n target: NonWordCollection,\n source: NonWordCollection,\n): NonWordCollection {\n if (source.counts.emoji > 0) {\n appendAll(target.emoji, source.emoji);\n target.counts.emoji += source.counts.emoji;\n }\n if (source.counts.symbols > 0) {\n appendAll(target.symbols, source.symbols);\n target.counts.symbols += source.counts.symbols;\n }\n if (source.counts.punctuation > 0) {\n appendAll(target.punctuation, source.punctuation);\n target.counts.punctuation += source.counts.punctuation;\n }\n if (source.counts.whitespace && source.counts.whitespace > 0 && source.whitespace) {\n const whitespace = target.whitespace ?? createWhitespaceCounts();\n whitespace.spaces += source.whitespace.spaces;\n whitespace.tabs += source.whitespace.tabs;\n whitespace.newlines += source.whitespace.newlines;\n whitespace.other += source.whitespace.other;\n target.whitespace = whitespace;\n target.counts.whitespace = (target.counts.whitespace ?? 0) + source.counts.whitespace;\n }\n return target;\n}\n\nfunction createWhitespaceCounts(): WhitespaceCounts {\n return { spaces: 0, tabs: 0, newlines: 0, other: 0 };\n}\n","import { countCharsForLocale, getSegmenter } from \"./segmenter\";\nimport {\n addNonWord,\n addWhitespace,\n classifyNonWordSegment,\n createNonWordCollection,\n mergeNonWordCollections,\n} from \"./non-words\";\nimport { appendAll } from \"../utils/append-all\";\nimport type {\n CharCollectorBreakdown,\n ChunkAnalysis,\n CollectorBreakdown,\n LocaleChunk,\n NonWordCollection,\n} from \"./types\";\n\ntype CharAnalysis = LocaleChunk & { chars: number; nonWords?: NonWordCollection };\ntype CharChunkAnalysis = CharAnalysis & { wordChars: number; nonWordChars: number };\n\nexport function analyzeChunk(\n chunk: LocaleChunk,\n collectNonWords?: boolean,\n includeWhitespace?: boolean,\n): ChunkAnalysis {\n const segmenter = getSegmenter(chunk.locale);\n const segments: string[] = [];\n const nonWords: NonWordCollection | null = collectNonWords\n ? createNonWordCollection()\n : null;\n for (const part of segmenter.segment(chunk.text)) {\n if (part.isWordLike) {\n segments.push(part.segment);\n } else if (collectNonWords && nonWords) {\n if (includeWhitespace) {\n addWhitespace(nonWords, part.segment);\n }\n const category = classifyNonWordSegment(part.segment);\n if (category) {\n addNonWord(nonWords, category, part.segment);\n }\n }\n }\n return {\n locale: chunk.locale,\n text: chunk.text,\n segments,\n words: segments.length,\n nonWords: nonWords ?? undefined,\n };\n}\n\nexport function analyzeCharChunk(\n chunk: LocaleChunk,\n collectNonWords?: boolean,\n includeWhitespace?: boolean,\n): CharChunkAnalysis {\n const segmenter = getSegmenter(chunk.locale);\n const nonWords: NonWordCollection | null = collectNonWords\n ? createNonWordCollection()\n : null;\n let chars = 0;\n let wordChars = 0;\n let nonWordChars = 0;\n\n for (const part of segmenter.segment(chunk.text)) {\n if (part.isWordLike) {\n const count = countCharsForLocale(part.segment, chunk.locale);\n chars += count;\n wordChars += count;\n continue;\n }\n\n if (collectNonWords && nonWords) {\n let whitespaceCount = 0;\n if (includeWhitespace) {\n whitespaceCount = addWhitespace(nonWords, part.segment);\n }\n const category = classifyNonWordSegment(part.segment);\n if (category) {\n addNonWord(nonWords, category, part.segment);\n }\n if (category || whitespaceCount > 0) {\n const count = countCharsForLocale(part.segment, chunk.locale);\n chars += count;\n nonWordChars += count;\n }\n }\n }\n\n return {\n locale: chunk.locale,\n text: chunk.text,\n chars,\n wordChars,\n nonWordChars,\n nonWords: nonWords ?? undefined,\n };\n}\n\nexport function aggregateCharsByLocale(\n chunks: CharChunkAnalysis[],\n): Array<CharCollectorBreakdown & { wordChars: number; nonWordChars: number }> {\n const order: string[] = [];\n const map = new Map<\n string,\n CharCollectorBreakdown & { wordChars: number; nonWordChars: number }\n >();\n\n for (const chunk of chunks) {\n const existing = map.get(chunk.locale);\n if (existing) {\n existing.chars += chunk.chars;\n existing.wordChars += chunk.wordChars;\n existing.nonWordChars += chunk.nonWordChars;\n if (chunk.nonWords) {\n if (!existing.nonWords) {\n existing.nonWords = createNonWordCollection();\n }\n mergeNonWordCollections(existing.nonWords, chunk.nonWords);\n }\n continue;\n }\n\n order.push(chunk.locale);\n map.set(chunk.locale, {\n locale: chunk.locale,\n chars: chunk.chars,\n wordChars: chunk.wordChars,\n nonWordChars: chunk.nonWordChars,\n nonWords: chunk.nonWords\n ? mergeNonWordCollections(createNonWordCollection(), chunk.nonWords)\n : undefined,\n });\n }\n\n return order.map((locale) => map.get(locale)!);\n}\n\nexport function aggregateByLocale(\n chunks: ChunkAnalysis[]\n): CollectorBreakdown[] {\n const order: string[] = [];\n const map = new Map<string, CollectorBreakdown>();\n\n for (const chunk of chunks) {\n const existing = map.get(chunk.locale);\n if (existing) {\n existing.words += chunk.words;\n appendAll(existing.segments, chunk.segments);\n continue;\n }\n\n order.push(chunk.locale);\n map.set(chunk.locale, {\n locale: chunk.locale,\n words: chunk.words,\n segments: [...chunk.segments],\n });\n }\n\n return order.map((locale) => map.get(locale)!);\n}\n","import type { WordCounterMode } from \"./types\";\n\nconst MODE_ALIASES: Record<string, WordCounterMode> = {\n chunk: \"chunk\",\n chunks: \"chunk\",\n segments: \"segments\",\n segment: \"segments\",\n seg: \"segments\",\n collector: \"collector\",\n collect: \"collector\",\n colle: \"collector\",\n char: \"char\",\n chars: \"char\",\n character: \"char\",\n characters: \"char\",\n \"char-collector\": \"char-collector\",\n};\n\nconst CHAR_MODE_ALIASES = new Set([\"char\", \"chars\", \"character\", \"characters\"]);\nconst COLLECTOR_MODE_ALIASES = new Set([\"collector\", \"collect\", \"colle\", \"col\"]);\n\nfunction collapseSeparators(value: string): string {\n return value.replace(/[-_\\s]+/g, \"\");\n}\n\nfunction isComposedCharCollectorFromTokens(value: string): boolean {\n const tokens = value\n .split(/[-_\\s]+/)\n .map((token) => token.trim())\n .filter((token) => token.length > 0);\n if (tokens.length < 2) {\n return false;\n }\n\n let hasCharAlias = false;\n let hasCollectorAlias = false;\n for (const token of tokens) {\n if (CHAR_MODE_ALIASES.has(token)) {\n hasCharAlias = true;\n continue;\n }\n if (COLLECTOR_MODE_ALIASES.has(token)) {\n hasCollectorAlias = true;\n continue;\n }\n return false;\n }\n\n return hasCharAlias && hasCollectorAlias;\n}\n\nfunction isComposedCharCollectorCompact(value: string): boolean {\n for (const charAlias of CHAR_MODE_ALIASES) {\n for (const collectorAlias of COLLECTOR_MODE_ALIASES) {\n if (value === `${charAlias}${collectorAlias}` || value === `${collectorAlias}${charAlias}`) {\n return true;\n }\n }\n }\n return false;\n}\n\nexport function normalizeMode(input?: string | null): WordCounterMode | null {\n if (!input) {\n return null;\n }\n const normalized = input.trim().toLowerCase();\n const direct = MODE_ALIASES[normalized];\n if (direct) {\n return direct;\n }\n\n if (isComposedCharCollectorFromTokens(normalized)) {\n return \"char-collector\";\n }\n\n const compact = collapseSeparators(normalized);\n if (isComposedCharCollectorCompact(compact)) {\n return \"char-collector\";\n }\n\n return MODE_ALIASES[compact] ?? null;\n}\n\nexport function resolveMode(\n input?: string | null,\n fallback: WordCounterMode = \"chunk\",\n): WordCounterMode {\n return normalizeMode(input) ?? fallback;\n}\n","import type { LatinHintRule } from \"./types\";\n\nconst DEFAULT_LATIN_HINT_RULES_SOURCE = [\n { tag: \"de\", pattern: \"[äöüÄÖÜß]\" },\n { tag: \"es\", pattern: \"[ñÑ¿¡]\" },\n { tag: \"pt\", pattern: \"[ãõÃÕ]\" },\n { tag: \"fr\", pattern: \"[œŒæÆ]\" },\n { tag: \"pl\", pattern: \"[ąćęłńśźżĄĆĘŁŃŚŹŻ]\" },\n { tag: \"tr\", pattern: \"[ıİğĞşŞ]\" },\n { tag: \"ro\", pattern: \"[ăĂâÂîÎșȘțȚ]\" },\n { tag: \"hu\", pattern: \"[őŐűŰ]\" },\n { tag: \"is\", pattern: \"[ðÐþÞ]\" },\n] satisfies LatinHintRule[];\n\nexport const DEFAULT_LATIN_HINT_RULES: ReadonlyArray<Readonly<LatinHintRule>> = Object.freeze(\n DEFAULT_LATIN_HINT_RULES_SOURCE.map((rule) => Object.freeze({ ...rule })),\n);\n","import type { LatinHintRule } from \"./types\";\nimport { DEFAULT_LATIN_HINT_RULES } from \"./latin-hints\";\n\nexport const DEFAULT_LOCALE = \"und-Latn\";\nexport const DEFAULT_HAN_TAG = \"und-Hani\";\n\nconst MAX_LATIN_HINT_PATTERN_LENGTH = 256;\n\nexport interface LocaleDetectOptions {\n latinLanguageHint?: string;\n latinTagHint?: string;\n latinLocaleHint?: string;\n latinHintRules?: LatinHintRule[];\n useDefaultLatinHints?: boolean;\n hanLanguageHint?: string;\n hanTagHint?: string;\n}\n\ntype ResolvedLatinHintRule = {\n tag: string;\n pattern: RegExp;\n priority: number;\n order: number;\n};\n\nexport type LocaleDetectContext = {\n latinHint?: string;\n hanHint?: string;\n latinHintRules: ResolvedLatinHintRule[];\n latinLocales: Set<string>;\n};\n\nconst regex = {\n hiragana: /\\p{Script=Hiragana}/u,\n katakana: /\\p{Script=Katakana}/u,\n hangul: /\\p{Script=Hangul}/u,\n han: /\\p{Script=Han}/u,\n latin: /\\p{Script=Latin}/u,\n arabic: /\\p{Script=Arabic}/u,\n cyrillic: /\\p{Script=Cyrillic}/u,\n devanagari: /\\p{Script=Devanagari}/u,\n thai: /\\p{Script=Thai}/u,\n};\n\nconst defaultLatinLocales = new Set<string>([\n DEFAULT_LOCALE,\n ...DEFAULT_LATIN_HINT_RULES.map((hint) => hint.tag),\n]);\n\nexport function isLatinLocale(locale: string, context?: LocaleDetectContext): boolean {\n if (context) {\n return context.latinLocales.has(locale);\n }\n return defaultLatinLocales.has(locale);\n}\n\nfunction resolveLatinHint(options: LocaleDetectOptions): string | undefined {\n const latinTagHint = options.latinTagHint?.trim();\n if (latinTagHint) {\n return latinTagHint;\n }\n\n const latinLanguageHint = options.latinLanguageHint?.trim();\n if (latinLanguageHint) {\n return latinLanguageHint;\n }\n\n const latinLocaleHint = options.latinLocaleHint?.trim();\n if (latinLocaleHint) {\n return latinLocaleHint;\n }\n\n return undefined;\n}\n\nfunction resolveHanHint(options: LocaleDetectOptions): string | undefined {\n const hanTagHint = options.hanTagHint?.trim();\n if (hanTagHint) {\n return hanTagHint;\n }\n\n const hanLanguageHint = options.hanLanguageHint?.trim();\n if (hanLanguageHint) {\n return hanLanguageHint;\n }\n\n return undefined;\n}\n\nfunction compileLatinHintPattern(\n pattern: string | RegExp,\n label: string,\n): RegExp {\n const source = typeof pattern === \"string\" ? pattern : pattern.source;\n const hasUnicodeMode =\n typeof pattern !== \"string\" &&\n (pattern.flags.includes(\"u\") || pattern.flags.includes(\"v\"));\n const flags =\n typeof pattern === \"string\"\n ? \"u\"\n : hasUnicodeMode\n ? pattern.flags\n : `${pattern.flags}u`;\n if (source.length === 0) {\n throw new Error(`${label}: pattern must not be empty.`);\n }\n if (source.length > MAX_LATIN_HINT_PATTERN_LENGTH) {\n throw new Error(\n `${label}: pattern must be at most ${MAX_LATIN_HINT_PATTERN_LENGTH} characters.`,\n );\n }\n try {\n return new RegExp(source, flags);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`${label}: invalid Unicode regex pattern (${message}).`);\n }\n}\n\nfunction normalizeLatinHintPriority(priority: unknown, label: string): number {\n if (priority === undefined) {\n return 0;\n }\n if (typeof priority !== \"number\" || !Number.isFinite(priority)) {\n throw new Error(`${label}: priority must be a finite number when provided.`);\n }\n return priority;\n}\n\nfunction compileLatinHintRule(\n rule: Readonly<LatinHintRule>,\n order: number,\n label: string,\n): ResolvedLatinHintRule {\n const tag = typeof rule.tag === \"string\" ? rule.tag.trim() : \"\";\n if (!tag) {\n throw new Error(`${label}: tag must be a non-empty string.`);\n }\n const pattern = compileLatinHintPattern(rule.pattern, label);\n const priority = normalizeLatinHintPriority(rule.priority, label);\n return {\n tag,\n pattern,\n priority,\n order,\n };\n}\n\nfunction resolveLatinHintRules(options: LocaleDetectOptions): ResolvedLatinHintRule[] {\n const useDefaultLatinHints = options.useDefaultLatinHints !== false;\n const customRules = options.latinHintRules ?? [];\n const combinedRules: Array<{ rule: Readonly<LatinHintRule>; label: string }> = [];\n\n for (let index = 0; index < customRules.length; index += 1) {\n const rule = customRules[index];\n if (!rule) {\n continue;\n }\n combinedRules.push({\n rule,\n label: `Invalid custom Latin hint rule at index ${index}`,\n });\n }\n\n if (useDefaultLatinHints) {\n for (let index = 0; index < DEFAULT_LATIN_HINT_RULES.length; index += 1) {\n const rule = DEFAULT_LATIN_HINT_RULES[index];\n if (!rule) {\n continue;\n }\n combinedRules.push({\n rule,\n label: `Invalid default Latin hint rule at index ${index}`,\n });\n }\n }\n\n const resolvedRules = combinedRules.map((entry, index) =>\n compileLatinHintRule(entry.rule, index, entry.label),\n );\n\n resolvedRules.sort((left, right) => {\n if (left.priority !== right.priority) {\n return right.priority - left.priority;\n }\n return left.order - right.order;\n });\n\n return resolvedRules;\n}\n\nexport function resolveLocaleDetectContext(\n options: LocaleDetectOptions = {},\n): LocaleDetectContext {\n const latinHint = resolveLatinHint(options);\n const latinHintRules = resolveLatinHintRules(options);\n const latinLocales = new Set<string>([DEFAULT_LOCALE]);\n for (const rule of latinHintRules) {\n latinLocales.add(rule.tag);\n }\n if (latinHint) {\n latinLocales.add(latinHint);\n }\n\n return {\n latinHint,\n hanHint: resolveHanHint(options),\n latinHintRules,\n latinLocales,\n };\n}\n\nfunction detectLatinLocale(char: string, context: LocaleDetectContext): string {\n for (const hint of context.latinHintRules) {\n hint.pattern.lastIndex = 0;\n if (hint.pattern.test(char)) {\n return hint.tag;\n }\n }\n return DEFAULT_LOCALE;\n}\n\nexport function detectLocaleForChar(\n char: string,\n previousLocale?: string | null,\n options: LocaleDetectOptions = {},\n context: LocaleDetectContext = resolveLocaleDetectContext(options),\n allowLatinLocaleCarry = true,\n allowJapaneseHanCarry = true,\n): string | null {\n if (regex.hiragana.test(char) || regex.katakana.test(char)) {\n return \"ja\";\n }\n if (regex.hangul.test(char)) {\n return \"ko\";\n }\n if (regex.arabic.test(char)) {\n return \"ar\";\n }\n if (regex.cyrillic.test(char)) {\n return \"ru\";\n }\n if (regex.devanagari.test(char)) {\n return \"hi\";\n }\n if (regex.thai.test(char)) {\n return \"th\";\n }\n\n if (regex.han.test(char)) {\n if (allowJapaneseHanCarry && previousLocale && previousLocale.startsWith(\"ja\")) {\n return previousLocale;\n }\n return context.hanHint ?? DEFAULT_HAN_TAG;\n }\n\n if (regex.latin.test(char)) {\n const hintedLocale = detectLatinLocale(char, context);\n if (hintedLocale !== DEFAULT_LOCALE) {\n return hintedLocale;\n }\n if (\n allowLatinLocaleCarry &&\n previousLocale &&\n isLatinLocale(previousLocale, context) &&\n previousLocale !== DEFAULT_LOCALE\n ) {\n return previousLocale;\n }\n if (context.latinHint) {\n return context.latinHint;\n }\n return DEFAULT_LOCALE;\n }\n\n return null;\n}\n","import {\n DEFAULT_LOCALE,\n detectLocaleForChar,\n isLatinLocale,\n resolveLocaleDetectContext,\n type LocaleDetectOptions,\n} from \"./locale-detect\";\nimport type { LocaleChunk } from \"./types\";\n\nconst HARD_BOUNDARY_REGEX = /[\\r\\n,.!?;:,、。!?;:.。、]/u;\nconst LATIN_PROMOTION_BREAK_REGEX = /[\\s,.!?;:,、。!?;:.。、]/u;\n\nexport function segmentTextByLocale(\n text: string,\n options: LocaleDetectOptions = {}\n): LocaleChunk[] {\n const context = resolveLocaleDetectContext(options);\n const chunks: LocaleChunk[] = [];\n // Keep currentLocale as a non-null string to simplify type-narrowing.\n let currentLocale: string = DEFAULT_LOCALE;\n let buffer = \"\";\n let bufferHasScript = false;\n let sawCarryBoundary = false;\n\n const updateCarryBoundaryState = (detected: string | null, char: string): void => {\n if (detected !== null) {\n sawCarryBoundary = false;\n return;\n }\n if (HARD_BOUNDARY_REGEX.test(char)) {\n sawCarryBoundary = true;\n }\n };\n\n for (const char of text) {\n const detected = detectLocaleForChar(\n char,\n currentLocale,\n options,\n context,\n !sawCarryBoundary,\n !sawCarryBoundary,\n );\n const targetLocale = detected ?? currentLocale;\n\n // If buffer is empty, this is the first character for a new chunk.\n if (buffer === \"\") {\n currentLocale = targetLocale;\n buffer = char;\n bufferHasScript = detected !== null;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n if (detected !== null && !bufferHasScript) {\n currentLocale = targetLocale;\n buffer += char;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n if (targetLocale !== currentLocale && detected !== null) {\n if (currentLocale === DEFAULT_LOCALE && isLatinLocale(targetLocale, context)) {\n const promotionBreakIndex = findLastLatinPromotionBreakIndex(buffer);\n if (promotionBreakIndex === -1) {\n currentLocale = targetLocale;\n buffer += char;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n const prefix = buffer.slice(0, promotionBreakIndex + 1);\n const suffix = buffer.slice(promotionBreakIndex + 1);\n if (prefix.length > 0) {\n chunks.push({ locale: currentLocale, text: prefix });\n }\n currentLocale = targetLocale;\n buffer = `${suffix}${char}`;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n // currentLocale is guaranteed to be a string here.\n chunks.push({ locale: currentLocale, text: buffer });\n currentLocale = targetLocale;\n buffer = char;\n bufferHasScript = true;\n updateCarryBoundaryState(detected, char);\n continue;\n }\n\n buffer += char;\n if (detected !== null) {\n bufferHasScript = true;\n }\n updateCarryBoundaryState(detected, char);\n }\n\n if (buffer.length > 0) {\n chunks.push({ locale: currentLocale, text: buffer });\n }\n\n return mergeAdjacentChunks(chunks);\n}\n\nfunction findLastLatinPromotionBreakIndex(buffer: string): number {\n for (let index = buffer.length - 1; index >= 0; index -= 1) {\n const char = buffer[index];\n if (!char) {\n continue;\n }\n if (LATIN_PROMOTION_BREAK_REGEX.test(char)) {\n return index;\n }\n }\n return -1;\n}\n\nfunction mergeAdjacentChunks(chunks: LocaleChunk[]): LocaleChunk[] {\n if (chunks.length === 0) {\n return chunks;\n }\n\n const merged: LocaleChunk[] = [];\n // We already returned for empty arrays above, so the first element is present.\n let last = chunks[0]!;\n\n for (let i = 1; i < chunks.length; i++) {\n const chunk = chunks[i]!;\n if (chunk.locale === last.locale) {\n last = { locale: last.locale, text: last.text + chunk.text };\n } else {\n merged.push(last);\n last = chunk;\n }\n }\n\n merged.push(last);\n return merged;\n}\n","import {\n analyzeCharChunk,\n analyzeChunk,\n aggregateByLocale,\n aggregateCharsByLocale,\n} from \"./analyze\";\nimport { resolveMode } from \"./mode\";\nimport { segmentTextByLocale } from \"./segment\";\nimport { countCharsForLocale, countWordsForLocale } from \"./segmenter\";\nimport { createNonWordCollection, mergeNonWordCollections } from \"./non-words\";\nimport type {\n CharBreakdown,\n CharCollectorBreakdown,\n ChunkBreakdown,\n ChunkWithSegments,\n NonWordCollection,\n WordCounterMode,\n WordCounterOptions,\n WordCounterResult,\n} from \"./types\";\n\nexport type {\n LatinHintRule,\n NonWordCollection,\n WordCounterMode,\n WordCounterOptions,\n WordCounterResult,\n WordCounterBreakdown,\n} from \"./types\";\n\nexport { countCharsForLocale, countWordsForLocale, segmentTextByLocale };\nexport { DEFAULT_LATIN_HINT_RULES } from \"./latin-hints\";\n\nexport function wordCounter(\n text: string,\n options: WordCounterOptions = {}\n): WordCounterResult {\n const mode: WordCounterMode = resolveMode(options.mode, \"chunk\");\n const collectNonWords = Boolean(options.nonWords);\n const includeWhitespace = Boolean(options.includeWhitespace);\n const chunks = segmentTextByLocale(text, {\n latinLanguageHint: options.latinLanguageHint,\n latinTagHint: options.latinTagHint,\n latinLocaleHint: options.latinLocaleHint,\n latinHintRules: options.latinHintRules,\n useDefaultLatinHints: options.useDefaultLatinHints,\n hanLanguageHint: options.hanLanguageHint,\n hanTagHint: options.hanTagHint,\n });\n\n if (mode === \"char\" || mode === \"char-collector\") {\n const analyzed = chunks.map((chunk) =>\n analyzeCharChunk(chunk, collectNonWords, includeWhitespace),\n );\n const total = analyzed.reduce((sum, chunk) => sum + chunk.chars, 0);\n const counts = collectNonWords\n ? {\n words: analyzed.reduce((sum, chunk) => sum + chunk.wordChars, 0),\n nonWords: analyzed.reduce((sum, chunk) => sum + chunk.nonWordChars, 0),\n total,\n }\n : undefined;\n\n if (mode === \"char\") {\n const items: CharBreakdown[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n chars: chunk.chars,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n const aggregated = aggregateCharsByLocale(analyzed);\n const items: CharCollectorBreakdown[] = aggregated.map((chunk) => ({\n locale: chunk.locale,\n chars: chunk.chars,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n const analyzed = chunks.map((chunk) =>\n analyzeChunk(chunk, collectNonWords, includeWhitespace),\n );\n const wordsTotal = analyzed.reduce((sum, chunk) => sum + chunk.words, 0);\n const nonWordsTotal = collectNonWords\n ? analyzed.reduce((sum, chunk) => {\n if (!chunk.nonWords) {\n return sum;\n }\n return sum + getNonWordTotal(chunk.nonWords);\n }, 0)\n : 0;\n const total = analyzed.reduce((sum, chunk) => {\n let chunkTotal = chunk.words;\n if (collectNonWords && chunk.nonWords) {\n chunkTotal += getNonWordTotal(chunk.nonWords);\n }\n return sum + chunkTotal;\n }, 0);\n\n const counts = collectNonWords ? { words: wordsTotal, nonWords: nonWordsTotal, total } : undefined;\n\n if (mode === \"segments\") {\n const items: ChunkWithSegments[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n words: chunk.words,\n segments: chunk.segments,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n if (mode === \"collector\") {\n const items = aggregateByLocale(analyzed);\n const nonWords = collectNonWordsAggregate(analyzed, collectNonWords);\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n nonWords,\n },\n };\n }\n\n const items: ChunkBreakdown[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n words: chunk.words,\n nonWords: chunk.nonWords,\n }));\n\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n}\n\nfunction getNonWordTotal(nonWords: NonWordCollection): number {\n return (\n nonWords.counts.emoji +\n nonWords.counts.symbols +\n nonWords.counts.punctuation +\n (nonWords.counts.whitespace ?? 0)\n );\n}\n\n\nfunction collectNonWordsAggregate(\n analyzed: Array<{ nonWords?: NonWordCollection }>,\n enabled: boolean,\n): NonWordCollection | undefined {\n if (!enabled) {\n return undefined;\n }\n const collection = createNonWordCollection();\n for (const chunk of analyzed) {\n if (!chunk.nonWords) {\n continue;\n }\n mergeNonWordCollections(collection, chunk.nonWords);\n }\n return collection;\n}\n","import { wordCounter } from \"./wc\";\n\nexport default wordCounter;\nexport { countCharsForLocale, countWordsForLocale, segmentTextByLocale } from \"./wc\";\nexport { DEFAULT_LATIN_HINT_RULES } from \"./wc\";\nexport type {\n LatinHintRule,\n NonWordCollection,\n WordCounterMode,\n WordCounterOptions,\n WordCounterResult,\n WordCounterBreakdown,\n} from \"./wc\";\n","import type { WordCounterMode, WordCounterOptions, WordCounterResult } from \"../wc/types\";\nimport wordCounter from \"../wc\";\nimport { parseMarkdown } from \"./parse-markdown\";\nimport type { SectionMode, SectionedResult } from \"./types\";\n\nfunction normalizeText(value: unknown): string {\n if (value == null) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction buildPerKeyItems(\n data: Record<string, unknown> | null,\n mode: WordCounterMode,\n options: WordCounterOptions,\n): Array<{ name: string; source: \"frontmatter\"; result: WordCounterResult }> {\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n return [];\n }\n\n return Object.entries(data).map(([key, value]) => {\n const valueText = normalizeText(value);\n const text = valueText ? `${key}: ${valueText}` : key;\n return {\n name: key,\n source: \"frontmatter\",\n result: wordCounter(text, options),\n };\n });\n}\n\nfunction buildSingleItem(\n name: string,\n text: string,\n mode: WordCounterMode,\n options: WordCounterOptions,\n source: \"frontmatter\" | \"content\",\n) {\n return [{ name, source, result: wordCounter(text, options) }];\n}\n\nfunction sumTotals(items: Array<{ result: WordCounterResult }>): number {\n return items.reduce((sum, item) => sum + item.result.total, 0);\n}\n\nexport function countSections(\n input: string,\n section: SectionMode,\n options: WordCounterOptions = {},\n): SectionedResult {\n const mode: WordCounterMode = options.mode ?? \"chunk\";\n if (section === \"all\") {\n const result = wordCounter(input, options);\n return {\n section,\n total: result.total,\n frontmatterType: null,\n items: [{ name: \"all\", source: \"content\", result }],\n };\n }\n\n const parsed = parseMarkdown(input);\n const frontmatterText = parsed.frontmatter ?? \"\";\n const contentText = parsed.content ?? \"\";\n\n let items: Array<{ name: string; source: \"frontmatter\" | \"content\"; result: WordCounterResult }> = [];\n\n if (section === \"frontmatter\") {\n items = buildSingleItem(\"frontmatter\", frontmatterText, mode, options, \"frontmatter\");\n } else if (section === \"content\") {\n items = buildSingleItem(\"content\", contentText, mode, options, \"content\");\n } else if (section === \"split\") {\n items = [\n ...buildSingleItem(\"frontmatter\", frontmatterText, mode, options, \"frontmatter\"),\n ...buildSingleItem(\"content\", contentText, mode, options, \"content\"),\n ];\n } else if (section === \"per-key\") {\n items = buildPerKeyItems(parsed.data, mode, options);\n } else if (section === \"split-per-key\") {\n items = [\n ...buildPerKeyItems(parsed.data, mode, options),\n ...buildSingleItem(\"content\", contentText, mode, options, \"content\"),\n ];\n }\n\n return {\n section,\n total: sumTotals(items),\n frontmatterType: parsed.frontmatterType,\n items,\n };\n}\n","import { countSections } from \"../markdown\";\nimport wordCounter, { segmentTextByLocale } from \"../wc\";\nimport type {\n DetectorCountSectionsOptions,\n DetectorLocaleOptions,\n DetectorWordCounterOptions,\n} from \"./types\";\n\nexport async function segmentTextByLocaleWithRegexDetector(\n text: string,\n options: DetectorLocaleOptions = {},\n) {\n return segmentTextByLocale(text, options);\n}\n\nexport async function wordCounterWithRegexDetector(\n text: string,\n options: DetectorWordCounterOptions = {},\n) {\n return wordCounter(text, options);\n}\n\nexport async function countSectionsWithRegexDetector(\n input: string,\n section: Parameters<typeof countSections>[1],\n options: DetectorCountSectionsOptions = {},\n) {\n return countSections(input, section, options);\n}\n","import {\n analyzeCharChunk,\n analyzeChunk,\n aggregateByLocale,\n aggregateCharsByLocale,\n} from \"../wc/analyze\";\nimport { resolveMode } from \"../wc/mode\";\nimport { createNonWordCollection, mergeNonWordCollections } from \"../wc/non-words\";\nimport type {\n CharBreakdown,\n CharCollectorBreakdown,\n ChunkBreakdown,\n ChunkWithSegments,\n LocaleChunk,\n NonWordCollection,\n WordCounterMode,\n WordCounterOptions,\n WordCounterResult,\n} from \"../wc/types\";\n\nfunction getNonWordTotal(nonWords: NonWordCollection): number {\n return (\n nonWords.counts.emoji +\n nonWords.counts.symbols +\n nonWords.counts.punctuation +\n (nonWords.counts.whitespace ?? 0)\n );\n}\n\nfunction collectNonWordsAggregate(\n analyzed: Array<{ nonWords?: NonWordCollection }>,\n enabled: boolean,\n): NonWordCollection | undefined {\n if (!enabled) {\n return undefined;\n }\n const collection = createNonWordCollection();\n for (const chunk of analyzed) {\n if (!chunk.nonWords) {\n continue;\n }\n mergeNonWordCollections(collection, chunk.nonWords);\n }\n return collection;\n}\n\nexport function buildWordCounterResultFromChunks(\n chunks: LocaleChunk[],\n options: WordCounterOptions = {},\n): WordCounterResult {\n const mode: WordCounterMode = resolveMode(options.mode, \"chunk\");\n const collectNonWords = Boolean(options.nonWords);\n const includeWhitespace = Boolean(options.includeWhitespace);\n\n if (mode === \"char\" || mode === \"char-collector\") {\n const analyzed = chunks.map((chunk) =>\n analyzeCharChunk(chunk, collectNonWords, includeWhitespace),\n );\n const total = analyzed.reduce((sum, chunk) => sum + chunk.chars, 0);\n const counts = collectNonWords\n ? {\n words: analyzed.reduce((sum, chunk) => sum + chunk.wordChars, 0),\n nonWords: analyzed.reduce((sum, chunk) => sum + chunk.nonWordChars, 0),\n total,\n }\n : undefined;\n\n if (mode === \"char\") {\n const items: CharBreakdown[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n chars: chunk.chars,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n const aggregated = aggregateCharsByLocale(analyzed);\n const items: CharCollectorBreakdown[] = aggregated.map((chunk) => ({\n locale: chunk.locale,\n chars: chunk.chars,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n const analyzed = chunks.map((chunk) =>\n analyzeChunk(chunk, collectNonWords, includeWhitespace),\n );\n const wordsTotal = analyzed.reduce((sum, chunk) => sum + chunk.words, 0);\n const nonWordsTotal = collectNonWords\n ? analyzed.reduce((sum, chunk) => {\n if (!chunk.nonWords) {\n return sum;\n }\n return sum + getNonWordTotal(chunk.nonWords);\n }, 0)\n : 0;\n const total = analyzed.reduce((sum, chunk) => {\n let chunkTotal = chunk.words;\n if (collectNonWords && chunk.nonWords) {\n chunkTotal += getNonWordTotal(chunk.nonWords);\n }\n return sum + chunkTotal;\n }, 0);\n\n const counts = collectNonWords ? { words: wordsTotal, nonWords: nonWordsTotal, total } : undefined;\n\n if (mode === \"segments\") {\n const items: ChunkWithSegments[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n words: chunk.words,\n segments: chunk.segments,\n nonWords: chunk.nonWords,\n }));\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n }\n\n if (mode === \"collector\") {\n const items = aggregateByLocale(analyzed);\n const nonWords = collectNonWordsAggregate(analyzed, collectNonWords);\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n nonWords,\n },\n };\n }\n\n const items: ChunkBreakdown[] = analyzed.map((chunk) => ({\n locale: chunk.locale,\n text: chunk.text,\n words: chunk.words,\n nonWords: chunk.nonWords,\n }));\n\n return {\n total,\n counts,\n breakdown: {\n mode,\n items,\n },\n };\n}\n","import { parseMarkdown } from \"../markdown\";\nimport type { SectionMode, SectionedResult } from \"../markdown\";\nimport type { WordCounterMode, WordCounterResult } from \"../wc/types\";\nimport type { DetectorCountSectionsOptions } from \"./types\";\nimport { wordCounterWithDetector } from \"./index\";\n\nfunction normalizeText(value: unknown): string {\n if (value == null) {\n return \"\";\n }\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nasync function buildPerKeyItems(\n data: Record<string, unknown> | null,\n options: DetectorCountSectionsOptions,\n): Promise<Array<{ name: string; source: \"frontmatter\"; result: WordCounterResult }>> {\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n return [];\n }\n\n return Promise.all(\n Object.entries(data).map(async ([key, value]) => {\n const valueText = normalizeText(value);\n const text = valueText ? `${key}: ${valueText}` : key;\n return {\n name: key,\n source: \"frontmatter\" as const,\n result: await wordCounterWithDetector(text, options),\n };\n }),\n );\n}\n\nasync function buildSingleItem(\n name: string,\n text: string,\n options: DetectorCountSectionsOptions,\n source: \"frontmatter\" | \"content\",\n): Promise<Array<{ name: string; source: \"frontmatter\" | \"content\"; result: WordCounterResult }>> {\n return [{ name, source, result: await wordCounterWithDetector(text, options) }];\n}\n\nfunction sumTotals(items: Array<{ result: WordCounterResult }>): number {\n return items.reduce((sum, item) => sum + item.result.total, 0);\n}\n\nexport async function countSectionsWithResolvedDetector(\n input: string,\n section: SectionMode,\n options: DetectorCountSectionsOptions = {},\n): Promise<SectionedResult> {\n const mode: WordCounterMode = options.mode ?? \"chunk\";\n if (section === \"all\") {\n const result = await wordCounterWithDetector(input, options);\n return {\n section,\n total: result.total,\n frontmatterType: null,\n items: [{ name: \"all\", source: \"content\", result }],\n };\n }\n\n const parsed = parseMarkdown(input);\n const frontmatterText = parsed.frontmatter ?? \"\";\n const contentText = parsed.content ?? \"\";\n\n let items: Array<{ name: string; source: \"frontmatter\" | \"content\"; result: WordCounterResult }> = [];\n\n if (section === \"frontmatter\") {\n items = await buildSingleItem(\"frontmatter\", frontmatterText, options, \"frontmatter\");\n } else if (section === \"content\") {\n items = await buildSingleItem(\"content\", contentText, options, \"content\");\n } else if (section === \"split\") {\n items = [\n ...(await buildSingleItem(\"frontmatter\", frontmatterText, options, \"frontmatter\")),\n ...(await buildSingleItem(\"content\", contentText, options, \"content\")),\n ];\n } else if (section === \"per-key\") {\n items = await buildPerKeyItems(parsed.data, options);\n } else if (section === \"split-per-key\") {\n items = [\n ...(await buildPerKeyItems(parsed.data, options)),\n ...(await buildSingleItem(\"content\", contentText, options, \"content\")),\n ];\n }\n\n return {\n section,\n total: sumTotals(items),\n frontmatterType: parsed.frontmatterType,\n items,\n };\n}\n","import { DEFAULT_HAN_TAG, DEFAULT_LOCALE } from \"../wc/locale-detect\";\n\nexport const LATIN_WASM_MIN_SCRIPT_CHARS = 24;\nexport const HANI_WASM_MIN_SCRIPT_CHARS = 12;\nexport const LATIN_WASM_MIN_CONFIDENCE = 0.75;\nexport const HANI_WASM_MIN_CONFIDENCE = 0.9;\nexport const LATIN_WASM_CORROBORATED_MIN_CONFIDENCE = 0.7;\n\nconst LATIN_SCRIPT_REGEX = /\\p{Script=Latin}/u;\nconst HAN_SCRIPT_REGEX = /\\p{Script=Han}/u;\n\nexport type DetectorRouteTag = typeof DEFAULT_LOCALE | typeof DEFAULT_HAN_TAG;\n\nexport type DetectorRoutePolicy = {\n routeTag: DetectorRouteTag;\n minScriptChars: number;\n minConfidence: number;\n requireReliable: boolean;\n};\n\nexport const DETECTOR_ROUTE_POLICIES: Record<DetectorRouteTag, DetectorRoutePolicy> = {\n [DEFAULT_LOCALE]: {\n routeTag: DEFAULT_LOCALE,\n minScriptChars: LATIN_WASM_MIN_SCRIPT_CHARS,\n minConfidence: LATIN_WASM_MIN_CONFIDENCE,\n requireReliable: true,\n },\n [DEFAULT_HAN_TAG]: {\n routeTag: DEFAULT_HAN_TAG,\n minScriptChars: HANI_WASM_MIN_SCRIPT_CHARS,\n minConfidence: HANI_WASM_MIN_CONFIDENCE,\n requireReliable: true,\n },\n};\n\nexport function isAmbiguousDetectorRoute(locale: string): locale is DetectorRouteTag {\n return locale === DEFAULT_LOCALE || locale === DEFAULT_HAN_TAG;\n}\n\nexport function countScriptBearingCharsForRoute(\n text: string,\n routeTag: DetectorRouteTag,\n): number {\n const matcher = routeTag === DEFAULT_HAN_TAG ? HAN_SCRIPT_REGEX : LATIN_SCRIPT_REGEX;\n let count = 0;\n for (const char of text) {\n if (matcher.test(char)) {\n count += 1;\n }\n }\n return count;\n}\n\nexport function shouldRunWasmDetector(text: string, routeTag: DetectorRouteTag): boolean {\n const policy = DETECTOR_ROUTE_POLICIES[routeTag];\n return countScriptBearingCharsForRoute(text, routeTag) >= policy.minScriptChars;\n}\n\nexport function normalizeDetectorSampleForRoute(\n text: string,\n routeTag: DetectorRouteTag,\n): string {\n const matcher = routeTag === DEFAULT_HAN_TAG ? HAN_SCRIPT_REGEX : LATIN_SCRIPT_REGEX;\n return [...text]\n .map((char) => {\n if (matcher.test(char)) {\n return char;\n }\n if (/\\s/u.test(char)) {\n return \" \";\n }\n return \" \";\n })\n .join(\"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n","import { existsSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport type { DetectorRouteTag } from \"./policy\";\nimport type { WhatlangWasmResult } from \"./whatlang-map\";\n\nconst GENERATED_FOLDER_NAME = \"wasm-language-detector\";\nconst GENERATED_MODULE_FILE = \"language_detector.js\";\nconst MAX_SEARCH_DEPTH = 8;\nconst requireFromHere = createRequire(import.meta.url);\n\nexport const WASM_DETECTOR_RUNTIME_UNAVAILABLE_MESSAGE =\n \"WASM detector runtime is unavailable. Run `bun run build:wasm` to generate it.\";\n\ntype WhatlangWasmModule = {\n detect_language: (text: string, routeTag: string) => WhatlangWasmResult | null;\n};\n\nlet modulePromise: Promise<WhatlangWasmModule> | null = null;\n\nfunction resolveCandidateModulePaths(): string[] {\n const moduleDir = dirname(fileURLToPath(import.meta.url));\n const candidates = new Set<string>();\n let currentDir = moduleDir;\n\n for (let depth = 0; depth < MAX_SEARCH_DEPTH; depth += 1) {\n candidates.add(join(currentDir, GENERATED_FOLDER_NAME, GENERATED_MODULE_FILE));\n candidates.add(join(currentDir, \"generated\", GENERATED_FOLDER_NAME, GENERATED_MODULE_FILE));\n\n const parentDir = dirname(currentDir);\n if (parentDir === currentDir) {\n break;\n }\n currentDir = parentDir;\n }\n\n return [...candidates];\n}\n\nfunction resolveWhatlangWasmModulePath(): string {\n for (const candidate of resolveCandidateModulePaths()) {\n if (existsSync(candidate)) {\n return candidate;\n }\n }\n\n throw new Error(WASM_DETECTOR_RUNTIME_UNAVAILABLE_MESSAGE);\n}\n\nasync function loadWhatlangWasmModule(): Promise<WhatlangWasmModule> {\n if (!modulePromise) {\n modulePromise = (async () => {\n const modulePath = resolveWhatlangWasmModulePath();\n return requireFromHere(modulePath) as WhatlangWasmModule;\n })();\n }\n\n return modulePromise;\n}\n\nexport async function detectWithWhatlangWasm(\n text: string,\n routeTag: DetectorRouteTag,\n): Promise<WhatlangWasmResult | null> {\n const wasmModule = await loadWhatlangWasmModule();\n return wasmModule.detect_language(text, routeTag);\n}\n","import { DEFAULT_HAN_TAG, DEFAULT_LOCALE } from \"../wc/locale-detect\";\nimport type { DetectorRouteTag } from \"./policy\";\nimport type { DetectorResult } from \"./types\";\n\nexport interface WhatlangWasmResult {\n lang: string;\n script: string;\n confidence: number;\n reliable: boolean;\n}\n\nconst LATIN_LANGUAGE_TAGS: Record<string, string> = {\n cat: \"ca\",\n ces: \"cs\",\n dan: \"da\",\n deu: \"de\",\n eng: \"en\",\n fin: \"fi\",\n fra: \"fr\",\n hun: \"hu\",\n ita: \"it\",\n lat: \"la\",\n nld: \"nl\",\n pol: \"pl\",\n por: \"pt\",\n ron: \"ro\",\n spa: \"es\",\n swe: \"sv\",\n tur: \"tr\",\n};\n\nconst HANI_LANGUAGE_TAGS: Record<string, string> = {\n cmn: \"zh\",\n jpn: \"ja\",\n};\n\nfunction hasSupportedScript(result: WhatlangWasmResult, routeTag: DetectorRouteTag): boolean {\n if (routeTag === DEFAULT_LOCALE) {\n return result.script === \"Latin\";\n }\n\n return result.script === \"Mandarin\";\n}\n\nfunction remapLanguageTag(\n lang: string,\n routeTag: DetectorRouteTag,\n): string | undefined {\n if (routeTag === DEFAULT_LOCALE) {\n return LATIN_LANGUAGE_TAGS[lang];\n }\n\n return HANI_LANGUAGE_TAGS[lang];\n}\n\nexport function remapWhatlangResult(\n result: WhatlangWasmResult,\n routeTag: DetectorRouteTag,\n): DetectorResult | null {\n if (!hasSupportedScript(result, routeTag)) {\n return null;\n }\n\n const tag = remapLanguageTag(result.lang, routeTag);\n if (!tag) {\n return null;\n }\n\n return {\n tag,\n confidence: result.confidence,\n reliable: result.reliable,\n source: \"wasm\",\n };\n}\n\nexport function getDetectorFallbackTag(routeTag: DetectorRouteTag): string {\n return routeTag === DEFAULT_HAN_TAG ? DEFAULT_HAN_TAG : DEFAULT_LOCALE;\n}\n","import { DEFAULT_HAN_TAG, DEFAULT_LOCALE } from \"../wc/locale-detect\";\nimport { segmentTextByLocale } from \"../wc\";\nimport type { LocaleChunk } from \"../wc/types\";\nimport { buildWordCounterResultFromChunks } from \"./result-builder\";\nimport { countSectionsWithResolvedDetector } from \"./sections\";\nimport {\n DETECTOR_ROUTE_POLICIES,\n LATIN_WASM_CORROBORATED_MIN_CONFIDENCE,\n isAmbiguousDetectorRoute,\n normalizeDetectorSampleForRoute,\n shouldRunWasmDetector,\n type DetectorRouteTag,\n} from \"./policy\";\nimport { detectWithWhatlangWasm, WASM_DETECTOR_RUNTIME_UNAVAILABLE_MESSAGE } from \"./whatlang-wasm\";\nimport { getDetectorFallbackTag, remapWhatlangResult } from \"./whatlang-map\";\nimport type {\n DetectorCountSectionsOptions,\n DetectorLocaleOptions,\n DetectorWordCounterOptions,\n} from \"./types\";\n\nfunction shouldAcceptDetectorTag(\n routeTag: DetectorRouteTag,\n confidence: number | undefined,\n reliable: boolean | undefined,\n): boolean {\n const policy = DETECTOR_ROUTE_POLICIES[routeTag];\n if (policy.requireReliable && reliable !== true) {\n return false;\n }\n\n if (confidence === undefined) {\n return false;\n }\n\n return confidence >= policy.minConfidence;\n}\n\ntype DetectorWindow = {\n routeTag: DetectorRouteTag;\n startIndex: number;\n endIndex: number;\n text: string;\n};\n\nfunction buildDetectorWindows(chunks: LocaleChunk[]): DetectorWindow[] {\n const windows: DetectorWindow[] = [];\n\n for (let index = 0; index < chunks.length; index += 1) {\n const chunk = chunks[index];\n if (!chunk || !isAmbiguousDetectorRoute(chunk.locale)) {\n continue;\n }\n\n const previousWindow = windows[windows.length - 1];\n if (\n previousWindow &&\n previousWindow.routeTag === chunk.locale &&\n previousWindow.endIndex === index - 1\n ) {\n previousWindow.endIndex = index;\n previousWindow.text += chunk.text;\n continue;\n }\n\n windows.push({\n routeTag: chunk.locale,\n startIndex: index,\n endIndex: index,\n text: chunk.text,\n });\n }\n\n return windows;\n}\n\nasync function resolveWindowLocale(window: DetectorWindow): Promise<string> {\n if (!shouldRunWasmDetector(window.text, window.routeTag)) {\n return window.routeTag;\n }\n\n const rawResult = await detectWithWhatlangWasm(window.text, window.routeTag);\n const rawRemapped = rawResult ? remapWhatlangResult(rawResult, window.routeTag) : null;\n\n const normalizedSample = normalizeDetectorSampleForRoute(window.text, window.routeTag);\n const normalizedResult =\n normalizedSample.length > 0 && normalizedSample !== window.text\n ? await detectWithWhatlangWasm(normalizedSample, window.routeTag)\n : null;\n const normalizedRemapped = normalizedResult\n ? remapWhatlangResult(normalizedResult, window.routeTag)\n : null;\n\n const candidates = [rawRemapped, normalizedRemapped].filter((value) => value !== null);\n if (candidates.length === 0) {\n return getDetectorFallbackTag(window.routeTag);\n }\n\n const strongestCandidate = candidates.reduce((best, current) => {\n if (!best) {\n return current;\n }\n return (current.confidence ?? 0) > (best.confidence ?? 0) ? current : best;\n }, candidates[0]);\n\n if (\n strongestCandidate &&\n shouldAcceptDetectorTag(\n window.routeTag,\n strongestCandidate.confidence,\n strongestCandidate.reliable,\n )\n ) {\n return strongestCandidate.tag;\n }\n\n if (\n window.routeTag === DEFAULT_LOCALE &&\n rawRemapped &&\n normalizedRemapped &&\n rawRemapped.tag === normalizedRemapped.tag\n ) {\n const corroboratedConfidence = Math.max(\n rawRemapped.confidence ?? 0,\n normalizedRemapped.confidence ?? 0,\n );\n if (corroboratedConfidence >= LATIN_WASM_CORROBORATED_MIN_CONFIDENCE) {\n return rawRemapped.tag;\n }\n }\n\n return getDetectorFallbackTag(window.routeTag);\n}\n\nexport { WASM_DETECTOR_RUNTIME_UNAVAILABLE_MESSAGE };\n\nexport async function segmentTextByLocaleWithWasmDetector(\n text: string,\n options: DetectorLocaleOptions = {},\n) {\n const chunks = segmentTextByLocale(text, options);\n const resolved = [...chunks];\n const windows = buildDetectorWindows(chunks);\n\n for (const window of windows) {\n const resolvedLocale = await resolveWindowLocale(window);\n for (let index = window.startIndex; index <= window.endIndex; index += 1) {\n const chunk = resolved[index];\n if (!chunk) {\n continue;\n }\n resolved[index] = {\n ...chunk,\n locale: resolvedLocale,\n };\n }\n }\n\n return resolved;\n}\n\nexport async function wordCounterWithWasmDetector(\n text: string,\n options: DetectorWordCounterOptions = {},\n) {\n const chunks = await segmentTextByLocaleWithWasmDetector(text, options);\n return buildWordCounterResultFromChunks(chunks, options);\n}\n\nexport async function countSectionsWithWasmDetector(\n input: string,\n section: Parameters<typeof countSectionsWithResolvedDetector>[1],\n options: DetectorCountSectionsOptions = {},\n) {\n return countSectionsWithResolvedDetector(input, section, options);\n}\n","import type { SectionMode } from \"../markdown\";\nimport type { LocaleChunk } from \"../wc/types\";\nimport {\n countSectionsWithRegexDetector,\n segmentTextByLocaleWithRegexDetector,\n wordCounterWithRegexDetector,\n} from \"./none\";\nimport {\n countSectionsWithWasmDetector,\n segmentTextByLocaleWithWasmDetector,\n WASM_DETECTOR_RUNTIME_UNAVAILABLE_MESSAGE,\n wordCounterWithWasmDetector,\n} from \"./wasm\";\nimport type {\n DetectorCountSectionsOptions,\n DetectorLocaleOptions,\n DetectorMode,\n DetectorResult,\n DetectorSource,\n DetectorWordCounterOptions,\n} from \"./types\";\n\nexport type {\n DetectorCountSections,\n DetectorCountSectionsOptions,\n DetectorCountResult,\n DetectorLocaleOptions,\n DetectorMode,\n DetectorResult,\n DetectorRuntimeOptions,\n DetectorSource,\n DetectorWordCounterOptions,\n} from \"./types\";\n\nexport const DETECTOR_MODES: DetectorMode[] = [\"regex\", \"wasm\"];\nexport const DEFAULT_DETECTOR_MODE: DetectorMode = \"regex\";\n\nexport function resolveDetectorMode(mode?: DetectorMode): DetectorMode {\n return mode ?? DEFAULT_DETECTOR_MODE;\n}\n\nexport function assertDetectorModeImplemented(mode?: DetectorMode): void {\n void mode;\n}\n\nexport async function segmentTextByLocaleWithDetector(\n text: string,\n options: DetectorLocaleOptions = {},\n): Promise<LocaleChunk[]> {\n const mode = resolveDetectorMode(options.detector);\n if (mode === \"wasm\") {\n return segmentTextByLocaleWithWasmDetector(text, options);\n }\n return segmentTextByLocaleWithRegexDetector(text, options);\n}\n\nexport async function wordCounterWithDetector(\n text: string,\n options: DetectorWordCounterOptions = {},\n) {\n const mode = resolveDetectorMode(options.detector);\n if (mode === \"wasm\") {\n return wordCounterWithWasmDetector(text, options);\n }\n return wordCounterWithRegexDetector(text, options);\n}\n\nexport async function countSectionsWithDetector(\n input: string,\n section: SectionMode,\n options: DetectorCountSectionsOptions = {},\n) {\n const mode = resolveDetectorMode(options.detector);\n if (mode === \"wasm\") {\n return countSectionsWithWasmDetector(input, section, options);\n }\n return countSectionsWithRegexDetector(input, section, options);\n}\n\nexport const DETECTOR_SOURCES: DetectorSource[] = [\"script\", \"hint\", \"wasm\"];\nexport const DEFAULT_DETECTOR_RESULT_SOURCE: DetectorSource = \"script\";\nexport { WASM_DETECTOR_RUNTIME_UNAVAILABLE_MESSAGE };\n\nexport function createDetectorResult(\n tag: string,\n source: DetectorSource = DEFAULT_DETECTOR_RESULT_SOURCE,\n confidence?: number,\n reliable?: boolean,\n): DetectorResult {\n return {\n tag,\n source,\n ...(confidence === undefined ? {} : { confidence }),\n ...(reliable === undefined ? {} : { reliable }),\n };\n}\n","import { countSections } from \"../../markdown\";\nimport type { SectionMode, SectionedResult } from \"../../markdown\";\nimport { appendAll } from \"../../utils/append-all\";\nimport wordCounter, { type NonWordCollection, type WordCounterResult } from \"../../wc\";\nimport { createNonWordCollection, mergeNonWordCollections } from \"../../wc/non-words\";\nimport type { BatchFileInput, BatchFileResult, BatchSummary } from \"../types\";\nimport type { BatchProgressSnapshot } from \"../progress/reporter\";\n\ntype BuildBatchSummaryOptions = {\n onFileCounted?: (snapshot: BatchProgressSnapshot) => void;\n onFinalizeStart?: () => void;\n preserveCollectorSegments?: boolean;\n};\n\ntype FinalizeBatchSummaryFromFileResultsOptions = {\n onFinalizeStart?: () => void;\n preserveCollectorSegments?: boolean;\n};\n\nfunction mergeWordCounterResult(\n left: WordCounterResult,\n right: WordCounterResult,\n preserveCollectorSegments: boolean,\n): WordCounterResult {\n if (left.breakdown.mode !== right.breakdown.mode) {\n throw new Error(\"Cannot merge different breakdown modes.\");\n }\n\n const total = left.total + right.total;\n const counts =\n left.counts || right.counts\n ? {\n words: (left.counts?.words ?? 0) + (right.counts?.words ?? 0),\n nonWords: (left.counts?.nonWords ?? 0) + (right.counts?.nonWords ?? 0),\n total: (left.counts?.total ?? 0) + (right.counts?.total ?? 0),\n }\n : undefined;\n\n if (left.breakdown.mode === \"chunk\" && right.breakdown.mode === \"chunk\") {\n return {\n total,\n counts,\n breakdown: {\n mode: \"chunk\",\n items: [...left.breakdown.items, ...right.breakdown.items],\n },\n };\n }\n\n if (left.breakdown.mode === \"segments\" && right.breakdown.mode === \"segments\") {\n return {\n total,\n counts,\n breakdown: {\n mode: \"segments\",\n items: [...left.breakdown.items, ...right.breakdown.items],\n },\n };\n }\n\n if (left.breakdown.mode === \"char\" && right.breakdown.mode === \"char\") {\n return {\n total,\n counts,\n breakdown: {\n mode: \"char\",\n items: [...left.breakdown.items, ...right.breakdown.items],\n },\n };\n }\n\n if (\n left.breakdown.mode === \"char-collector\" &&\n right.breakdown.mode === \"char-collector\"\n ) {\n const localeOrder: string[] = [];\n const mergedByLocale = new Map<\n string,\n {\n locale: string;\n chars: number;\n nonWords?: NonWordCollection;\n }\n >();\n\n const addItems = (items: typeof left.breakdown.items): void => {\n for (const item of items) {\n const existing = mergedByLocale.get(item.locale);\n if (existing) {\n existing.chars += item.chars;\n if (item.nonWords) {\n if (!existing.nonWords) {\n existing.nonWords = createNonWordCollection();\n }\n mergeNonWordCollections(existing.nonWords, item.nonWords);\n }\n continue;\n }\n\n localeOrder.push(item.locale);\n mergedByLocale.set(item.locale, {\n locale: item.locale,\n chars: item.chars,\n nonWords: item.nonWords\n ? mergeNonWordCollections(createNonWordCollection(), item.nonWords)\n : undefined,\n });\n }\n };\n\n addItems(left.breakdown.items);\n addItems(right.breakdown.items);\n\n return {\n total,\n counts,\n breakdown: {\n mode: \"char-collector\",\n items: localeOrder.map((locale) => {\n const value = mergedByLocale.get(locale);\n if (!value) {\n throw new Error(`Missing char-collector entry for locale: ${locale}`);\n }\n return value;\n }),\n },\n };\n }\n\n if (left.breakdown.mode === \"collector\" && right.breakdown.mode === \"collector\") {\n const localeOrder: string[] = [];\n const mergedByLocale = new Map<\n string,\n {\n locale: string;\n words: number;\n segments: string[];\n }\n >();\n\n const addItems = (items: typeof left.breakdown.items): void => {\n for (const item of items) {\n const existing = mergedByLocale.get(item.locale);\n if (existing) {\n existing.words += item.words;\n if (preserveCollectorSegments) {\n appendAll(existing.segments, item.segments);\n }\n continue;\n }\n\n localeOrder.push(item.locale);\n mergedByLocale.set(item.locale, {\n locale: item.locale,\n words: item.words,\n segments: preserveCollectorSegments ? [...item.segments] : [],\n });\n }\n };\n\n addItems(left.breakdown.items);\n addItems(right.breakdown.items);\n\n let mergedNonWords: NonWordCollection | undefined;\n if (left.breakdown.nonWords || right.breakdown.nonWords) {\n mergedNonWords = createNonWordCollection();\n if (left.breakdown.nonWords) {\n mergeNonWordCollections(mergedNonWords, left.breakdown.nonWords);\n }\n if (right.breakdown.nonWords) {\n mergeNonWordCollections(mergedNonWords, right.breakdown.nonWords);\n }\n }\n\n return {\n total,\n counts,\n breakdown: {\n mode: \"collector\",\n items: localeOrder.map((locale) => {\n const value = mergedByLocale.get(locale);\n if (!value) {\n throw new Error(`Missing collector entry for locale: ${locale}`);\n }\n return value;\n }),\n nonWords: mergedNonWords,\n },\n };\n }\n\n return {\n total,\n counts,\n breakdown: left.breakdown,\n };\n}\n\nfunction aggregateWordCounterResults(\n results: WordCounterResult[],\n preserveCollectorSegments: boolean,\n): WordCounterResult {\n if (results.length === 0) {\n return wordCounter(\"\", { mode: \"chunk\" });\n }\n\n const first = results[0];\n if (!first) {\n return wordCounter(\"\", { mode: \"chunk\" });\n }\n\n let aggregate = first;\n for (let index = 1; index < results.length; index += 1) {\n const current = results[index];\n if (!current) {\n continue;\n }\n aggregate = mergeWordCounterResult(aggregate, current, preserveCollectorSegments);\n }\n\n return aggregate;\n}\n\nfunction buildSectionKey(name: string, source: \"frontmatter\" | \"content\"): string {\n return `${source}:${name}`;\n}\n\nfunction aggregateSectionedResults(\n results: SectionedResult[],\n preserveCollectorSegments: boolean,\n): SectionedResult {\n if (results.length === 0) {\n return {\n section: \"all\",\n total: 0,\n frontmatterType: null,\n items: [],\n };\n }\n\n const section = results[0]?.section ?? \"all\";\n const grouped = new Map<\n string,\n {\n name: string;\n source: \"frontmatter\" | \"content\";\n items: WordCounterResult[];\n }\n >();\n let total = 0;\n let frontmatterType = results[0]?.frontmatterType ?? null;\n\n for (const result of results) {\n total += result.total;\n\n if (result.section !== section) {\n throw new Error(\"Cannot aggregate section results with different section modes.\");\n }\n\n if (frontmatterType !== result.frontmatterType) {\n frontmatterType = null;\n }\n\n for (const item of result.items) {\n const key = buildSectionKey(item.name, item.source);\n const existing = grouped.get(key);\n if (!existing) {\n grouped.set(key, {\n name: item.name,\n source: item.source,\n items: [item.result],\n });\n continue;\n }\n\n existing.items.push(item.result);\n }\n }\n\n const sourceOrder = new Map<\"frontmatter\" | \"content\", number>([\n [\"frontmatter\", 0],\n [\"content\", 1],\n ]);\n\n const items = [...grouped.values()]\n .sort((left, right) => {\n const sourceDiff = (sourceOrder.get(left.source) ?? 0) - (sourceOrder.get(right.source) ?? 0);\n if (sourceDiff !== 0) {\n return sourceDiff;\n }\n return left.name.localeCompare(right.name);\n })\n .map((entry) => ({\n name: entry.name,\n source: entry.source,\n result: aggregateWordCounterResults(entry.items, preserveCollectorSegments),\n }));\n\n return {\n section,\n total,\n frontmatterType,\n items,\n };\n}\n\nfunction stripCollectorSegmentsFromWordCounterResult(result: WordCounterResult): void {\n if (result.breakdown.mode !== \"collector\") {\n return;\n }\n\n for (const item of result.breakdown.items) {\n item.segments = [];\n }\n}\n\nfunction stripCollectorSegmentsFromSectionedResult(result: SectionedResult): void {\n for (const item of result.items) {\n stripCollectorSegmentsFromWordCounterResult(item.result);\n }\n}\n\nexport function compactCollectorSegmentsInCountResult(\n result: WordCounterResult | SectionedResult,\n): void {\n if (\"section\" in result) {\n stripCollectorSegmentsFromSectionedResult(result);\n return;\n }\n\n stripCollectorSegmentsFromWordCounterResult(result);\n}\n\nexport async function buildBatchSummary(\n inputs: BatchFileInput[],\n section: SectionMode,\n wcOptions: Parameters<typeof wordCounter>[1],\n options: BuildBatchSummaryOptions = {},\n): Promise<BatchSummary> {\n const preserveCollectorSegments = options.preserveCollectorSegments ?? true;\n const files: BatchFileResult[] = [];\n\n for (const input of inputs) {\n const result =\n section === \"all\"\n ? wordCounter(input.content, wcOptions)\n : countSections(input.content, section, wcOptions);\n\n if (!preserveCollectorSegments) {\n compactCollectorSegmentsInCountResult(result);\n }\n\n files.push({\n path: input.path,\n result,\n });\n\n options.onFileCounted?.({\n completed: files.length,\n total: inputs.length,\n });\n }\n\n return finalizeBatchSummaryFromFileResults(files, section, wcOptions, {\n onFinalizeStart: options.onFinalizeStart,\n preserveCollectorSegments: options.preserveCollectorSegments,\n });\n}\n\nexport function finalizeBatchSummaryFromFileResults(\n files: BatchFileResult[],\n section: SectionMode,\n wcOptions: Parameters<typeof wordCounter>[1],\n options: FinalizeBatchSummaryFromFileResultsOptions = {},\n): BatchSummary {\n const preserveCollectorSegments = options.preserveCollectorSegments ?? true;\n if (!preserveCollectorSegments) {\n for (const file of files) {\n compactCollectorSegmentsInCountResult(file.result);\n }\n }\n\n options.onFinalizeStart?.();\n if (files.length === 0) {\n return {\n files,\n skipped: [],\n aggregate:\n section === \"all\"\n ? wordCounter(\"\", wcOptions)\n : {\n section,\n total: 0,\n frontmatterType: null,\n items: [],\n },\n };\n }\n\n const aggregate =\n section === \"all\"\n ? aggregateWordCounterResults(\n files.map((file) => file.result as WordCounterResult),\n preserveCollectorSegments,\n )\n : aggregateSectionedResults(\n files.map((file) => file.result as SectionedResult),\n preserveCollectorSegments,\n );\n\n return {\n files,\n skipped: [],\n aggregate,\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport type { BatchFileInput, BatchSkip } from \"../types\";\n\nexport function isProbablyBinary(buffer: Buffer): boolean {\n if (buffer.length === 0) {\n return false;\n }\n\n const sampleSize = Math.min(buffer.length, 1024);\n let suspicious = 0;\n\n for (let index = 0; index < sampleSize; index += 1) {\n const byte = buffer[index] ?? 0;\n\n if (byte === 0) {\n return true;\n }\n\n if (byte === 9 || byte === 10 || byte === 13) {\n continue;\n }\n\n if (byte >= 32 && byte <= 126) {\n continue;\n }\n\n if (byte >= 128) {\n continue;\n }\n\n suspicious += 1;\n }\n\n return suspicious / sampleSize > 0.3;\n}\n\nexport async function loadBatchInputs(\n filePaths: string[],\n): Promise<{ files: BatchFileInput[]; skipped: BatchSkip[] }> {\n const files: BatchFileInput[] = [];\n const skipped: BatchSkip[] = [];\n\n for (const filePath of filePaths) {\n let buffer: Buffer;\n try {\n buffer = await readFile(filePath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n skipped.push({ path: filePath, reason: `not readable: ${message}` });\n continue;\n }\n\n if (isProbablyBinary(buffer)) {\n skipped.push({ path: filePath, reason: \"binary file\" });\n continue;\n }\n\n files.push({\n path: filePath,\n content: buffer.toString(\"utf8\"),\n });\n }\n\n return { files, skipped };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { parentPort, workerData } from \"node:worker_threads\";\nimport { countSections } from \"../../../../markdown\";\nimport { countSectionsWithDetector, wordCounterWithDetector } from \"../../../../detector\";\nimport wordCounter from \"../../../../wc\";\nimport { compactCollectorSegmentsInCountResult } from \"../../aggregate\";\nimport { isProbablyBinary } from \"../../../path/load\";\nimport type {\n WorkerConfig,\n WorkerRequestMessage,\n WorkerResponseMessage,\n} from \"./protocol\";\n\nconst config = workerData as WorkerConfig;\n\nif (!parentPort) {\n throw new Error(\"Worker protocol init failed: missing parentPort.\");\n}\n\nparentPort.on(\"message\", async (message: WorkerRequestMessage) => {\n if (message.type === \"shutdown\") {\n parentPort?.close();\n return;\n }\n\n const path = message.path;\n\n let buffer: Buffer;\n try {\n buffer = await readFile(path);\n } catch (error) {\n const code =\n typeof error === \"object\" && error !== null && \"code\" in error\n ? String(error.code)\n : undefined;\n const messageText = error instanceof Error ? error.message : String(error);\n\n if (code === \"EMFILE\" || code === \"ENFILE\") {\n const response: WorkerResponseMessage = {\n type: \"fatal\",\n taskId: message.taskId,\n index: message.index,\n path,\n code,\n message: messageText,\n };\n parentPort?.postMessage(response);\n return;\n }\n\n const response: WorkerResponseMessage = {\n type: \"result\",\n taskId: message.taskId,\n index: message.index,\n payload: {\n kind: \"skip\",\n skip: { path, reason: `not readable: ${messageText}` },\n },\n };\n parentPort?.postMessage(response);\n return;\n }\n\n if (isProbablyBinary(buffer)) {\n const response: WorkerResponseMessage = {\n type: \"result\",\n taskId: message.taskId,\n index: message.index,\n payload: {\n kind: \"skip\",\n skip: { path, reason: \"binary file\" },\n },\n };\n parentPort?.postMessage(response);\n return;\n }\n\n try {\n const content = buffer.toString(\"utf8\");\n const result =\n config.detectorMode === \"regex\"\n ? config.section === \"all\"\n ? wordCounter(content, config.wcOptions)\n : countSections(content, config.section, config.wcOptions)\n : config.section === \"all\"\n ? await wordCounterWithDetector(content, {\n ...config.wcOptions,\n detector: config.detectorMode,\n })\n : await countSectionsWithDetector(content, config.section, {\n ...config.wcOptions,\n detector: config.detectorMode,\n });\n\n if (!config.preserveCollectorSegments) {\n compactCollectorSegmentsInCountResult(result);\n }\n\n const response: WorkerResponseMessage = {\n type: \"result\",\n taskId: message.taskId,\n index: message.index,\n payload: {\n kind: \"file\",\n file: {\n path,\n result,\n },\n },\n };\n parentPort?.postMessage(response);\n } catch (error) {\n const code =\n typeof error === \"object\" && error !== null && \"code\" in error\n ? String(error.code)\n : undefined;\n const messageText = error instanceof Error ? error.message : String(error);\n const response: WorkerResponseMessage = {\n type: \"fatal\",\n taskId: message.taskId,\n index: message.index,\n path,\n code,\n message: messageText,\n };\n parentPort?.postMessage(response);\n }\n});\n"],"mappings":"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"}
@@ -3,7 +3,6 @@
3
3
  import { existsSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  import { Worker } from "node:worker_threads";
6
-
7
6
  //#region src/cli/batch/jobs/worker-pool.ts
8
7
  var WorkerPoolUnavailableError = class extends Error {};
9
8
  var WorkerPoolTaskFatalError = class extends Error {
@@ -24,6 +23,9 @@ function resolveWorkerEntryUrl() {
24
23
  for (const candidate of candidates) if (existsSync(fileURLToPath(candidate))) return candidate;
25
24
  return null;
26
25
  }
26
+ function isWorkerThreadsAvailable() {
27
+ return typeof Worker === "function";
28
+ }
27
29
  function isWorkerResponseMessage(value) {
28
30
  if (typeof value !== "object" || value === null) return false;
29
31
  if (!("type" in value)) return false;
@@ -113,6 +115,7 @@ async function countBatchInputsWithWorkerPool(options) {
113
115
  try {
114
116
  worker = new Worker(workerEntryUrl, { workerData: {
115
117
  section: options.section,
118
+ detectorMode: options.detectorMode,
116
119
  wcOptions: options.wcOptions,
117
120
  preserveCollectorSegments: options.preserveCollectorSegments
118
121
  } });
@@ -181,7 +184,7 @@ async function countBatchInputsWithWorkerPool(options) {
181
184
  }
182
185
  });
183
186
  }
184
-
185
187
  //#endregion
186
- export { WorkerPoolTaskFatalError, WorkerPoolUnavailableError, countBatchInputsWithWorkerPool };
188
+ export { WorkerPoolTaskFatalError, WorkerPoolUnavailableError, countBatchInputsWithWorkerPool, isWorkerThreadsAvailable, resolveWorkerEntryUrl };
189
+
187
190
  //# sourceMappingURL=worker-pool.mjs.map