@storyteller-platform/align 0.1.6 → 0.1.7

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.
@@ -0,0 +1,8 @@
1
+ import * as _storyteller_platform_transliteration from '@storyteller-platform/transliteration';
2
+
3
+ declare function slugify(text: string, locale: Intl.Locale): Promise<{
4
+ result: string;
5
+ mapping: _storyteller_platform_transliteration.Mapping;
6
+ }>;
7
+
8
+ export { slugify };
@@ -0,0 +1,102 @@
1
+ import "../chunk-BIEQXUOY.js";
2
+ import { getCurrency } from "locale-currency";
3
+ import { toWords } from "to-words";
4
+ import { slugify as transliterateSlugify } from "@storyteller-platform/transliteration";
5
+ const replacerMap = /* @__PURE__ */ new WeakMap();
6
+ function createReplacers(locale) {
7
+ const maximizedLocale = locale.maximize();
8
+ const demoNumber = 123456.789;
9
+ const currencyFormat = new Intl.NumberFormat(locale, {
10
+ style: "currency",
11
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
12
+ currency: getCurrency(locale.maximize().region)
13
+ });
14
+ const currencyParts = currencyFormat.formatToParts(demoNumber);
15
+ const currencySymbols = currencyParts.reduce(
16
+ (acc, part, index) => {
17
+ if (part.type === "group") {
18
+ return {
19
+ ...acc,
20
+ group: part.value
21
+ };
22
+ }
23
+ if (part.type === "decimal") {
24
+ return {
25
+ ...acc,
26
+ decimal: part.value
27
+ };
28
+ }
29
+ if (part.type === "currency") {
30
+ return {
31
+ ...acc,
32
+ currency: part.value,
33
+ currencyLeading: index === 0
34
+ };
35
+ }
36
+ return acc;
37
+ },
38
+ { group: "", decimal: "", currency: "", currencyLeading: true }
39
+ );
40
+ const numeralRegexPart = `(\\p{Number}[\\p{Number}${currencySymbols.group}]*(?:[${currencySymbols.decimal}]\\p{Number}*)?)`;
41
+ const currencyRegex = currencySymbols.currencyLeading ? new RegExp(`[${currencySymbols.currency}]\\s?${numeralRegexPart}`, "gu") : new RegExp(`${numeralRegexPart}\\s?[${currencySymbols.currency}]`, "gu");
42
+ function currencyReplacer(match) {
43
+ const numeralMatch = match[1];
44
+ if (!numeralMatch) return match[0];
45
+ const normalizedNumeral = numeralMatch.replaceAll(new RegExp(`\\${currencySymbols.group}`, "g"), "").replace(new RegExp(`\\${currencySymbols.decimal}`), ".");
46
+ const number = parseFloat(normalizedNumeral);
47
+ return toWords(number, {
48
+ localeCode: `${maximizedLocale.language}-${maximizedLocale.region}`,
49
+ currency: true,
50
+ doNotAddOnly: true
51
+ });
52
+ }
53
+ const numberFormat = new Intl.NumberFormat(locale);
54
+ const numberParts = numberFormat.formatToParts(demoNumber);
55
+ const numberSymbols = numberParts.reduce(
56
+ (acc, part) => {
57
+ if (part.type === "group") {
58
+ return {
59
+ ...acc,
60
+ group: part.value
61
+ };
62
+ }
63
+ if (part.type === "decimal") {
64
+ return {
65
+ ...acc,
66
+ decimal: part.value
67
+ };
68
+ }
69
+ return acc;
70
+ },
71
+ { group: "", decimal: "" }
72
+ );
73
+ const numberRegex = new RegExp(
74
+ `(\\p{Number}[\\p{Number}${numberSymbols.group}]*(?:[${numberSymbols.decimal}]\\p{Number}*)?)`,
75
+ "gu"
76
+ );
77
+ function numberReplacer(match) {
78
+ const numeralMatch = match[1];
79
+ if (!numeralMatch) return match[0];
80
+ const normalizedNumeral = numeralMatch.replaceAll(new RegExp(`\\${numberSymbols.group}`, "g"), "").replace(new RegExp(`\\${numberSymbols.decimal}`), ".");
81
+ const number = parseFloat(normalizedNumeral);
82
+ return toWords(number, {
83
+ localeCode: `${maximizedLocale.language}-${maximizedLocale.region}`
84
+ });
85
+ }
86
+ return [
87
+ [currencyRegex, currencyReplacer],
88
+ [numberRegex, numberReplacer]
89
+ ];
90
+ }
91
+ async function slugify(text, locale) {
92
+ const replacers = replacerMap.get(locale) ?? createReplacers(locale);
93
+ replacerMap.set(locale, replacers);
94
+ const { result, mapping } = await transliterateSlugify(text, {
95
+ allowedChars: "a-zA-Z0-9",
96
+ replace: replacers
97
+ });
98
+ return { result, mapping };
99
+ }
100
+ export {
101
+ slugify
102
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storyteller-platform/align",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "A library and CLI for automatically aligning audiobooks and EPUBs to produce Media Overlays",
5
5
  "author": "Shane Friedman",
6
6
  "license": "MIT",
@@ -57,14 +57,17 @@
57
57
  "@optique/core": "^0.10.7",
58
58
  "@optique/run": "^0.10.7",
59
59
  "@storyteller-platform/audiobook": "^0.3.8",
60
- "@storyteller-platform/epub": "^0.4.6",
61
- "@storyteller-platform/ghost-story": "^0.1.3",
60
+ "@storyteller-platform/epub": "^0.4.7",
61
+ "@storyteller-platform/ghost-story": "^0.1.4",
62
+ "@storyteller-platform/transliteration": "^3.1.0",
62
63
  "chalk": "^5.4.1",
63
64
  "cli-progress": "^3.12.0",
64
65
  "esbuild": "^0.27.3",
66
+ "locale-currency": "^1.0.0",
65
67
  "memoize": "^10.2.0",
66
68
  "pino": "^10.3.1",
67
69
  "pino-pretty": "^13.1.3",
70
+ "to-words": "^5.3.0",
68
71
  "zod": "^3.24.0"
69
72
  },
70
73
  "devDependencies": {