@nowline/core 0.2.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.
Files changed (69) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +84 -0
  3. package/dist/generated/ast.d.ts +958 -0
  4. package/dist/generated/ast.d.ts.map +1 -0
  5. package/dist/generated/ast.js +795 -0
  6. package/dist/generated/ast.js.map +1 -0
  7. package/dist/generated/grammar.d.ts +7 -0
  8. package/dist/generated/grammar.d.ts.map +1 -0
  9. package/dist/generated/grammar.js +2509 -0
  10. package/dist/generated/grammar.js.map +1 -0
  11. package/dist/generated/module.d.ts +14 -0
  12. package/dist/generated/module.d.ts.map +1 -0
  13. package/dist/generated/module.js +21 -0
  14. package/dist/generated/module.js.map +1 -0
  15. package/dist/i18n/codes.d.ts +3 -0
  16. package/dist/i18n/codes.d.ts.map +1 -0
  17. package/dist/i18n/codes.js +54 -0
  18. package/dist/i18n/codes.js.map +1 -0
  19. package/dist/i18n/index.d.ts +17 -0
  20. package/dist/i18n/index.d.ts.map +1 -0
  21. package/dist/i18n/index.js +82 -0
  22. package/dist/i18n/index.js.map +1 -0
  23. package/dist/i18n/messages.en.d.ts +96 -0
  24. package/dist/i18n/messages.en.d.ts.map +1 -0
  25. package/dist/i18n/messages.en.js +57 -0
  26. package/dist/i18n/messages.en.js.map +1 -0
  27. package/dist/i18n/messages.fr-CA.d.ts +3 -0
  28. package/dist/i18n/messages.fr-CA.d.ts.map +1 -0
  29. package/dist/i18n/messages.fr-CA.js +11 -0
  30. package/dist/i18n/messages.fr-CA.js.map +1 -0
  31. package/dist/i18n/messages.fr-FR.d.ts +3 -0
  32. package/dist/i18n/messages.fr-FR.d.ts.map +1 -0
  33. package/dist/i18n/messages.fr-FR.js +11 -0
  34. package/dist/i18n/messages.fr-FR.js.map +1 -0
  35. package/dist/i18n/messages.fr.d.ts +3 -0
  36. package/dist/i18n/messages.fr.d.ts.map +1 -0
  37. package/dist/i18n/messages.fr.js +55 -0
  38. package/dist/i18n/messages.fr.js.map +1 -0
  39. package/dist/index.d.ts +9 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +8 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/language/include-resolver.d.ts +46 -0
  44. package/dist/language/include-resolver.d.ts.map +1 -0
  45. package/dist/language/include-resolver.js +306 -0
  46. package/dist/language/include-resolver.js.map +1 -0
  47. package/dist/language/nowline-module.d.ts +18 -0
  48. package/dist/language/nowline-module.d.ts.map +1 -0
  49. package/dist/language/nowline-module.js +63 -0
  50. package/dist/language/nowline-module.js.map +1 -0
  51. package/dist/language/nowline-validator.d.ts +65 -0
  52. package/dist/language/nowline-validator.d.ts.map +1 -0
  53. package/dist/language/nowline-validator.js +1654 -0
  54. package/dist/language/nowline-validator.js.map +1 -0
  55. package/package.json +37 -0
  56. package/src/generated/ast.ts +1178 -0
  57. package/src/generated/grammar.ts +2511 -0
  58. package/src/generated/module.ts +25 -0
  59. package/src/i18n/codes.ts +102 -0
  60. package/src/i18n/index.ts +102 -0
  61. package/src/i18n/messages.en.ts +86 -0
  62. package/src/i18n/messages.fr-CA.ts +13 -0
  63. package/src/i18n/messages.fr-FR.ts +13 -0
  64. package/src/i18n/messages.fr.ts +91 -0
  65. package/src/index.ts +22 -0
  66. package/src/language/include-resolver.ts +470 -0
  67. package/src/language/nowline-module.ts +114 -0
  68. package/src/language/nowline-validator.ts +1991 -0
  69. package/src/language/nowline.langium +217 -0
@@ -0,0 +1,25 @@
1
+ /******************************************************************************
2
+ * This file was generated by langium-cli 4.2.0.
3
+ * DO NOT EDIT MANUALLY!
4
+ ******************************************************************************/
5
+
6
+ import type { LangiumSharedCoreServices, LangiumCoreServices, LangiumGeneratedCoreServices, LangiumGeneratedSharedCoreServices, LanguageMetaData, Module } from 'langium';
7
+ import { NowlineAstReflection } from './ast.js';
8
+ import { NowlineGrammar } from './grammar.js';
9
+
10
+ export const NowlineLanguageMetaData = {
11
+ languageId: 'nowline',
12
+ fileExtensions: ['.nowline'],
13
+ caseInsensitive: false,
14
+ mode: 'development'
15
+ } as const satisfies LanguageMetaData;
16
+
17
+ export const NowlineGeneratedSharedModule: Module<LangiumSharedCoreServices, LangiumGeneratedSharedCoreServices> = {
18
+ AstReflection: () => new NowlineAstReflection()
19
+ };
20
+
21
+ export const NowlineGeneratedModule: Module<LangiumCoreServices, LangiumGeneratedCoreServices> = {
22
+ Grammar: () => NowlineGrammar(),
23
+ LanguageMetaData: () => NowlineLanguageMetaData,
24
+ parser: {}
25
+ };
@@ -0,0 +1,102 @@
1
+ // Stable error codes for validator messages. Codes never change once shipped:
2
+ // renumbering is a major-version concern. Adding a new code is always
3
+ // safe; deleting one means the rule was removed entirely.
4
+ //
5
+ // Code ranges are reserved by category to keep the table scannable:
6
+ // NL.E0001–E0099 structural / file-level
7
+ // NL.E0100–E0199 directive
8
+ // NL.E0200–E0299 include
9
+ // NL.E0300–E0399 identifier / id-or-title / indentation
10
+ // NL.E0400–E0499 property values (duration, size, date, scale, etc.)
11
+ // NL.E0500–E0599 anchor / milestone / footnote
12
+ // NL.E0600–E0699 item / swimlane
13
+ // NL.E0700–E0799 capacity / utilization
14
+ // NL.E0800–E0899 style / color / symbol
15
+ // NL.E0900–E0999 config blocks (calendar, scale, default)
16
+ // NL.W0700–W0799 warnings (silently-ignored input)
17
+ //
18
+ // The full list of allocated codes lives in `messages.en.ts` (one entry
19
+ // per code). The runtime walks the locale fallback chain and falls
20
+ // through to en-US when a key is missing — see `i18n/index.ts`.
21
+
22
+ export type MessageCode =
23
+ // Structural (NL.E0001–E0099)
24
+ | 'NL.E0001' // config-after-roadmap
25
+ | 'NL.E0002' // include-after-config
26
+ | 'NL.E0003' // include-after-roadmap
27
+ | 'NL.E0004' // swimlane-required
28
+ | 'NL.E0005' // mixed-tabs-and-spaces
29
+
30
+ // Directive (NL.E0100–E0199)
31
+ | 'NL.E0100' // invalid-version-format
32
+ | 'NL.E0101' // version-beyond-supported
33
+ | 'NL.E0102' // unknown-directive-property
34
+ | 'NL.E0103' // duplicate-directive-property
35
+ | 'NL.E0104' // invalid-locale
36
+
37
+ // Include (NL.E0200–E0299)
38
+ | 'NL.E0200' // invalid-include-mode
39
+ | 'NL.E0201' // duplicate-include-option
40
+
41
+ // Identifier (NL.E0300–E0399)
42
+ | 'NL.E0300' // duplicate-identifier
43
+ | 'NL.E0301' // id-or-title-required
44
+
45
+ // Property values (NL.E0400–E0499)
46
+ | 'NL.E0400' // invalid-duration
47
+ | 'NL.E0401' // invalid-size-ref
48
+ | 'NL.E0402' // invalid-effort
49
+ | 'NL.E0403' // invalid-remaining-percent
50
+ | 'NL.E0404' // remaining-out-of-range
51
+ | 'NL.E0405' // invalid-date
52
+ | 'NL.E0406' // invalid-scale
53
+ | 'NL.E0407' // invalid-calendar
54
+ | 'NL.E0408' // empty-property-list
55
+
56
+ // Anchor / milestone / footnote (NL.E0500–E0599)
57
+ | 'NL.E0500' // anchor-requires-date
58
+ | 'NL.E0501' // anchor-needs-roadmap-start
59
+ | 'NL.E0502' // anchor-before-roadmap-start
60
+ | 'NL.E0503' // milestone-requires-date-or-after
61
+ | 'NL.E0504' // milestone-before-roadmap-start
62
+ | 'NL.E0505' // footnote-requires-on
63
+
64
+ // Item (NL.E0600–E0699)
65
+ | 'NL.E0600' // item-requires-size-or-duration
66
+
67
+ // Warnings (NL.W0700–W0799)
68
+ | 'NL.W0700'; // unknown-entity-property
69
+
70
+ export const ALL_CODES: ReadonlyArray<MessageCode> = [
71
+ 'NL.E0001',
72
+ 'NL.E0002',
73
+ 'NL.E0003',
74
+ 'NL.E0004',
75
+ 'NL.E0005',
76
+ 'NL.E0100',
77
+ 'NL.E0101',
78
+ 'NL.E0102',
79
+ 'NL.E0103',
80
+ 'NL.E0104',
81
+ 'NL.E0200',
82
+ 'NL.E0201',
83
+ 'NL.E0300',
84
+ 'NL.E0301',
85
+ 'NL.E0400',
86
+ 'NL.E0401',
87
+ 'NL.E0402',
88
+ 'NL.E0403',
89
+ 'NL.E0404',
90
+ 'NL.E0405',
91
+ 'NL.E0406',
92
+ 'NL.E0407',
93
+ 'NL.E0408',
94
+ 'NL.E0500',
95
+ 'NL.E0501',
96
+ 'NL.E0502',
97
+ 'NL.E0503',
98
+ 'NL.E0504',
99
+ 'NL.E0505',
100
+ 'NL.E0600',
101
+ 'NL.W0700',
102
+ ] as const;
@@ -0,0 +1,102 @@
1
+ // Validator message registry. Walks the BCP-47 fallback chain, falling
2
+ // through to `en-US` for any missing key. Other locales (fr, fr-CA,
3
+ // fr-FR, …) plug in via `registerBundle` so the renderer in `@nowline/cli`
4
+ // can wire them at startup without forcing `@nowline/core` to import
5
+ // every locale file at build time.
6
+ //
7
+ // Coverage contract: `messages.en.ts` is the source of truth — every
8
+ // `MessageCode` MUST have an entry there. Coverage CI lives in
9
+ // `test/i18n/messages-coverage.test.ts`.
10
+
11
+ import type { MessageCode } from './codes.js';
12
+ import { messages as enMessages } from './messages.en.js';
13
+ import { messages as frMessages } from './messages.fr.js';
14
+ import { messages as frCAMessages } from './messages.fr-CA.js';
15
+ import { messages as frFRMessages } from './messages.fr-FR.js';
16
+
17
+ export type { MessageCode } from './codes.js';
18
+
19
+ // `messages.en.ts` re-exported with its inferred type so other locales
20
+ // can `satisfies` against it. Each function takes one named-argument
21
+ // object and returns a localized string.
22
+ export type MessageBundle = {
23
+ [K in MessageCode]?: (...args: never[]) => string;
24
+ };
25
+
26
+ // Bundles are keyed by the BCP-47 tag. `en-US` is the canonical root and
27
+ // `fr` is the neutral French base; `fr-CA` and `fr-FR` are overlay shells
28
+ // that ship empty by design. The fallback walker (`fr-CA → fr → en-US`)
29
+ // fills in any missing keys, so authors only have to populate the
30
+ // overlays when a regional divergence actually exists.
31
+ //
32
+ // Empty overlays are intentional — they establish the contract for
33
+ // where regional divergences go when they appear, and keep the
34
+ // distribution surface uniform across locales.
35
+ const bundles = new Map<string, MessageBundle>([
36
+ ['en-US', enMessages as MessageBundle],
37
+ ['fr', frMessages],
38
+ ['fr-CA', frCAMessages],
39
+ ['fr-FR', frFRMessages],
40
+ ]);
41
+
42
+ export function registerBundle(locale: string, bundle: MessageBundle): void {
43
+ bundles.set(locale, bundle);
44
+ }
45
+
46
+ /**
47
+ * Format a message in the resolved locale.
48
+ *
49
+ * Walks the locale fallback chain (`fr-CA → fr → en-US`) and returns
50
+ * the first match. Always returns a string because `en-US` is
51
+ * guaranteed to define every code.
52
+ */
53
+ export function tr<K extends MessageCode>(
54
+ locale: string,
55
+ code: K,
56
+ ...args: MessageArgs<K>
57
+ ): string {
58
+ for (const tag of fallbackChain(locale)) {
59
+ const bundle = bundles.get(tag);
60
+ const fn = bundle?.[code];
61
+ if (fn) return (fn as (...a: typeof args) => string)(...args);
62
+ }
63
+ // Defensive fallback: en-US must define every code, but if a future
64
+ // refactor accidentally forgets one, surface the code itself rather
65
+ // than throwing — partial localization is recoverable; a thrown
66
+ // exception during validation is not.
67
+ return code;
68
+ }
69
+
70
+ // Type helper: extract the named-argument object type for a given code.
71
+ // `messages.en.ts` is the canonical signature source; other bundles
72
+ // satisfy `MessageBundle`, which only constrains the return type.
73
+ export type MessageArgs<K extends MessageCode> = Parameters<(typeof enMessages)[K]>;
74
+
75
+ const DEFAULT_LOCALE = 'en-US';
76
+
77
+ // Local copy of the BCP-47 fallback walker. Intentionally duplicated
78
+ // from `@nowline/layout/i18n` (which has the same logic) so that
79
+ // `@nowline/core` doesn't depend on `@nowline/layout`. The two
80
+ // implementations should evolve together — see `specs/localization.md`.
81
+ function fallbackChain(locale: string): string[] {
82
+ const chain: string[] = [];
83
+ let current = normalize(locale);
84
+ while (current.length > 0) {
85
+ if (!chain.includes(current)) chain.push(current);
86
+ const dash = current.lastIndexOf('-');
87
+ if (dash <= 0) break;
88
+ current = current.slice(0, dash);
89
+ }
90
+ if (!chain.includes(DEFAULT_LOCALE)) chain.push(DEFAULT_LOCALE);
91
+ return chain;
92
+ }
93
+
94
+ function normalize(locale: string): string {
95
+ const parts = locale.split('-');
96
+ return parts
97
+ .map((part, i) => {
98
+ if (i === 0) return part.toLowerCase();
99
+ return /^[a-zA-Z]{2}$/.test(part) ? part.toUpperCase() : part;
100
+ })
101
+ .join('-');
102
+ }
@@ -0,0 +1,86 @@
1
+ // English message bundle. The root locale — every key here MUST exist
2
+ // (CI enforces this in `messages-coverage.test.ts`). Other locales may
3
+ // omit keys; the loader falls through to en-US for any missing entry.
4
+ //
5
+ // Each entry is a plain function taking strongly-typed args. This keeps
6
+ // translation reviewable (no positional `{0}` / `{1}` indirection) and
7
+ // gives every placeholder a name. Authors translating to fr only have
8
+ // to swap the function body — the signature stays identical.
9
+ //
10
+ // We deliberately do NOT use `satisfies Record<MessageCode, ...>` here:
11
+ // the type of each entry is what `MessageArgs<K>` (in `index.ts`) reads
12
+ // to type-check call sites. A `satisfies` constraint would widen each
13
+ // entry to a uniform `(...args: never[]) => string` signature and break
14
+ // per-code argument inference. Coverage of `MessageCode` is enforced by
15
+ // the runtime test in `test/i18n/messages-coverage.test.ts`.
16
+
17
+ export const messages = {
18
+ // Structural
19
+ 'NL.E0001': () => 'Config section must appear before roadmap.',
20
+ 'NL.E0002': () => 'Include declarations must appear before the config section.',
21
+ 'NL.E0003': () => 'Include declarations must appear before the roadmap section.',
22
+ 'NL.E0004': () => 'At least one swimlane is required.',
23
+ 'NL.E0005': (a: { line: number }) =>
24
+ `Line ${a.line}: mixed tabs and spaces in indentation. Use either tabs or spaces consistently.`,
25
+
26
+ // Directive
27
+ 'NL.E0100': (a: { version: string }) =>
28
+ `Invalid version format "${a.version}". Expected format: v1, v2, etc.`,
29
+ 'NL.E0101': (a: { version: string; supported: string }) =>
30
+ `This file requires Nowline ${a.version}, but the parser only supports up to ${a.supported}.`,
31
+ 'NL.E0102': (a: { key: string; allowed: string }) =>
32
+ `Unknown directive property "${a.key}". Allowed: ${a.allowed}.`,
33
+ 'NL.E0103': (a: { key: string }) => `Duplicate directive property "${a.key}".`,
34
+ 'NL.E0104': (a: { value: string }) =>
35
+ `Invalid locale "${a.value}". Use a BCP-47 tag like "en-US", "fr", or "fr-CA".`,
36
+
37
+ // Include
38
+ 'NL.E0200': (a: { value: string }) =>
39
+ `Invalid include mode "${a.value}". Must be merge, ignore, or isolate.`,
40
+ 'NL.E0201': (a: { key: string }) => `Duplicate "${a.key}" option on include.`,
41
+
42
+ // Identifier
43
+ 'NL.E0300': (a: { name: string; location: string }) =>
44
+ `Duplicate identifier "${a.name}". First declared at ${a.location}.`,
45
+ 'NL.E0301': (a: { type: string }) => `${a.type} must have an identifier, a title, or both.`,
46
+
47
+ // Property values
48
+ 'NL.E0400': (a: { value: string }) =>
49
+ `Invalid duration "${a.value}". Use a raw duration literal like 0.5d, 2w, 1m, 2q. Use "size:NAME" to reference a declared size.`,
50
+ 'NL.E0401': (a: { value: string }) =>
51
+ `Invalid size "${a.value}". Use the id of a declared size (e.g. xs, m, lg).`,
52
+ 'NL.E0402': (a: { value: string }) =>
53
+ `Invalid effort "${a.value}". Use a raw duration literal like 0.5d, 2w, 1m, 2q.`,
54
+ 'NL.E0403': (a: { value: string }) =>
55
+ `Invalid remaining value "${a.value}". Use a percentage like 30% or a duration literal like 1w, 0.5d.`,
56
+ 'NL.E0404': (a: { value: string }) => `Remaining must be between 0% and 100%, got ${a.value}.`,
57
+ 'NL.E0405': (a: { key: string; value: string }) =>
58
+ `Invalid ${a.key} "${a.value}". Use ISO 8601 format: YYYY-MM-DD.`,
59
+ 'NL.E0406': (a: { value: string }) =>
60
+ `Invalid scale "${a.value}". Use a raw duration literal like 1w, 2w, 1q (no name lookup).`,
61
+ 'NL.E0407': (a: { value: string }) =>
62
+ `Invalid calendar "${a.value}". Must be business, full, or custom.`,
63
+ 'NL.E0408': (a: { key: string }) => `Property "${a.key}" requires at least one reference.`,
64
+
65
+ // Anchor / milestone / footnote
66
+ 'NL.E0500': (a: { name: string }) => `Anchor "${a.name}" requires a "date:" property.`,
67
+ 'NL.E0501': (a: { name: string }) =>
68
+ `Anchor "${a.name}" has a date but the roadmap is missing "start:". Add start:YYYY-MM-DD to the roadmap.`,
69
+ 'NL.E0502': (a: { name: string; date: string; start: string }) =>
70
+ `Anchor "${a.name}" date ${a.date} is before roadmap start ${a.start}.`,
71
+ 'NL.E0503': (a: { name: string }) =>
72
+ `Milestone "${a.name}" requires at least one of "date:" or "after:".`,
73
+ 'NL.E0504': (a: { name: string; date: string; start: string }) =>
74
+ `Milestone "${a.name}" date ${a.date} is before roadmap start ${a.start}.`,
75
+ 'NL.E0505': () => 'Footnote requires an "on:" property referencing one or more entities.',
76
+
77
+ // Item
78
+ 'NL.E0600': (a: { name: string }) =>
79
+ `Item "${a.name}" requires a "size:" or "duration:" property.`,
80
+
81
+ // Warnings
82
+ 'NL.W0700': (a: { key: string; entity: string; suggested: string }) =>
83
+ `Unknown property "${a.key}" on ${a.entity}. The renderer ignores it.${
84
+ a.suggested ? ` Did you mean "${a.suggested}"?` : ''
85
+ }`,
86
+ };
@@ -0,0 +1,13 @@
1
+ // Bundle de messages — surcouche fr-CA (Québec).
2
+ //
3
+ // Vide à la conception. Cette surcouche existe pour héberger les
4
+ // divergences spécifiques au Québec lorsqu'elles apparaissent\ : une
5
+ // terminologie OQLF qui s'écarte du français neutre est rejetée de
6
+ // `messages.fr.ts` et atterrit ici.
7
+ //
8
+ // Les clés absentes redescendent automatiquement la chaîne de repli
9
+ // BCP-47\ : `fr-CA → fr → en-US`. Voir `specs/localization.md`.
10
+
11
+ import type { MessageBundle } from './index.js';
12
+
13
+ export const messages: MessageBundle = {};
@@ -0,0 +1,13 @@
1
+ // Bundle de messages — surcouche fr-FR (France).
2
+ //
3
+ // Vide à la conception. Cette surcouche existe pour héberger les
4
+ // divergences spécifiques à la France hexagonale lorsqu'elles
5
+ // apparaissent\ : une terminologie qui s'écarte du français neutre est
6
+ // rejetée de `messages.fr.ts` et atterrit ici.
7
+ //
8
+ // Les clés absentes redescendent automatiquement la chaîne de repli
9
+ // BCP-47\ : `fr-FR → fr → en-US`. Voir `specs/localization.md`.
10
+
11
+ import type { MessageBundle } from './index.js';
12
+
13
+ export const messages: MessageBundle = {};
@@ -0,0 +1,91 @@
1
+ // Bundle de messages français — base régionalement neutre.
2
+ //
3
+ // Les divergences spécifiques au Québec ou à la France vont dans
4
+ // `messages.fr-CA.ts` / `messages.fr-FR.ts`, qui se superposent par-dessus
5
+ // celui-ci via la chaîne de repli BCP-47 (`fr-CA → fr → en-US`).
6
+ //
7
+ // Origine\ : traduction automatique amorcée, puis relecture humaine
8
+ // francophone du Québec (terminologie OQLF, Grand dictionnaire
9
+ // terminologique). Toute formulation typiquement québécoise doit
10
+ // descendre dans `messages.fr-CA.ts` plutôt que de polluer cette base.
11
+ //
12
+ // Les clés manquantes ici font silencieusement repli sur `messages.en.ts`,
13
+ // donc une couverture partielle est sûre.
14
+
15
+ import type { MessageBundle } from './index.js';
16
+
17
+ export const messages: MessageBundle = {
18
+ // Structurel
19
+ 'NL.E0001': () => 'La section config doit précéder la section roadmap.',
20
+ 'NL.E0002': () => 'Les déclarations include doivent précéder la section config.',
21
+ 'NL.E0003': () => 'Les déclarations include doivent précéder la section roadmap.',
22
+ 'NL.E0004': () => 'Au moins une swimlane est requise.',
23
+ 'NL.E0005': (a: { line: number }) =>
24
+ `Ligne ${a.line}\u00A0: tabulations et espaces mélangés dans l'indentation. Utilisez l'un ou l'autre, mais pas les deux.`,
25
+
26
+ // Directive
27
+ 'NL.E0100': (a: { version: string }) =>
28
+ `Format de version invalide «\u00A0${a.version}\u00A0». Format attendu\u00A0: v1, v2, etc.`,
29
+ 'NL.E0101': (a: { version: string; supported: string }) =>
30
+ `Ce fichier requiert Nowline ${a.version}, mais l'analyseur ne prend en charge que jusqu'à ${a.supported}.`,
31
+ 'NL.E0102': (a: { key: string; allowed: string }) =>
32
+ `Propriété de directive inconnue «\u00A0${a.key}\u00A0». Valeurs admises\u00A0: ${a.allowed}.`,
33
+ 'NL.E0103': (a: { key: string }) => `Propriété de directive «\u00A0${a.key}\u00A0» en double.`,
34
+ 'NL.E0104': (a: { value: string }) =>
35
+ `Locale invalide «\u00A0${a.value}\u00A0». Utilisez une étiquette BCP-47 telle que «\u00A0en-US\u00A0», «\u00A0fr\u00A0» ou «\u00A0fr-CA\u00A0».`,
36
+
37
+ // Include
38
+ 'NL.E0200': (a: { value: string }) =>
39
+ `Mode d'include invalide «\u00A0${a.value}\u00A0». Doit être merge, ignore ou isolate.`,
40
+ 'NL.E0201': (a: { key: string }) => `Option «\u00A0${a.key}\u00A0» en double sur include.`,
41
+
42
+ // Identifiant
43
+ 'NL.E0300': (a: { name: string; location: string }) =>
44
+ `Identifiant en double «\u00A0${a.name}\u00A0». Première déclaration à ${a.location}.`,
45
+ 'NL.E0301': (a: { type: string }) =>
46
+ `${a.type} doit comporter un identifiant, un titre, ou les deux.`,
47
+
48
+ // Valeurs de propriété
49
+ 'NL.E0400': (a: { value: string }) =>
50
+ `Durée invalide «\u00A0${a.value}\u00A0». Utilisez un littéral de durée brut comme 0.5d, 2w, 1m, 2q. Utilisez «\u00A0size:NOM\u00A0» pour référencer une taille déclarée.`,
51
+ 'NL.E0401': (a: { value: string }) =>
52
+ `Taille invalide «\u00A0${a.value}\u00A0». Utilisez l'identifiant d'une taille déclarée (p.\u00A0ex. xs, m, lg).`,
53
+ 'NL.E0402': (a: { value: string }) =>
54
+ `Effort invalide «\u00A0${a.value}\u00A0». Utilisez un littéral de durée brut comme 0.5d, 2w, 1m, 2q.`,
55
+ 'NL.E0403': (a: { value: string }) =>
56
+ `Valeur restante invalide «\u00A0${a.value}\u00A0». Utilisez un pourcentage tel que 30% ou un littéral de durée comme 1w, 0.5d.`,
57
+ 'NL.E0404': (a: { value: string }) =>
58
+ `La valeur restante doit être comprise entre 0 % et 100 %, reçu ${a.value}.`,
59
+ 'NL.E0405': (a: { key: string; value: string }) =>
60
+ `${a.key} invalide «\u00A0${a.value}\u00A0». Utilisez le format ISO 8601\u00A0: AAAA-MM-JJ.`,
61
+ 'NL.E0406': (a: { value: string }) =>
62
+ `Échelle invalide «\u00A0${a.value}\u00A0». Utilisez un littéral de durée brut comme 1w, 2w, 1q (pas de recherche par nom).`,
63
+ 'NL.E0407': (a: { value: string }) =>
64
+ `Calendrier invalide «\u00A0${a.value}\u00A0». Doit être business, full ou custom.`,
65
+ 'NL.E0408': (a: { key: string }) =>
66
+ `La propriété «\u00A0${a.key}\u00A0» exige au moins une référence.`,
67
+
68
+ // Ancre / jalon / note de bas de page
69
+ 'NL.E0500': (a: { name: string }) =>
70
+ `L'ancre «\u00A0${a.name}\u00A0» exige une propriété «\u00A0date:\u00A0».`,
71
+ 'NL.E0501': (a: { name: string }) =>
72
+ `L'ancre «\u00A0${a.name}\u00A0» a une date, mais «\u00A0start:\u00A0» manque sur la roadmap. Ajoutez start:AAAA-MM-JJ à la roadmap.`,
73
+ 'NL.E0502': (a: { name: string; date: string; start: string }) =>
74
+ `La date ${a.date} de l'ancre «\u00A0${a.name}\u00A0» précède le début de la roadmap (${a.start}).`,
75
+ 'NL.E0503': (a: { name: string }) =>
76
+ `Le jalon «\u00A0${a.name}\u00A0» exige au moins l'une des propriétés «\u00A0date:\u00A0» ou «\u00A0after:\u00A0».`,
77
+ 'NL.E0504': (a: { name: string; date: string; start: string }) =>
78
+ `La date ${a.date} du jalon «\u00A0${a.name}\u00A0» précède le début de la roadmap (${a.start}).`,
79
+ 'NL.E0505': () =>
80
+ 'Une note de bas de page exige une propriété «\u00A0on:\u00A0» référençant au moins une entité.',
81
+
82
+ // Élément
83
+ 'NL.E0600': (a: { name: string }) =>
84
+ `L'élément «\u00A0${a.name}\u00A0» exige une propriété «\u00A0size:\u00A0» ou «\u00A0duration:\u00A0».`,
85
+
86
+ // Avertissements
87
+ 'NL.W0700': (a: { key: string; entity: string; suggested: string }) =>
88
+ `Propriété inconnue «\u00A0${a.key}\u00A0» sur ${a.entity}. Le moteur de rendu l'ignore.${
89
+ a.suggested ? ` Vouliez-vous dire «\u00A0${a.suggested}\u00A0»\u00A0?` : ''
90
+ }`,
91
+ };
package/src/index.ts ADDED
@@ -0,0 +1,22 @@
1
+ export * from './generated/ast.js';
2
+ export * from './generated/module.js';
3
+ export { ALL_CODES, type MessageCode } from './i18n/codes.js';
4
+ export {
5
+ type MessageArgs,
6
+ type MessageBundle,
7
+ registerBundle,
8
+ tr,
9
+ } from './i18n/index.js';
10
+ export {
11
+ type IncludeMode,
12
+ type IsolatedRegion,
13
+ type ResolveDiagnostic,
14
+ type ResolvedConfig,
15
+ type ResolvedContent,
16
+ type ResolveIncludesOptions,
17
+ type ResolveResult,
18
+ resolveIncludes,
19
+ } from './language/include-resolver.js';
20
+ export type { NowlineAddedServices, NowlineServices } from './language/nowline-module.js';
21
+ export { createNowlineServices, NowlineModule } from './language/nowline-module.js';
22
+ export { NowlineValidator, registerValidationChecks } from './language/nowline-validator.js';