@mailwoman/variant-aliases 9.1.0 → 9.3.0

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.
@@ -13,16 +13,18 @@
13
13
  * - `docs/articles/understanding/exotic-poi/regional-variant-queries.md` for the linguistic
14
14
  * background and the source tables this data is derived from.
15
15
  * - Issue #166 for the v0.6.0+ runtime integration plan (kind classifier consumes this table to emit
16
- * `kind=amenity` / `kind=brand` proposals, gated by locale-gate output).
16
+ * `kind=amenity` / `kind=brand` proposals, filtered by `@mailwoman/locale-hint` output).
17
17
  */
18
18
 
19
- export { VARIANT_ALIAS_VERSION, getAllAliases, lookupVariantAliases } from "./lookup.ts"
19
+ export { VARIANT_ALIAS_VERSION, getAllAliases, lookupVariantAliases, resolveLocaleScope } from "#lookup"
20
20
 
21
21
  export type {
22
22
  AliasLookupResult,
23
23
  AmenityAlias,
24
24
  BrandAlias,
25
+ LocaleScope,
26
+ LocaleScopeMatch,
25
27
  VariantAlias,
26
28
  VariantAliasTable,
27
29
  VariantKind,
28
- } from "./types.ts"
30
+ } from "#types"
@@ -6,44 +6,26 @@
6
6
  * Regional variant alias lookup. Given a token (or short phrase) and a detected locale, return the
7
7
  * canonical amenity category or brand it refers to.
8
8
  *
9
- * This is the data-side foundation for #166 (variant alias table + locale-gated category matching).
9
+ * This is the data-side foundation for #166 (variant alias table + locale-restricted category matching).
10
10
  * The runtime integration into the kind classifier is v0.6.0+ work.
11
11
  */
12
12
 
13
- import { existsSync, readFileSync } from "node:fs"
14
- import { resolve } from "node:path"
13
+ import { readLocalJSONFile } from "@mailwoman/core/fs/readers"
14
+ import { resolvePackagedDataPath } from "@mailwoman/core/module/packaged-data"
15
15
 
16
- import type { AliasLookupResult, VariantAlias, VariantAliasTable } from "./types.ts"
16
+ import type { AliasLookupResult, LocaleScopeMatch, VariantAlias, VariantAliasTable } from "#types"
17
17
 
18
18
  const moduleDir = import.meta.dirname
19
19
 
20
20
  /**
21
- * Read the shipped alias table.
22
- *
23
- * `data/` sits at the package root (it is a `files` entry), and this module sits either at that root — running from
24
- * source — or under `out/` when compiled, so there are exactly two places to look. The probe tests for the FILE:
25
- * probing by attempting a parse folds a corrupt table into "not this candidate", and the package then reports a missing
26
- * table it is looking straight at.
27
- *
28
- * `@mailwoman/poi-taxonomy` carries the same loader against its own tables. The duplication is deliberate — both
29
- * packages declare ZERO dependencies and publish independently, so sharing one would mean one taking a dependency on
30
- * the other for eight lines.
21
+ * Read the shipped alias table, located by the shared source-tree/`out/` probe in
22
+ * `@mailwoman/core/module/packaged-data`.
31
23
  */
32
- function loadTable(): VariantAliasTable {
33
- const candidates = [resolve(moduleDir, "data", "aliases.json"), resolve(moduleDir, "..", "data", "aliases.json")]
34
- const found = candidates.find((candidate) => existsSync(candidate))
35
-
36
- if (!found) {
37
- throw new Error(`variant-aliases: could not find data/aliases.json — looked in ${candidates.join(", ")}`)
38
- }
39
-
40
- // A corrupt shipped table is a broken build, and the SyntaxError names the offset. Zero dependencies here, so
41
- // `@mailwoman/core`'s parse wrappers are deliberately out of reach.
42
- // oxlint-disable-next-line no-restricted-properties
43
- return JSON.parse(readFileSync(found, "utf8")) as VariantAliasTable
24
+ async function loadTable(): Promise<VariantAliasTable> {
25
+ return readLocalJSONFile<VariantAliasTable>(await resolvePackagedDataPath(moduleDir, "aliases.json"))
44
26
  }
45
27
 
46
- const TABLE = loadTable()
28
+ const TABLE = await loadTable()
47
29
 
48
30
  /**
49
31
  * Indexed by lowercased variant string for O(1) lookup. Multiple entries can share the same variant key (e.g. ambiguous
@@ -64,7 +46,35 @@ const INDEX: ReadonlyMap<string, ReadonlyArray<VariantAlias>> = (() => {
64
46
  })()
65
47
 
66
48
  /**
67
- * Match a query token against the variant alias table, gated by detected locale.
49
+ * Decide how a locale-scoped record answers under a detected locale — the rule every locale-restricted vocabulary in
50
+ * the pipeline follows.
51
+ *
52
+ * - `unscoped` (confidence 1) when the record declares no locales at all.
53
+ * - `exact` (confidence 1) when the detected locale is one the record declares.
54
+ * - `language` (confidence 0.5) when only the language subtag agrees — weaker on purpose, because regional variants are
55
+ * by definition regional.
56
+ * - `null` otherwise, and for any scoped record when the locale is unknown: a phrasing declared regional cannot be
57
+ * reached without knowing the region.
58
+ */
59
+ export function resolveLocaleScope(
60
+ locales: ReadonlyArray<string> | undefined,
61
+ locale: string | undefined
62
+ ): LocaleScopeMatch | null {
63
+ if (!locales) return { scope: "unscoped", confidence: 1 }
64
+
65
+ if (!locale) return null
66
+
67
+ if (locales.includes(locale)) return { scope: "exact", confidence: 1 }
68
+
69
+ const language = locale.split(/[-_]/)[0]
70
+
71
+ if (locales.some((tag) => tag.split(/[-_]/)[0] === language)) return { scope: "language", confidence: 0.5 }
72
+
73
+ return null
74
+ }
75
+
76
+ /**
77
+ * Match a query token against the variant alias table, filtered by detected locale.
68
78
  *
69
79
  * Confidence:
70
80
  *
@@ -85,21 +95,13 @@ export function lookupVariantAliases(text: string, locale: string): AliasLookupR
85
95
 
86
96
  if (!candidates || !candidates.length) return []
87
97
 
88
- const language = locale.split(/[-_]/)[0]
89
98
  const results: AliasLookupResult[] = []
90
99
 
91
100
  for (const alias of candidates) {
92
- if (alias.locales.includes(locale)) {
93
- results.push({ alias, confidence: 1 })
94
-
95
- continue
96
- }
97
-
98
- // Relaxed match: any locale in `locales` that shares the same language part.
99
- const langMatch = alias.locales.some((l) => l.split(/[-_]/)[0] === language)
101
+ const match = resolveLocaleScope(alias.locales, locale)
100
102
 
101
- if (langMatch) {
102
- results.push({ alias, confidence: 0.5 })
103
+ if (match) {
104
+ results.push({ alias, confidence: match.confidence })
103
105
  }
104
106
  }
105
107
 
@@ -16,13 +16,13 @@
16
16
  */
17
17
  export type VariantKind = "amenity" | "brand"
18
18
 
19
- export interface VariantAliasBase {
19
+ interface VariantAliasBase {
20
20
  /**
21
21
  * The user-typed variant. Always lowercase for the lookup key (CJK preserved as-is).
22
22
  */
23
23
  variant: string
24
24
  /**
25
- * BCP-47 locale tags where this variant is in active use. Used to gate lookups: only consider an alias when the
25
+ * BCP-47 locale tags where this variant is in active use. Used to filter lookups: only consider an alias when the
26
26
  * detected locale matches one of these. A query in `en-US` won't match Australian "servo" because `en-AU` is not in
27
27
  * `["en-US"]`.
28
28
  */
@@ -58,6 +58,27 @@ export interface VariantAliasTable {
58
58
  aliases: ReadonlyArray<VariantAlias>
59
59
  }
60
60
 
61
+ /**
62
+ * How a record's locale scope met the locale a query was read under.
63
+ *
64
+ * - `unscoped` — the record declares no locales and answers under any.
65
+ * - `exact` — the query's locale tag is one the record declares.
66
+ * - `language` — only the language subtag agrees. Weaker on purpose: a regional phrasing reached through its language
67
+ * alone is a guess about the region.
68
+ */
69
+ export type LocaleScope = "unscoped" | "exact" | "language"
70
+
71
+ /**
72
+ * One locale-scoped record matched under one locale.
73
+ */
74
+ export interface LocaleScopeMatch {
75
+ scope: LocaleScope
76
+ /**
77
+ * `1` for `unscoped` and `exact`, `0.5` for `language`.
78
+ */
79
+ confidence: number
80
+ }
81
+
61
82
  export interface AliasLookupResult {
62
83
  alias: VariantAlias
63
84
  /**
package/out/index.d.ts CHANGED
@@ -13,8 +13,8 @@
13
13
  * - `docs/articles/understanding/exotic-poi/regional-variant-queries.md` for the linguistic
14
14
  * background and the source tables this data is derived from.
15
15
  * - Issue #166 for the v0.6.0+ runtime integration plan (kind classifier consumes this table to emit
16
- * `kind=amenity` / `kind=brand` proposals, gated by locale-gate output).
16
+ * `kind=amenity` / `kind=brand` proposals, filtered by `@mailwoman/locale-hint` output).
17
17
  */
18
- export { VARIANT_ALIAS_VERSION, getAllAliases, lookupVariantAliases } from "./lookup.ts";
19
- export type { AliasLookupResult, AmenityAlias, BrandAlias, VariantAlias, VariantAliasTable, VariantKind, } from "./types.ts";
18
+ export { VARIANT_ALIAS_VERSION, getAllAliases, lookupVariantAliases, resolveLocaleScope } from "#lookup";
19
+ export type { AliasLookupResult, AmenityAlias, BrandAlias, LocaleScope, LocaleScopeMatch, VariantAlias, VariantAliasTable, VariantKind, } from "#types";
20
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAExF,YAAY,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EACjB,WAAW,GACX,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAExG,YAAY,EACX,iBAAiB,EACjB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,WAAW,GACX,MAAM,QAAQ,CAAA"}
package/out/index.js CHANGED
@@ -13,7 +13,7 @@
13
13
  * - `docs/articles/understanding/exotic-poi/regional-variant-queries.md` for the linguistic
14
14
  * background and the source tables this data is derived from.
15
15
  * - Issue #166 for the v0.6.0+ runtime integration plan (kind classifier consumes this table to emit
16
- * `kind=amenity` / `kind=brand` proposals, gated by locale-gate output).
16
+ * `kind=amenity` / `kind=brand` proposals, filtered by `@mailwoman/locale-hint` output).
17
17
  */
18
- export { VARIANT_ALIAS_VERSION, getAllAliases, lookupVariantAliases } from "./lookup.js";
18
+ export { VARIANT_ALIAS_VERSION, getAllAliases, lookupVariantAliases, resolveLocaleScope } from "#lookup";
19
19
  //# sourceMappingURL=index.js.map
package/out/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA"}
package/out/lookup.d.ts CHANGED
@@ -6,12 +6,24 @@
6
6
  * Regional variant alias lookup. Given a token (or short phrase) and a detected locale, return the
7
7
  * canonical amenity category or brand it refers to.
8
8
  *
9
- * This is the data-side foundation for #166 (variant alias table + locale-gated category matching).
9
+ * This is the data-side foundation for #166 (variant alias table + locale-restricted category matching).
10
10
  * The runtime integration into the kind classifier is v0.6.0+ work.
11
11
  */
12
- import type { AliasLookupResult, VariantAlias } from "./types.ts";
12
+ import type { AliasLookupResult, LocaleScopeMatch, VariantAlias } from "#types";
13
13
  /**
14
- * Match a query token against the variant alias table, gated by detected locale.
14
+ * Decide how a locale-scoped record answers under a detected locale — the rule every locale-restricted vocabulary in
15
+ * the pipeline follows.
16
+ *
17
+ * - `unscoped` (confidence 1) when the record declares no locales at all.
18
+ * - `exact` (confidence 1) when the detected locale is one the record declares.
19
+ * - `language` (confidence 0.5) when only the language subtag agrees — weaker on purpose, because regional variants are
20
+ * by definition regional.
21
+ * - `null` otherwise, and for any scoped record when the locale is unknown: a phrasing declared regional cannot be
22
+ * reached without knowing the region.
23
+ */
24
+ export declare function resolveLocaleScope(locales: ReadonlyArray<string> | undefined, locale: string | undefined): LocaleScopeMatch | null;
25
+ /**
26
+ * Match a query token against the variant alias table, filtered by detected locale.
15
27
  *
16
28
  * Confidence:
17
29
  *
@@ -1 +1 @@
1
- {"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAqB,MAAM,YAAY,CAAA;AAkDpF;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CA8BtF;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,aAAa,CAAC,YAAY,CAAC,CAE3D;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAAgB,CAAA"}
1
+ {"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../lib/lookup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,YAAY,EAAqB,MAAM,QAAQ,CAAA;AAgClG;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,EAC1C,MAAM,EAAE,MAAM,GAAG,SAAS,GACxB,gBAAgB,GAAG,IAAI,CAYzB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAsBtF;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,aAAa,CAAC,YAAY,CAAC,CAE3D;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAAgB,CAAA"}
package/out/lookup.js CHANGED
@@ -6,36 +6,20 @@
6
6
  * Regional variant alias lookup. Given a token (or short phrase) and a detected locale, return the
7
7
  * canonical amenity category or brand it refers to.
8
8
  *
9
- * This is the data-side foundation for #166 (variant alias table + locale-gated category matching).
9
+ * This is the data-side foundation for #166 (variant alias table + locale-restricted category matching).
10
10
  * The runtime integration into the kind classifier is v0.6.0+ work.
11
11
  */
12
- import { existsSync, readFileSync } from "node:fs";
13
- import { resolve } from "node:path";
12
+ import { readLocalJSONFile } from "@mailwoman/core/fs/readers";
13
+ import { resolvePackagedDataPath } from "@mailwoman/core/module/packaged-data";
14
14
  const moduleDir = import.meta.dirname;
15
15
  /**
16
- * Read the shipped alias table.
17
- *
18
- * `data/` sits at the package root (it is a `files` entry), and this module sits either at that root — running from
19
- * source — or under `out/` when compiled, so there are exactly two places to look. The probe tests for the FILE:
20
- * probing by attempting a parse folds a corrupt table into "not this candidate", and the package then reports a missing
21
- * table it is looking straight at.
22
- *
23
- * `@mailwoman/poi-taxonomy` carries the same loader against its own tables. The duplication is deliberate — both
24
- * packages declare ZERO dependencies and publish independently, so sharing one would mean one taking a dependency on
25
- * the other for eight lines.
16
+ * Read the shipped alias table, located by the shared source-tree/`out/` probe in
17
+ * `@mailwoman/core/module/packaged-data`.
26
18
  */
27
- function loadTable() {
28
- const candidates = [resolve(moduleDir, "data", "aliases.json"), resolve(moduleDir, "..", "data", "aliases.json")];
29
- const found = candidates.find((candidate) => existsSync(candidate));
30
- if (!found) {
31
- throw new Error(`variant-aliases: could not find data/aliases.json — looked in ${candidates.join(", ")}`);
32
- }
33
- // A corrupt shipped table is a broken build, and the SyntaxError names the offset. Zero dependencies here, so
34
- // `@mailwoman/core`'s parse wrappers are deliberately out of reach.
35
- // oxlint-disable-next-line no-restricted-properties
36
- return JSON.parse(readFileSync(found, "utf8"));
19
+ async function loadTable() {
20
+ return readLocalJSONFile(await resolvePackagedDataPath(moduleDir, "aliases.json"));
37
21
  }
38
- const TABLE = loadTable();
22
+ const TABLE = await loadTable();
39
23
  /**
40
24
  * Indexed by lowercased variant string for O(1) lookup. Multiple entries can share the same variant key (e.g. ambiguous
41
25
  * "takeaway" only matches GB but not AU if both list it differently), so each entry is an array of all aliases that
@@ -52,7 +36,30 @@ const INDEX = (() => {
52
36
  return map;
53
37
  })();
54
38
  /**
55
- * Match a query token against the variant alias table, gated by detected locale.
39
+ * Decide how a locale-scoped record answers under a detected locale — the rule every locale-restricted vocabulary in
40
+ * the pipeline follows.
41
+ *
42
+ * - `unscoped` (confidence 1) when the record declares no locales at all.
43
+ * - `exact` (confidence 1) when the detected locale is one the record declares.
44
+ * - `language` (confidence 0.5) when only the language subtag agrees — weaker on purpose, because regional variants are
45
+ * by definition regional.
46
+ * - `null` otherwise, and for any scoped record when the locale is unknown: a phrasing declared regional cannot be
47
+ * reached without knowing the region.
48
+ */
49
+ export function resolveLocaleScope(locales, locale) {
50
+ if (!locales)
51
+ return { scope: "unscoped", confidence: 1 };
52
+ if (!locale)
53
+ return null;
54
+ if (locales.includes(locale))
55
+ return { scope: "exact", confidence: 1 };
56
+ const language = locale.split(/[-_]/)[0];
57
+ if (locales.some((tag) => tag.split(/[-_]/)[0] === language))
58
+ return { scope: "language", confidence: 0.5 };
59
+ return null;
60
+ }
61
+ /**
62
+ * Match a query token against the variant alias table, filtered by detected locale.
56
63
  *
57
64
  * Confidence:
58
65
  *
@@ -71,17 +78,11 @@ export function lookupVariantAliases(text, locale) {
71
78
  const candidates = INDEX.get(norm);
72
79
  if (!candidates || !candidates.length)
73
80
  return [];
74
- const language = locale.split(/[-_]/)[0];
75
81
  const results = [];
76
82
  for (const alias of candidates) {
77
- if (alias.locales.includes(locale)) {
78
- results.push({ alias, confidence: 1 });
79
- continue;
80
- }
81
- // Relaxed match: any locale in `locales` that shares the same language part.
82
- const langMatch = alias.locales.some((l) => l.split(/[-_]/)[0] === language);
83
- if (langMatch) {
84
- results.push({ alias, confidence: 0.5 });
83
+ const match = resolveLocaleScope(alias.locales, locale);
84
+ if (match) {
85
+ results.push({ alias, confidence: match.confidence });
85
86
  }
86
87
  }
87
88
  results.sort((a, b) => b.confidence - a.confidence);
package/out/lookup.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"lookup.js","sourceRoot":"","sources":["../lookup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lookup.js","sourceRoot":"","sources":["../lib/lookup.ts"],"names":[],"mappings":"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"}
package/out/types.d.ts CHANGED
@@ -14,13 +14,13 @@
14
14
  * "Mickey D's", "マクド") all map to `McDonald's`.
15
15
  */
16
16
  export type VariantKind = "amenity" | "brand";
17
- export interface VariantAliasBase {
17
+ interface VariantAliasBase {
18
18
  /**
19
19
  * The user-typed variant. Always lowercase for the lookup key (CJK preserved as-is).
20
20
  */
21
21
  variant: string;
22
22
  /**
23
- * BCP-47 locale tags where this variant is in active use. Used to gate lookups: only consider an alias when the
23
+ * BCP-47 locale tags where this variant is in active use. Used to filter lookups: only consider an alias when the
24
24
  * detected locale matches one of these. A query in `en-US` won't match Australian "servo" because `en-AU` is not in
25
25
  * `["en-US"]`.
26
26
  */
@@ -51,6 +51,25 @@ export interface VariantAliasTable {
51
51
  description: string;
52
52
  aliases: ReadonlyArray<VariantAlias>;
53
53
  }
54
+ /**
55
+ * How a record's locale scope met the locale a query was read under.
56
+ *
57
+ * - `unscoped` — the record declares no locales and answers under any.
58
+ * - `exact` — the query's locale tag is one the record declares.
59
+ * - `language` — only the language subtag agrees. Weaker on purpose: a regional phrasing reached through its language
60
+ * alone is a guess about the region.
61
+ */
62
+ export type LocaleScope = "unscoped" | "exact" | "language";
63
+ /**
64
+ * One locale-scoped record matched under one locale.
65
+ */
66
+ export interface LocaleScopeMatch {
67
+ scope: LocaleScope;
68
+ /**
69
+ * `1` for `unscoped` and `exact`, `0.5` for `language`.
70
+ */
71
+ confidence: number;
72
+ }
54
73
  export interface AliasLookupResult {
55
74
  alias: VariantAlias;
56
75
  /**
@@ -58,4 +77,5 @@ export interface AliasLookupResult {
58
77
  */
59
78
  confidence: number;
60
79
  }
80
+ export {};
61
81
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,CAAA;AAE7C,MAAM,WAAW,gBAAgB;IAChC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC9B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACrD,IAAI,EAAE,SAAS,CAAA;IACf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IACnD,IAAI,EAAE,OAAO,CAAA;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,UAAU,CAAA;AAEpD,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;CACpC;AAED,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,YAAY,CAAA;IACnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,OAAO,CAAA;AAE7C,UAAU,gBAAgB;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC9B;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,YAAa,SAAQ,gBAAgB;IACrD,IAAI,EAAE,SAAS,CAAA;IACf;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,UAAW,SAAQ,gBAAgB;IACnD,IAAI,EAAE,OAAO,CAAA;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;CACb;AAED,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,UAAU,CAAA;AAEpD,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,aAAa,CAAC,YAAY,CAAC,CAAA;CACpC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAA;AAE3D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,KAAK,EAAE,WAAW,CAAA;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,YAAY,CAAA;IACnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAA;CAClB"}
package/out/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../lib/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@mailwoman/variant-aliases",
3
- "version": "9.1.0",
4
- "description": "Regional variant alias table — local terms for amenities/brands gated by locale. 'servo' → fuel (en-AU), 'マクド' → McDonald's (ja-JP), 'PFK' → KFC (fr-CA).",
3
+ "version": "9.3.0",
4
+ "description": "Regional variant alias table — local terms for amenities/brands blocked by locale. 'servo' → fuel (en-AU), 'マクド' → McDonald's (ja-JP), 'PFK' → KFC (fr-CA).",
5
5
  "license": "AGPL-3.0-only OR LicenseRef-Commercial",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "https://github.com/sister-software/mailwoman.git",
9
- "directory": "variant-aliases"
9
+ "directory": "packages/variant-aliases"
10
10
  },
11
11
  "files": [
12
12
  "out/**/*.js",
@@ -21,14 +21,29 @@
21
21
  "!*.test.ts",
22
22
  "!*.test.tsx",
23
23
  "!**/*.test.ts",
24
- "!**/*.test.tsx"
24
+ "!**/*.test.tsx",
25
+ "!test/**"
25
26
  ],
26
27
  "type": "module",
28
+ "sideEffects": false,
29
+ "imports": {
30
+ "#*": {
31
+ "types": "./out/*.d.ts",
32
+ "node": "./out/*.js",
33
+ "default": "./out/*.js"
34
+ }
35
+ },
27
36
  "exports": {
28
37
  "./package.json": "./package.json",
29
38
  ".": {
30
39
  "types": "./out/index.d.ts",
40
+ "node": "./out/index.js",
31
41
  "default": "./out/index.js"
42
+ },
43
+ "./lookup": {
44
+ "types": "./out/lookup.d.ts",
45
+ "node": "./out/lookup.js",
46
+ "default": "./out/lookup.js"
32
47
  }
33
48
  },
34
49
  "publishConfig": {
@@ -37,8 +52,24 @@
37
52
  "./package.json": "./package.json",
38
53
  ".": {
39
54
  "types": "./out/index.d.ts",
55
+ "node": "./out/index.js",
40
56
  "default": "./out/index.js"
57
+ },
58
+ "./lookup": {
59
+ "types": "./out/lookup.d.ts",
60
+ "node": "./out/lookup.js",
61
+ "default": "./out/lookup.js"
62
+ }
63
+ },
64
+ "imports": {
65
+ "#*": {
66
+ "types": "./out/*.d.ts",
67
+ "node": "./out/*.js",
68
+ "default": "./out/*.js"
41
69
  }
42
70
  }
71
+ },
72
+ "dependencies": {
73
+ "@mailwoman/core": "9.3.0"
43
74
  }
44
75
  }