fix: shorten update notes and contain entry content in cards
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import { renderReleaseMarkdown } from '../release-notes/markdown.ts';
|
||||
|
||||
test('업데이트의 모든 문단과 목록을 하나의 카드에 묶는다', () => {
|
||||
const html = renderReleaseMarkdown('## 날짜\n\n### 기능\n\n첫 문단\n\n추가 문단\n\n- 목록\n\n### 다음 기능\n\n설명');
|
||||
const cards = [...html.matchAll(/<section class="update-entry">([\s\S]*?)<\/section>/g)];
|
||||
assert.equal(cards.length, 2);
|
||||
assert.match(cards[0][1], /첫 문단[\s\S]*추가 문단[\s\S]*<ul>/);
|
||||
assert.doesNotMatch(cards[0][1], /다음 기능/);
|
||||
assert.match(cards[1][1], /다음 기능[\s\S]*설명/);
|
||||
assert.ok(html.indexOf('<h2>') < html.indexOf('<section'));
|
||||
});
|
||||
|
||||
test('구분선과 날짜는 카드 밖에 두고 원시 HTML은 계속 이스케이프한다', () => {
|
||||
const html = renderReleaseMarkdown('### 기능\n\n<script>alert(1)</script>\n\n---\n\n## 다음 날짜\n\n### 새 기능\n\n[문서](https://example.com)');
|
||||
assert.match(html, /<\/section>\s*<hr>/);
|
||||
assert.match(html, /<hr>\s*<h2>다음 날짜<\/h2>\s*<section/);
|
||||
assert.doesNotMatch(html, /<script>/);
|
||||
assert.match(html, /<script>/);
|
||||
assert.match(html, /href="https:\/\/example.com\/"/);
|
||||
});
|
||||
@@ -39,10 +39,26 @@ renderer.image = ({ href, title, text }) => {
|
||||
};
|
||||
|
||||
export function renderReleaseMarkdown(markdown: string): string {
|
||||
return marked.parse(markdown, {
|
||||
const options = {
|
||||
async: false,
|
||||
breaks: true,
|
||||
gfm: true,
|
||||
renderer
|
||||
}) as string;
|
||||
} as const;
|
||||
const tokens = marked.lexer(markdown, options);
|
||||
let html = '';
|
||||
let entryOpen = false;
|
||||
for (const token of tokens) {
|
||||
const boundary = token.type === 'hr' || (token.type === 'heading' && token.depth <= 3);
|
||||
if (boundary && entryOpen) {
|
||||
html += '</section>\n';
|
||||
entryOpen = false;
|
||||
}
|
||||
if (token.type === 'heading' && token.depth === 3) {
|
||||
html += '<section class="update-entry">\n';
|
||||
entryOpen = true;
|
||||
}
|
||||
html += marked.parser([token], options);
|
||||
}
|
||||
return html + (entryOpen ? '</section>\n' : '');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user