Files
pdfme/packages/schemas/__tests__/multiVariableText.test.ts
Kyohei Fukuda 16bec8babb [codex] Add inline markdown text format (#1461)
* feat(schemas): add inline markdown text format

* fix(common): handle missing git tags in version script

* fix(converter): align pdfjs document options with latest types

* test(generator): update pdfjs image snapshots

* test(playground): register inline markdown example

* refactor(schemas): avoid default font i18n key

* refactor(schemas): move markdown controls to prop panel end

* refactor(schemas): use checkbox for inline markdown toggle

* fix(schemas): localize multi variable text prop labels

* refactor(schemas): align inline markdown fallback control

* fix(schemas): address inline markdown review feedback

* refactor(schemas): address inline markdown review refinements

* fix(schemas): correct synthetic italic pdf skew

* test(playground): add bold italic inline markdown sample
2026-05-02 16:34:43 +09:00

162 lines
5.4 KiB
TypeScript

import {
substituteVariables,
substituteVariablesAsInlineMarkdownLiterals,
validateVariables,
} from '../src/multiVariableText/helper.js';
import { parseInlineMarkdown, stripInlineMarkdown } from '../src/text/inlineMarkdown.js';
import { MultiVariableTextSchema } from '../src/multiVariableText/types.js';
import {
countUniqueVariableNames,
getVariableIndices,
getVariableNames,
} from '../src/multiVariableText/variables.js';
describe('substituteVariables', () => {
it('should substitute variables in a string', () => {
const text = 'Hello, {name}!';
const variables = { name: 'World' };
const result = substituteVariables(text, variables);
expect(result).toBe('Hello, World!');
});
it('should handle special characters in variable names', () => {
const text = 'Hello, {*na-me}!';
const variables = { '*na-me': 'World' };
const result = substituteVariables(text, variables);
expect(result).toBe('Hello, World!');
});
it('should handle numeric variable names', () => {
let text = 'Hello, {123}!';
let variables = { '123': 'World' };
let result = substituteVariables(text, variables);
expect(result).toBe('Hello, World!');
});
it('should remove variables that were not substituted', () => {
const text = 'Hello, {name}! Welcome to {place}.';
const variables = { name: 'World' };
const result = substituteVariables(text, variables);
expect(result).toBe('Hello, World! Welcome to .');
});
it('should handle empty input strings', () => {
const text = '';
const variables = { name: 'World' };
const result = substituteVariables(text, variables);
expect(result).toBe('');
});
it('should handle empty variables', () => {
const text = 'Hello, {name}!';
const variables = {};
const result = substituteVariables(text, variables);
expect(result).toBe('Hello, !');
});
it('should handle variables as a JSON string', () => {
const text = 'Hello, {name}!';
const variables = '{"name": "World"}';
const result = substituteVariables(text, variables);
expect(result).toBe('Hello, World!');
});
it('should handle invalid JSON string for variables', () => {
const text = 'Hello, {name}!';
const variables = 'invalid json';
expect(() => substituteVariables(text, variables)).toThrow(SyntaxError);
});
it('should keep inline markdown variables as literal text while preserving template styling', () => {
const text = '**{name}** uses `{code}`';
const variables = { name: 'A **bold** user', code: 'PDF `42`' };
const result = substituteVariablesAsInlineMarkdownLiterals(text, variables);
expect(stripInlineMarkdown(result)).toBe('A **bold** user uses PDF `42`');
expect(parseInlineMarkdown(result)).toEqual([
{ text: 'A **bold** user', bold: true },
{ text: ' uses ' },
{ text: 'PDF `42`', code: true },
]);
});
});
describe('multiVariableText variable scanning', () => {
it('should record variable start indices for well-formed placeholders', () => {
const indices = getVariableIndices('{first} {second}');
expect(indices.get(0)).toBe('first');
expect(indices.get(8)).toBe('second');
});
it('should restart from the latest opening brace in malformed input', () => {
expect(getVariableNames('Hello {{name}}')).toEqual(['name']);
});
it('should match the innermost completed placeholder when braces are nested', () => {
expect(getVariableNames('{a{b}')).toEqual(['b']);
});
it('should count only unique completed variable names', () => {
expect(countUniqueVariableNames('{name} {name} {city')).toBe(1);
});
});
describe('validateVariables', () => {
// @ts-ignore
const schema: MultiVariableTextSchema = {
name: 'test',
variables: ['var1', 'var2'],
required: true,
};
it('should return true for valid input with all required variables', () => {
const value = JSON.stringify({ var1: 'value1', var2: 'value2' });
expect(validateVariables(value, schema)).toBe(true);
});
it('should throw an error for missing required variables', () => {
const value = JSON.stringify({ var1: 'value1' });
expect(() => validateVariables(value, schema)).toThrow(
'[@pdfme/generator] variable var2 is missing for field test'
);
});
it('should return false for missing non-required variables', () => {
// @ts-ignore
const nonRequiredSchema: MultiVariableTextSchema = {
name: 'test',
variables: ['var1', 'var2'],
required: false,
};
const value = JSON.stringify({ var1: 'value1' });
expect(validateVariables(value, nonRequiredSchema)).toBe(false);
});
it('should throw an error for invalid JSON input', () => {
const value = '{ var1: value1 var2: value2 }'; // Invalid JSON
expect(() => validateVariables(value, schema)).toThrow(SyntaxError);
});
it('should return true for a string with no variables', () => {
// @ts-ignore
const readOnlyText: MultiVariableTextSchema = {
name: 'test',
variables: [],
required: true,
};
const value = '';
expect(validateVariables(value, readOnlyText)).toBe(true);
});
it('should return false for a string with variables but no input JSON and required set to false', () => {
// @ts-ignore
const readOnlyText: MultiVariableTextSchema = {
variables: ['var'],
required: false,
};
const value = '';
expect(validateVariables(value, readOnlyText)).toBe(false);
});
});