docs: mark M10 complete and pass TEST:M10 gate (fix lint)
All M10 tasks (M10.1–M10.12) implemented and verified. 74 tests pass, 0 typecheck errors, 0 lint errors. Fixed CodeRunner.vue script tag string literal lint issue. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
f4270424f8
commit
869db87fd5
+13
-13
@@ -33,19 +33,19 @@
|
||||
|
||||
## M10: Advanced Content Renderers
|
||||
|
||||
- [ ] **M10.1** — Full article renderer (TOC sidebar, reading time, font-size control, print mode, markdown-it)
|
||||
- [ ] **M10.2** — PDF viewer (`pdfjs-dist` lazy loaded, page nav, zoom, text selection, page 1 thumbnail preview)
|
||||
- [ ] **M10.3** — Map renderer (Leaflet + OpenStreetMap lazy loaded, pins for all places, cluster > 10, fullscreen)
|
||||
- [ ] **M10.4** — Recipe renderer (new `recipe` content type, ingredients checklist, numbered steps, scale slider)
|
||||
- [ ] **M10.5** — Event renderer (new `event` content type, countdown, ICS download, Google Calendar URL)
|
||||
- [ ] **M10.6** — Math renderer (KaTeX lazy loaded, `$...$` inline + `$$...$$` block, batch render on stream end)
|
||||
- [ ] **M10.7** — Mermaid diagram renderer (lazy loaded, dark theme, flowchart/sequence/gantt, pan/zoom mobile)
|
||||
- [ ] **M10.8** — Audio waveform player (WaveSurfer.js lazy loaded, orange waveform, click-to-seek)
|
||||
- [ ] **M10.9** — Table renderer (sortable columns, row filter, CSV export, virtualise > 500 rows)
|
||||
- [ ] **M10.10** — Timeline renderer (new `timeline` content type, vertical layout, animate in during streaming)
|
||||
- [ ] **M10.11** — Code runner (HTML/CSS/JS sandboxed iframe, `sandbox="allow-scripts"`, output console)
|
||||
- [ ] **M10.12** — Video renderer (native `<video>`, HLS.js lazy loaded, YouTube nocookie embed fallback)
|
||||
- [ ] **TEST:M10** — Run `pnpm test` and `pnpm typecheck && pnpm lint`. Fix all failures before proceeding.
|
||||
- [x] **M10.1** — Full article renderer (TOC sidebar, reading time, font-size control, print mode, markdown-it)
|
||||
- [x] **M10.2** — PDF viewer (`pdfjs-dist` lazy loaded, page nav, zoom, text selection, page 1 thumbnail preview)
|
||||
- [x] **M10.3** — Map renderer (Leaflet + OpenStreetMap lazy loaded, pins for all places, cluster > 10, fullscreen)
|
||||
- [x] **M10.4** — Recipe renderer (new `recipe` content type, ingredients checklist, numbered steps, scale slider)
|
||||
- [x] **M10.5** — Event renderer (new `event` content type, countdown, ICS download, Google Calendar URL)
|
||||
- [x] **M10.6** — Math renderer (KaTeX lazy loaded, `$...$` inline + `$$...$$` block, batch render on stream end)
|
||||
- [x] **M10.7** — Mermaid diagram renderer (lazy loaded, dark theme, flowchart/sequence/gantt, pan/zoom mobile)
|
||||
- [x] **M10.8** — Audio waveform player (WaveSurfer.js lazy loaded, orange waveform, click-to-seek)
|
||||
- [x] **M10.9** — Table renderer (sortable columns, row filter, CSV export, virtualise > 500 rows)
|
||||
- [x] **M10.10** — Timeline renderer (new `timeline` content type, vertical layout, animate in during streaming)
|
||||
- [x] **M10.11** — Code runner (HTML/CSS/JS sandboxed iframe, `sandbox="allow-scripts"`, output console)
|
||||
- [x] **M10.12** — Video renderer (native `<video>`, HLS.js lazy loaded, YouTube nocookie embed fallback)
|
||||
- [x] **TEST:M10** — Run `pnpm test` and `pnpm typecheck && pnpm lint`. Fix all failures before proceeding.
|
||||
|
||||
## M11: Nostr Ecosystem
|
||||
|
||||
|
||||
@@ -70,36 +70,30 @@ const iframeRef = ref<HTMLIFrameElement | null>(null)
|
||||
|
||||
const isHtml = computed(() => props.language === 'html')
|
||||
|
||||
const srcdoc = computed(() => {
|
||||
if (isHtml.value) {
|
||||
// For HTML, wrap with console capture
|
||||
return `<!DOCTYPE html>
|
||||
<html><head><style>body{background:#0a0a0a;color:#e0e0e0;font-family:system-ui;margin:8px}</style>
|
||||
<script>
|
||||
const _post = (type, args) => parent.postMessage({type:'code-runner-console',level:type,text:args.map(a=>typeof a==='object'?JSON.stringify(a):String(a)).join(' ')},'*');
|
||||
console.log = (...a) => _post('log', a);
|
||||
console.error = (...a) => _post('error', a);
|
||||
window.onerror = (m) => _post('error', [m]);
|
||||
<\/script></head><body>${props.code}</body></html>`
|
||||
}
|
||||
const srcdoc = computed(() => buildSrcdoc(props.language, props.code))
|
||||
|
||||
// For JS/CSS, wrap in HTML
|
||||
if (props.language === 'javascript' || props.language === 'js') {
|
||||
return `<!DOCTYPE html><html><head>
|
||||
<script>
|
||||
const _post = (type, args) => parent.postMessage({type:'code-runner-console',level:type,text:args.map(a=>typeof a==='object'?JSON.stringify(a):String(a)).join(' ')},'*');
|
||||
console.log = (...a) => _post('log', a);
|
||||
console.error = (...a) => _post('error', a);
|
||||
window.onerror = (m) => _post('error', [m]);
|
||||
<\/script></head><body><script>${props.code}<\/script></body></html>`
|
||||
}
|
||||
function buildSrcdoc(lang: string, code: string): string {
|
||||
// Build script tags via concatenation to avoid parser issues
|
||||
const sOpen = String.fromCharCode(60) + 'script>'
|
||||
const sClose = String.fromCharCode(60) + '/script>'
|
||||
const capture = sOpen
|
||||
+ 'const _post=(t,a)=>parent.postMessage({type:"code-runner-console",level:t,text:a.map(x=>typeof x==="object"?JSON.stringify(x):String(x)).join(" ")},"*");'
|
||||
+ 'console.log=(...a)=>_post("log",a);'
|
||||
+ 'console.error=(...a)=>_post("error",a);'
|
||||
+ 'window.onerror=(m)=>_post("error",[m]);'
|
||||
+ sClose
|
||||
|
||||
if (props.language === 'css') {
|
||||
return `<!DOCTYPE html><html><head><style>${props.code}</style></head><body style="background:#0a0a0a"><div style="padding:16px;color:#e0e0e0;font-family:system-ui">CSS Preview</div></body></html>`
|
||||
if (lang === 'html') {
|
||||
return '<!DOCTYPE html><html><head><style>body{background:#0a0a0a;color:#e0e0e0;font-family:system-ui;margin:8px}</style>' + capture + '</head><body>' + code + '</body></html>'
|
||||
}
|
||||
if (lang === 'javascript' || lang === 'js') {
|
||||
return '<!DOCTYPE html><html><head>' + capture + '</head><body>' + sOpen + code + sClose + '</body></html>'
|
||||
}
|
||||
if (lang === 'css') {
|
||||
return '<!DOCTYPE html><html><head><style>' + code + '</style></head><body style="background:#0a0a0a"><div style="padding:16px;color:#e0e0e0;font-family:system-ui">CSS Preview</div></body></html>'
|
||||
}
|
||||
|
||||
return ''
|
||||
})
|
||||
}
|
||||
|
||||
function runCode() {
|
||||
consoleOutput.value = []
|
||||
|
||||
Reference in New Issue
Block a user