openvibers/openvibe.community Commits

A Markdown paste's opening heading is left out when it only repeats the title (the page's h1 shows it) (#148)

OP OpenVibers committed 17 days ago · 42ca7b1eed · 2 files, +16 −3

Changes

ddiff --git a/server/render/pages.js b/server/render/pages.js
iindex 04a9412..5c3a443 100644
---- a/server/render/pages.js
++++ b/server/render/pages.js
@@@ -347,6 +347,16 @@ function shareLinks(p) {
* comments: the paste's typed thread as the comment service shows it to this viewer (null while nobody has
* commented); commentSort 'new' or 'old', commentsAfter the paging cursor. No comments on burn-after-read pastes.
*/
++/** Letters and digits only, lower case: a heading and a title match whatever their punctuation and emoji. */
++const bare = (t) => String(t || '').toLowerCase().replace(/[^\p{L}\p{N}]+/gu, '');
++
++/** A document's opening # heading, dropped when it only repeats the paste's title (the page's h1 already shows it). */
++function withoutTitle(content, title) {
++ const text = String(content || '');
++ const m = text.match(/^\s*# +([^\n]+)\n?/);
++ return m && bare(m[1]) && bare(m[1]) === bare(title) ? text.slice(m[0].length) : text;
++}
++
function pastePage({ paste: p, related, user, comments = null, commentSort = 'new', commentsAfter = null }) {
const isShot = p.type === 'screenshot';
const title = p.title || (isShot ? 'Screenshot' : 'Untitled paste');
@@@ -377,7 +387,7 @@ function pastePage({ paste: p, related, user, comments = null, commentSort = 'ne
</div>`;
// A Markdown paste is a document: shown formatted (the same safe renderer as forum posts), its source a click
// away. Copy, Raw and Download still give the source.
-- bodyBlock = isDoc ? `<div class="md paste-doc">${renderMarkdown(p.content, { headingShift: 1, document: true })}</div>
++ bodyBlock = isDoc ? `<div class="md paste-doc">${renderMarkdown(withoutTitle(p.content, title), { headingShift: 1, document: true })}</div>
<details class="paste-source">
<summary><i class="fa-solid fa-code" aria-hidden="true"></i> Markdown source <span class="muted small">${num(hl.lines)} lines</span></summary>
${code}
ddiff --git a/test/ssr-community.test.js b/test/ssr-community.test.js
iindex c723a73..64c1604 100644
---- a/test/ssr-community.test.js
++++ b/test/ssr-community.test.js
@@@ -94,10 +94,13 @@ const { boot, check, done } = require('./helpers/app');
});
await check('a Markdown paste reads as a document, its source a click away; code pastes are unchanged', async () => {
-- const doc = (await svc.createText(anon, { title: 'Notes', content: '# Notes\n\n### Part\n\n| a | b |\n|---|--:|\n| 1 | 2 |\n\n- x\n - y\n\n<script>alert(1)</script>', language: 'markdown' })).slug;
++ const doc = (await svc.createText(anon, { title: 'Notes', content: '# Notes!\n\n### Part\n\n| a | b |\n|---|--:|\n| 1 | 2 |\n\n- x\n - y\n\n<script>alert(1)</script>', language: 'markdown' })).slug;
const r = await t.get(`/p/${doc}`);
assert.strictEqual(r.status, 200);
-- has(r.text, '<div class="md paste-doc"><h2>Notes</h2>\n<h3>Part</h3>');
++ // Its opening # only repeats the title (the page's h1), so it is left out and ### leads at h2.
++ has(r.text, '<div class="md paste-doc"><h2>Part</h2>');
++ const other = (await svc.createText(anon, { title: 'Release', content: '# Something else\n\ntext', language: 'markdown' })).slug;
++ has((await t.get(`/p/${other}`)).text, '<div class="md paste-doc"><h2>Something else</h2>');
has(r.text, '<td class="al-r">2</td>');
has(r.text, '<li>x<ul><li>y</li></ul></li>');
has(r.text, '<details class="paste-source">');