feat: v0.2.2 — plugin refactor, i18n, outline tracking, formatTable, code title, fr locale
CI / test (18.x) (push) Canceled after 0s
CI / test (20.x) (push) Canceled after 0s
CI / test (22.x) (push) Canceled after 0s

## Added
- French (fr) locale with 60+ translations
- Outline panel scroll tracking with active heading highlight
- exec('formatTable') for auto-aligning Markdown table columns
- Code block title rendering via ```js title=hello.js```
- Escaped pipe \| support in table cells
- Custom block token fallback rendering as <div>
- Gutter incremental DOM update (no more full innerHTML)
- 694 tests (+10)

## Changed
- All 6 preset plugins refactored to closure-based state (no this pollution)
- shortcutHelp plugin now i18n-aware (shortcut labels follow locale)
- Context menu labels (Cut/Copy/Paste/Select All) i18n-translated
- Warm theme now has progressBg + closeHoverBg fields
This commit is contained in:
2026-07-25 09:26:54 +08:00
parent aa9f5f220e
commit de545d1da6
13 changed files with 535 additions and 187 deletions
+47 -2
View File
@@ -1022,10 +1022,10 @@ describe('parseMarkdown - 覆盖率:链接引用回退', () => {
});
describe('parseMarkdown - 覆盖率:自定义 token default 渲染', () => {
test('未识别 token type 返回空字符串', () => {
test('未识别 token type 渲染为回退 div', () => {
const tokens = [{ type: 'unknownType', text: 'whatever' }];
const html = renderTokens(tokens);
expect(html).toBe('');
expect(html).toContain('me-block-unknownType');
});
});
@@ -1225,3 +1225,48 @@ describe('parseMarkdown - v0.2.1 引用链接容错', () => {
expect(() => renderTokens([{ type: 'paragraph', text: '[x][bad]' }], { refs: { bad: 'not-json' } })).not.toThrow();
});
});
// ============ v0.2.2 表格转义 ============
describe('parseMarkdown - v0.2.2 表格转义竖线', () => {
test('表格单元格内 \\| 不被分割', () => {
const md = '| Name | Value |\n| --- | --- |\n| a\\|b | c |';
const html = parseMarkdown(md);
// a\|b 应该作为单个单元格内容
expect(html).toContain('a|b');
});
});
// ============ v0.2.2 代码块 info string ============
describe('parseMarkdown - v0.2.2 代码块属性', () => {
test('代码块 title 属性被提取', () => {
const { tokens } = parseTokens('```js title=hello.js\nconsole.log(1)\n```');
const codeToken = tokens.find((t) => t.type === 'code');
expect(codeToken).toBeDefined();
expect(codeToken.lang).toBe('js');
expect(codeToken.attrs).toBeDefined();
expect(codeToken.attrs.title).toBe('hello.js');
});
test('代码块 title 渲染为标题栏', () => {
const html = parseMarkdown('```js title=demo.js\nvar x = 1;\n```');
expect(html).toContain('me-code-title');
expect(html).toContain('demo.js');
});
test('无 title 时不渲染标题栏', () => {
const html = parseMarkdown('```js\nvar x = 1;\n```');
expect(html).not.toContain('me-code-title');
});
});
// ============ v0.2.2 自定义 token 回退渲染 ============
describe('parseMarkdown - v0.2.2 自定义 token 渲染', () => {
test('自定义 token 包含 content 时渲染内容', () => {
const html = renderTokens([{ type: 'customAlert', content: '**Important!**' }]);
expect(html).toContain('me-block-customAlert');
expect(html).toContain('<strong>Important!</strong>');
});
});