Compare commits
2 Commits
1550332d41
...
0a73eda9b2
| Author | SHA1 | Date | |
|---|---|---|---|
| 0a73eda9b2 | |||
| 8dfd35e611 |
@@ -43,7 +43,17 @@ describe('renderMarkdown', () => {
|
|||||||
|
|
||||||
it('shows task lists as ticked boxes nobody can click', () => {
|
it('shows task lists as ticked boxes nobody can click', () => {
|
||||||
const html = renderMarkdown('- [x] Reproducido\n- [ ] Arreglado');
|
const html = renderMarkdown('- [x] Reproducido\n- [ ] Arreglado');
|
||||||
expect(html).toContain('<input checked="" disabled="" type="checkbox">');
|
const boxes = Array.from(
|
||||||
expect(html).toContain('<input disabled="" type="checkbox">');
|
new DOMParser()
|
||||||
|
.parseFromString(html, 'text/html')
|
||||||
|
.querySelectorAll<HTMLInputElement>('input[type="checkbox"]'),
|
||||||
|
);
|
||||||
|
expect(boxes.map((box) => box.checked)).toEqual([true, false]);
|
||||||
|
// Not `disabled` (browsers grey those out): out of reach instead.
|
||||||
|
for (const box of boxes) {
|
||||||
|
expect(box.disabled).toBe(false);
|
||||||
|
expect(box.getAttribute('aria-disabled')).toBe('true');
|
||||||
|
expect(box.tabIndex).toBe(-1);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -67,9 +67,14 @@ function installHooks(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node.tagName === 'INPUT') {
|
if (node.tagName === 'INPUT') {
|
||||||
// Task lists: `- [x] done` renders as a ticked, read-only box.
|
// Task lists: `- [x] done` renders as a ticked box nobody can change.
|
||||||
|
// Not `disabled`: browsers grey those out; CSS takes the clicks away.
|
||||||
if (node.getAttribute('type') !== 'checkbox') node.remove();
|
if (node.getAttribute('type') !== 'checkbox') node.remove();
|
||||||
else node.setAttribute('disabled', '');
|
else {
|
||||||
|
node.removeAttribute('disabled');
|
||||||
|
node.setAttribute('aria-disabled', 'true');
|
||||||
|
node.setAttribute('tabindex', '-1');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const cls = node.getAttribute('class');
|
const cls = node.getAttribute('class');
|
||||||
if (cls && !/^ts-mention( is-me)?$/.test(cls))
|
if (cls && !/^ts-mention( is-me)?$/.test(cls))
|
||||||
@@ -117,7 +122,8 @@ export function renderMarkdown(text: string, me: string | null = null): string {
|
|||||||
'data-user',
|
'data-user',
|
||||||
'type',
|
'type',
|
||||||
'checked',
|
'checked',
|
||||||
'disabled',
|
'aria-disabled',
|
||||||
|
'tabindex',
|
||||||
],
|
],
|
||||||
// DOMPurify's own rule plus `attachment:`: links and images to http(s),
|
// DOMPurify's own rule plus `attachment:`: links and images to http(s),
|
||||||
// mail or a pasted file; plain values (`type="checkbox"`) still pass.
|
// mail or a pasted file; plain values (`type="checkbox"`) still pass.
|
||||||
@@ -179,10 +185,20 @@ export const MARKDOWN_STYLES = `
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Task items: the box takes the bullet's place, so their text lines
|
||||||
|
up with the other items' (as in the editor). */
|
||||||
li:has(> input[type='checkbox']),
|
li:has(> input[type='checkbox']),
|
||||||
li:has(> p:first-child > input[type='checkbox']) {
|
li:has(> p:first-child > input[type='checkbox']) {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin-left: -1.375rem;
|
}
|
||||||
|
li > input[type='checkbox'],
|
||||||
|
li > p:first-child > input[type='checkbox'] {
|
||||||
|
width: 0.875rem;
|
||||||
|
height: 0.875rem;
|
||||||
|
margin: 0 0.25rem 0 -1.375rem;
|
||||||
|
vertical-align: -0.125em;
|
||||||
|
accent-color: var(--ts-brand);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
color: var(--ts-brand);
|
color: var(--ts-brand);
|
||||||
|
|||||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -38,7 +38,7 @@
|
|||||||
"@ngrx/signals": "^22.0.1",
|
"@ngrx/signals": "^22.0.1",
|
||||||
"@ngx-translate/core": "^18.0.0",
|
"@ngx-translate/core": "^18.0.0",
|
||||||
"@ngx-translate/http-loader": "^18.0.0",
|
"@ngx-translate/http-loader": "^18.0.0",
|
||||||
"@pi/ui": "^0.0.6",
|
"@pi/ui": "^0.0.7",
|
||||||
"@tiptap/core": "3.31.3",
|
"@tiptap/core": "3.31.3",
|
||||||
"@tiptap/extension-image": "3.31.3",
|
"@tiptap/extension-image": "3.31.3",
|
||||||
"@tiptap/extension-list": "3.31.3",
|
"@tiptap/extension-list": "3.31.3",
|
||||||
@@ -13518,9 +13518,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@pi/ui": {
|
"node_modules/@pi/ui": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.7",
|
||||||
"resolved": "https://nexus.pireon.dev/repository/npm-releases/@pi/ui/-/ui-0.0.6.tgz",
|
"resolved": "https://nexus.pireon.dev/repository/npm-releases/@pi/ui/-/ui-0.0.7.tgz",
|
||||||
"integrity": "sha1-982qcV3+ZYQqeVXKE5Hf6AOcV8c=",
|
"integrity": "sha1-PkfcIIYypFMmuypt5C3UbxDNJbc=",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"luxon": "^3.0.0",
|
"luxon": "^3.0.0",
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
"@ngrx/signals": "^22.0.1",
|
"@ngrx/signals": "^22.0.1",
|
||||||
"@ngx-translate/core": "^18.0.0",
|
"@ngx-translate/core": "^18.0.0",
|
||||||
"@ngx-translate/http-loader": "^18.0.0",
|
"@ngx-translate/http-loader": "^18.0.0",
|
||||||
"@pi/ui": "^0.0.6",
|
"@pi/ui": "^0.0.7",
|
||||||
"@tiptap/core": "3.31.3",
|
"@tiptap/core": "3.31.3",
|
||||||
"@tiptap/extension-image": "3.31.3",
|
"@tiptap/extension-image": "3.31.3",
|
||||||
"@tiptap/extension-list": "3.31.3",
|
"@tiptap/extension-list": "3.31.3",
|
||||||
|
|||||||
Reference in New Issue
Block a user