ontoref/assets/presentation/.tmp-regenerate-reader-docs.mjs
Jesús Pérez d59644b96f
feat: unified auth model, project onboarding, install pipeline, config management
The full scope across this batch: POST /sessions key→token exchange, SessionStore dual-index with revoke_by_id, CLI Bearer injection (ONTOREF_TOKEN), ontoref setup
  --gen-keys, install scripts, daemon config form roundtrip, ADR-004/005, on+re self-description update (fully-self-described), and landing page refresh.
2026-03-13 20:56:31 +00:00

200 lines
9.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'node:fs'
import { resolve } from 'node:path'
import { parser } from '@slidev/cli'
const TOTAL_SECONDS = 30 * 60
const data = await parser.load(resolve('.'), resolve('slides.md'))
const slides = data.slides.map((s, i) => ({
n: i + 1,
name: s.frontmatter?.name || null,
raw: s.content || '',
}))
function stripText(raw) {
let t = raw
t = t.replace(/<!--[\s\S]*?-->/g, ' ')
t = t.replace(/<style[\s\S]*?<\/style>/gi, ' ')
t = t.replace(/```[\s\S]*?```/g, ' [code example] ')
t = t.replace(/<[^>]+>/g, ' ')
t = t.replace(/^\s*::.*::\s*$/gm, ' ')
t = t.replace(/^\s*#\s*/gm, '')
t = t.replace(/^\s*[-*]\s+/gm, '')
t = t.replace(/^\s*\d+\.\s+/gm, '')
t = t.replace(/\[(.*?)\]\((.*?)\)/g, '$1')
t = t.replace(/[`*_~]/g, '')
t = t.replace(/\|/g, ' ')
t = t.replace(/\n{3,}/g, '\n\n')
const lines = t.split(/\r?\n/).map(l => l.trim()).filter(Boolean)
return lines
}
function simplify(line) {
let t = line
const repl = [
[/\binfrastructure\b/gi, 'infra'],
[/\bconfiguration\b/gi, 'config'],
[/\bvalidation\b/gi, 'check'],
[/\breliability\b/gi, 'stable work'],
[/\bdeclarative\b/gi, 'declared'],
[/\borchestrator\b/gi, 'controller'],
[/\bdistributed\b/gi, 'spread out'],
[/\bparadigm\b/gi, 'approach'],
[/\bpragmatism\b/gi, 'practical work'],
[/\bguarantees\b/gi, 'safety rules'],
[/\bprovisioning\b/gi, 'setup'],
[/\bcompiler\b/gi, 'compiler check'],
]
for (const [re, to] of repl) t = t.replace(re, to)
t = t.replace(/\bIaC\b/g, 'I A C').replace(/\bCI\/CD\b/g, 'C I slash C D').replace(/24×7×365/g, 'all day, every day')
t = t.replace(/\s+—\s+/g, '. ').replace(/\s+->\s+/g, '. then ').replace(/,\s*/g, '. ')
t = t.replace(/\s{2,}/g, ' ').trim()
return t
}
function say(line) {
const rules = [
[/\bInfrastructure\b/gi, 'Infrastructure (IN-fruh-STRUHK-cher)'],
[/\bautomation\b/gi, 'automation (aw-tuh-MAY-shun)'],
[/\bconfiguration\b/gi, 'configuration (kun-fig-yuh-RAY-shun)'],
[/\bprovisioning\b/gi, 'provisioning (pruh-VIH-zhuh-ning)'],
[/\bcompiler\b/gi, 'compiler (kum-PIE-ler)'],
[/\breliability\b/gi, 'reliability (rih-lai-uh-BIH-luh-tee)'],
[/\bvalidation\b/gi, 'validation (val-ih-DAY-shun)'],
[/\bdeclarative\b/gi, 'declarative (dih-KLAR-uh-tiv)'],
[/\borchestrator\b/gi, 'orchestrator (OR-kes-tray-ter)'],
[/\bparadigm\b/gi, 'paradigm (PAIR-uh-dym)'],
[/\bRust\b/g, 'Rust (rahst)'],
[/\bSerde\b/g, 'Serde (SER-dee)'],
[/\bOption\b/g, 'Option (OP-shun)'],
[/\benum\b/gi, 'enum (EE-num)'],
[/\bKubernetes\b/gi, 'Kubernetes (koo-ber-NET-eez)'],
[/\bAnsible\b/gi, 'Ansible (AN-suh-buhl)'],
[/\bTerraform\b/gi, 'Terraform (TEH-ruh-form)'],
[/\bCI\/CD\b/g, 'CI/CD (see-eye / see-dee)'],
[/\bIaC\b/g, 'IaC (eye-ay-see)'],
]
let t = line
for (const [re, rep] of rules) t = t.replace(re, rep)
t = t.replace(/\s+—\s+/g, ' / ').replace(/\.\s+/g, '. / ').replace(/:\s+/g, ': / ')
return t
}
function phase(n) {
if (n <= 3) return ['Act 1 - Hook & Promise', 'Low -> Medium', 'Credibilidad y dolor real', 'Calma, pausas limpias']
if (n <= 7) return ['Act 2 - Escalation', 'Medium -> High', 'Crecimiento de complejidad sin control', 'Ritmo creciente']
if (n <= 14) return ['Act 3 - Problem Anatomy', 'High', 'Causa raiz y costo de fallar tarde', 'Didactico, frases cortas']
if (n <= 18) return ['Act 4 - Turning Point', 'Peak', 'No faltan tools, falta paradigma', 'Silencios intencionales']
if (n <= 23) return ['Act 5 - Resolution', 'High -> Medium', 'Types y compiler como respuesta', 'Claro y tecnico']
if (n <= 31) return ['Act 6 - Proof in Production', 'Medium -> High', 'Casos reales e impacto operativo', 'Energetico y concreto']
return ['Act 7 - Close & CTA', 'Medium -> Low', 'Cierre emocional con accion', 'Lento y memorable']
}
const slideTexts = slides.map(s => ({ ...s, lines: stripText(s.raw) }))
// 1) reader-script-en.md
let out = '# Rustikon 2026 - Slide Text (Reader Version)\n\n'
out += 'One section per real Slidev slide (parser-based count).\n\n'
for (const s of slideTexts) {
out += `## Slide ${s.n}${s.name ? ` (name: ${s.name})` : ''}\n\n`
const [story, tension, emphasis, delivery] = phase(s.n)
out += `STORY: ${story}\nTENSION: ${tension}\nEMPHASIS: ${emphasis}\nDELIVERY: ${delivery}\n\n`
if (!s.lines.length) out += '[No readable text]\n\n'
else out += s.lines.join('\n') + '\n\n'
}
fs.writeFileSync('reader-script-en.md', out)
// 2) pronunciation
out = '# Rustikon 2026 - Reader Script with Pronunciation Guide\n\n'
out += 'Use this for practice. Read the SAY line.\n\n'
for (const s of slideTexts) {
out += `## Slide ${s.n}${s.name ? ` (name: ${s.name})` : ''}\n\n`
const [story, tension, emphasis, delivery] = phase(s.n)
out += `STORY: ${story}\nTENSION: ${tension}\nEMPHASIS: ${emphasis}\nDELIVERY: ${delivery}\n\n`
if (!s.lines.length) {
out += 'EN: [No readable text]\nSAY: [No readable text]\n\n'
continue
}
for (const l of s.lines) out += `EN: ${l}\nSAY: ${say(l)}\n\n`
}
fs.writeFileSync('reader-script-en-pronunciation.md', out)
// 3) simple
out = '# Rustikon 2026 - Simple Reader Script (Easy English)\n\n'
out += 'Short and clear lines for easy pronunciation.\n\n'
for (const s of slideTexts) {
out += `## Slide ${s.n}${s.name ? ` (name: ${s.name})` : ''}\n\n`
const [story, tension, emphasis, delivery] = phase(s.n)
out += `STORY: ${story}\nTENSION: ${tension}\nEMPHASIS: ${emphasis}\nDELIVERY: ${delivery}\n\n`
if (!s.lines.length) {
out += '[No readable text]\n\n'
continue
}
for (const l of s.lines) out += `${simplify(l)}\n\n`
}
fs.writeFileSync('reader-script-en-simple.md', out)
// 4) live
out = '# Rustikon 2026 - Live Reader Script (Speech Only)\n\n'
out += 'Only lines to speak. Legend: `/` short pause, `//` long pause.\n\n'
for (const s of slideTexts) {
out += `## Slide ${s.n}${s.name ? ` (name: ${s.name})` : ''}\n\n`
const [story, tension, emphasis, delivery] = phase(s.n)
out += `STORY: ${story}\nTENSION: ${tension}\nEMPHASIS: ${emphasis}\nDELIVERY: ${delivery}\n\n`
const spoken = s.lines.map(simplify).filter(l => /[A-Za-z]/.test(l) && !/^[-=]+$/.test(l))
if (!spoken.length) {
out += '(No spoken text. Move forward.)\n\n'
continue
}
for (const l of spoken) out += `${l.replace(/\.\s+/g, '. / ').replace(/\s+—\s+/g, ' / ')}\n\n`
}
fs.writeFileSync('reader-script-en-live.md', out)
// 5) live 30-min
const weights = slideTexts.map(s => {
const words = s.lines.join(' ').split(/\s+/).filter(Boolean).length
return 6 + words
})
let secs = weights.map(w => Math.round((w / weights.reduce((a,b)=>a+b,0)) * TOTAL_SECONDS))
const minSec=15,maxSec=90
secs = secs.map(v => Math.max(minSec, Math.min(maxSec, v)))
let diff = TOTAL_SECONDS - secs.reduce((a,b)=>a+b,0)
while (diff !== 0) {
let changed = false
for (let i=0; i<secs.length && diff!==0; i++) {
if (diff > 0 && secs[i] < maxSec) { secs[i]++; diff--; changed = true }
else if (diff < 0 && secs[i] > minSec) { secs[i]--; diff++; changed = true }
}
if (!changed) break
}
const mmss = (t)=>`${String(Math.floor(t/60)).padStart(2,'0')}:${String(t%60).padStart(2,'0')}`
out = '# Rustikon 2026 - Live Reader (30-Min Timing)\n\n'
out += 'Total target: 30:00 (1800s)\n\n'
out += 'How to use:\n- Keep your pace near each slide target.\n- If you are late, cut one example line and move on.\n- If you are early, add one short emphasis line.\n\n'
let cum = 0
for (let i=0;i<slideTexts.length;i++) {
const s = slideTexts[i]
cum += secs[i]
out += `## Slide ${s.n}${s.name ? ` (name: ${s.name})` : ''} [target: ${secs[i]}s | cumulative: ${mmss(cum)}]\n\n`
const [story, tension, emphasis, delivery] = phase(s.n)
out += `STORY: ${story}\nTENSION: ${tension}\nEMPHASIS: ${emphasis}\nDELIVERY: ${delivery}\n\n`
const spoken = s.lines.map(simplify).filter(l => /[A-Za-z]/.test(l) && !/^[-=]+$/.test(l))
if (!spoken.length) out += '(No spoken text. Move forward.)\n\n'
else for (const l of spoken) out += `${l.replace(/\.\s+/g, '. / ')}\n\n`
}
out += '## Checkpoints\n\n'
for (const mark of [5,10,15,20,25,30]) {
const target = mark * 60
let c = 0, slideN = 1
for (let i=0;i<secs.length;i++) { c += secs[i]; if (c >= target) { slideN = i + 1; break } }
out += `- ${String(mark).padStart(2,'0')}:00 -> around Slide ${slideN}\n`
}
fs.writeFileSync('reader-script-en-live-30min.md', out)
// 6) key moments for 35 slides
const key = `# Rustikon 2026 - Key Story Moments\n\nUse this as your minimal narrative map for a 30-minute talk.\n\n## Moment 1 - Hook (Slides 1-3)\nPurpose: Win attention and establish credibility.\n\nAnchor line:\n"I have lived this problem for decades, and I wanted one thing: to sleep."\n\n## Moment 2 - Rising Tension (Slides 4-7)\nPurpose: Show complexity growing faster than control.\n\nAnchor line:\n"We changed tools many times, but not the model."\n\n## Moment 3 - Crisis / Root Cause (Slides 8-14)\nPurpose: Make the cost of late failure undeniable.\n\nAnchor line:\n"Fail late is expensive. Fail early is cheap."\n\n## Moment 4 - Turning Point (Slides 15-18)\nPurpose: Reframe the problem.\n\nAnchor line:\n"The problem was not the tools. The problem was the paradigm."\n\n## Moment 5 - Proof in Production (Slides 24-31)\nPurpose: Show real operational evidence.\n\nAnchor line:\n"At 3 AM, the system responds first. Not me."\n\n## Moment 6 - Emotional Close + CTA (Slides 33-35)\nPurpose: Close with trust and clear action.\n\nAnchor line:\n"Rust gave me deterministic systems and better sleep."\n\n## One-Line Backup Version\n1. I lived this problem for decades.\n2. Complexity grew; certainty did not.\n3. Late failures are the real tax.\n4. Types changed the paradigm.\n5. Production proof: lower MTTR and deterministic workflows.\n6. Start small: model infrastructure as types.\n`
fs.writeFileSync('key-moments-storytelling.md', key)
console.log('Real Slidev slides:', slideTexts.length)
console.log('Docs regenerated with parser-based slide count.')