diff --git a/__snapshots__/packages/java-edition/test-out/json/parser/index.spec.js b/__snapshots__/packages/java-edition/test-out/json/parser/index.spec.js new file mode 100644 index 000000000..e2bc159d6 --- /dev/null +++ b/__snapshots__/packages/java-edition/test-out/json/parser/index.spec.js @@ -0,0 +1,309 @@ +exports['translationValueParser() Parse "hello %" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 7 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 7 + }, + "value": "%" + } + ], + "value": "hello %" + }, + "errors": [ + { + "range": { + "start": 7, + "end": 7 + }, + "message": "Expected “s”. If you want to display a literal percent sign, use “%%” instead", + "severity": 3 + } + ] +} + +exports['translationValueParser() Parse "hello %$s" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 9 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 7 + }, + "value": "%" + } + ], + "value": "hello %$s" + }, + "errors": [ + { + "range": { + "start": 7, + "end": 7 + }, + "message": "Expected “s”. If you want to display a literal percent sign, use “%%” instead", + "severity": 3 + } + ] +} + +exports['translationValueParser() Parse "hello %%" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 8 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 8 + }, + "value": "%%" + } + ], + "value": "hello %%" + }, + "errors": [] +} + +exports['translationValueParser() Parse "hello %1" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 8 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 8 + }, + "value": "%1" + } + ], + "value": "hello %1" + }, + "errors": [ + { + "range": { + "start": 8, + "end": 8 + }, + "message": "Expected “$”. If you want to display a literal percent sign, use “%%” instead", + "severity": 3 + }, + { + "range": { + "start": 8, + "end": 8 + }, + "message": "Expected “s”. If you want to display a literal percent sign, use “%%” instead", + "severity": 3 + } + ] +} + +exports['translationValueParser() Parse "hello %1$" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 9 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 9 + }, + "value": "%1$" + } + ], + "value": "hello %1$" + }, + "errors": [ + { + "range": { + "start": 9, + "end": 9 + }, + "message": "Expected “s”. If you want to display a literal percent sign, use “%%” instead", + "severity": 3 + } + ] +} + +exports['translationValueParser() Parse "hello %1$s" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 10 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 10 + }, + "value": "%1$s" + } + ], + "value": "hello %1$s" + }, + "errors": [] +} + +exports['translationValueParser() Parse "hello %s %42$s" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 14 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 8 + }, + "value": "%s" + }, + { + "type": "literal", + "range": { + "start": 9, + "end": 14 + }, + "value": "%42$s" + } + ], + "value": "hello %s %42$s" + }, + "errors": [] +} + +exports['translationValueParser() Parse "hello %s" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 8 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 8 + }, + "value": "%s" + } + ], + "value": "hello %s" + }, + "errors": [] +} + +exports['translationValueParser() Parse "hello %s%" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 9 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 8 + }, + "value": "%s" + }, + { + "type": "literal", + "range": { + "start": 8, + "end": 9 + }, + "value": "%" + } + ], + "value": "hello %s%" + }, + "errors": [ + { + "range": { + "start": 9, + "end": 9 + }, + "message": "Expected “s”. If you want to display a literal percent sign, use “%%” instead", + "severity": 3 + } + ] +} + +exports['translationValueParser() Parse "hello %s%%" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 10 + }, + "children": [ + { + "type": "literal", + "range": { + "start": 6, + "end": 8 + }, + "value": "%s" + }, + { + "type": "literal", + "range": { + "start": 8, + "end": 10 + }, + "value": "%%" + } + ], + "value": "hello %s%%" + }, + "errors": [] +} + +exports['translationValueParser() Parse "hello world" 1'] = { + "node": { + "type": "java_edition:translation_value", + "range": { + "start": 0, + "end": 11 + }, + "children": [], + "value": "hello world" + }, + "errors": [] +} diff --git a/packages/java-edition/src/json/parser/index.ts b/packages/java-edition/src/json/parser/index.ts index 85fff9ca6..61a8a21a7 100644 --- a/packages/java-edition/src/json/parser/index.ts +++ b/packages/java-edition/src/json/parser/index.ts @@ -60,10 +60,22 @@ export const translationValueParser: core.InfallibleParser hasInteger = true } if (hasInteger && !src.trySkip('$')) { - ctx.err.report(localize('expected', localeQuote('$')), src) + ctx.err.report( + localize( + 'java-edition.translation-value.percent-escape-hint', + localize('expected', localeQuote('$')), + ), + src, + ) } if (!src.trySkip('s')) { - ctx.err.report(localize('expected', localeQuote('s')), src) + ctx.err.report( + localize( + 'java-edition.translation-value.percent-escape-hint', + localize('expected', localeQuote('s')), + ), + src, + ) } const token = src.sliceToCursor(argStart) ans.children.push({ diff --git a/packages/java-edition/test/json/parser/index.spec.ts b/packages/java-edition/test/json/parser/index.spec.ts new file mode 100644 index 000000000..da0fb9791 --- /dev/null +++ b/packages/java-edition/test/json/parser/index.spec.ts @@ -0,0 +1,25 @@ +import { showWhitespaceGlyph, testParser } from '@spyglassmc/core/test-out/utils.js' +import { describe, it } from 'mocha' +import snapshot from 'snap-shot-it' +import { translationValueParser } from '../../../lib/json/parser/index.js' + +describe('translationValueParser()', () => { + const cases: string[] = [ + 'hello world', + 'hello %', + 'hello %%', + 'hello %s', + 'hello %s%', + 'hello %s%%', + 'hello %1', + 'hello %1$', + 'hello %$s', + 'hello %1$s', + 'hello %s %42$s', + ] + for (const content of cases) { + it(`Parse "${showWhitespaceGlyph(content)}"`, () => { + snapshot(testParser(translationValueParser, content)) + }) + } +}) diff --git a/packages/locales/src/locales/en.json b/packages/locales/src/locales/en.json index 27a4c9484..1db414b7f 100644 --- a/packages/locales/src/locales/en.json +++ b/packages/locales/src/locales/en.json @@ -52,6 +52,7 @@ "java-edition.binder.wrong-version": "Files in the %0% folder are not recognized in loaded version %1%", "java-edition.pack-format.unsupported": "Pack format %0% does not have a corresponding release version. Snapshot versions are unsupported.", "java-edition.pack-format.not-loaded": "Pack format %0% does not match the actively loaded version %1%. You may need to reload Spyglass.", + "java-edition.translation-value.percent-escape-hint": "%0%. If you want to display a literal percent sign, use “%%” instead", "json.doc.advancement.display": "Advancement display settings. If present, the advancement will be visible in the advancement tabs.", "json.checker.array.length-between": "%0% with length between %1% and %2%", "json.checker.object.field.union-empty-members": "Disallowed property", diff --git a/packages/vscode-extension/package.json b/packages/vscode-extension/package.json index d48c29a8a..28d00c72c 100644 --- a/packages/vscode-extension/package.json +++ b/packages/vscode-extension/package.json @@ -266,6 +266,10 @@ "id": "error", "description": "An error." }, + { + "id": "escape", + "description": "An escape sequence." + }, { "id": "literal", "description": "A literal."