@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.
- package/LICENSE +190 -0
- package/README.md +84 -0
- package/dist/generated/ast.d.ts +958 -0
- package/dist/generated/ast.d.ts.map +1 -0
- package/dist/generated/ast.js +795 -0
- package/dist/generated/ast.js.map +1 -0
- package/dist/generated/grammar.d.ts +7 -0
- package/dist/generated/grammar.d.ts.map +1 -0
- package/dist/generated/grammar.js +2509 -0
- package/dist/generated/grammar.js.map +1 -0
- package/dist/generated/module.d.ts +14 -0
- package/dist/generated/module.d.ts.map +1 -0
- package/dist/generated/module.js +21 -0
- package/dist/generated/module.js.map +1 -0
- package/dist/i18n/codes.d.ts +3 -0
- package/dist/i18n/codes.d.ts.map +1 -0
- package/dist/i18n/codes.js +54 -0
- package/dist/i18n/codes.js.map +1 -0
- package/dist/i18n/index.d.ts +17 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +82 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/messages.en.d.ts +96 -0
- package/dist/i18n/messages.en.d.ts.map +1 -0
- package/dist/i18n/messages.en.js +57 -0
- package/dist/i18n/messages.en.js.map +1 -0
- package/dist/i18n/messages.fr-CA.d.ts +3 -0
- package/dist/i18n/messages.fr-CA.d.ts.map +1 -0
- package/dist/i18n/messages.fr-CA.js +11 -0
- package/dist/i18n/messages.fr-CA.js.map +1 -0
- package/dist/i18n/messages.fr-FR.d.ts +3 -0
- package/dist/i18n/messages.fr-FR.d.ts.map +1 -0
- package/dist/i18n/messages.fr-FR.js +11 -0
- package/dist/i18n/messages.fr-FR.js.map +1 -0
- package/dist/i18n/messages.fr.d.ts +3 -0
- package/dist/i18n/messages.fr.d.ts.map +1 -0
- package/dist/i18n/messages.fr.js +55 -0
- package/dist/i18n/messages.fr.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/language/include-resolver.d.ts +46 -0
- package/dist/language/include-resolver.d.ts.map +1 -0
- package/dist/language/include-resolver.js +306 -0
- package/dist/language/include-resolver.js.map +1 -0
- package/dist/language/nowline-module.d.ts +18 -0
- package/dist/language/nowline-module.d.ts.map +1 -0
- package/dist/language/nowline-module.js +63 -0
- package/dist/language/nowline-module.js.map +1 -0
- package/dist/language/nowline-validator.d.ts +65 -0
- package/dist/language/nowline-validator.d.ts.map +1 -0
- package/dist/language/nowline-validator.js +1654 -0
- package/dist/language/nowline-validator.js.map +1 -0
- package/package.json +37 -0
- package/src/generated/ast.ts +1178 -0
- package/src/generated/grammar.ts +2511 -0
- package/src/generated/module.ts +25 -0
- package/src/i18n/codes.ts +102 -0
- package/src/i18n/index.ts +102 -0
- package/src/i18n/messages.en.ts +86 -0
- package/src/i18n/messages.fr-CA.ts +13 -0
- package/src/i18n/messages.fr-FR.ts +13 -0
- package/src/i18n/messages.fr.ts +91 -0
- package/src/index.ts +22 -0
- package/src/language/include-resolver.ts +470 -0
- package/src/language/nowline-module.ts +114 -0
- package/src/language/nowline-validator.ts +1991 -0
- 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';
|