From 809d9df4116f313e123b4e82d525bbc94b713c4a Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 18:58:46 +0200 Subject: [PATCH 01/10] =?UTF-8?q?=F0=9F=90=9B=20fix(docs):=20remplace=20js?= =?UTF-8?q?doc-to-markdown=20par=20TypeDoc,=20corrige=20docs:build?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit jsdoc-to-markdown ne parse pas le TypeScript (interfaces, generics, annotations de type ne sont pas du JS valide) : jsdoc:build scannait des .js disparus depuis la migration et générait silencieusement 0 fichier. TypeDoc + typedoc-plugin-markdown gèrent le TS nativement. docs:build écrivait aussi docs-dist HORS du repo : `vitepress build docs-sources --outDir ../docs-dist` résout --outDir relatif au cwd du script npm (racine du repo), pas à docs-sources — le build atterrissait donc dans le répertoire parent du repo, jamais dans .gitignore ni déployable. Corrigé en --outDir docs-dist. docs-sources/developers/code/ (généré à chaque build) devient entièrement gitignored, y compris index.md qui était committé par erreur. --- .gitignore | 2 +- docs-sources/developers/code/index.md | 45 ----- package-lock.json | 235 ++++++++++++++++++++++++-- package.json | 4 +- scripts/jsdoc-build.mjs | 84 ++++----- 5 files changed, 252 insertions(+), 118 deletions(-) delete mode 100644 docs-sources/developers/code/index.md diff --git a/.gitignore b/.gitignore index 512a05b3..86ccbfc3 100644 --- a/.gitignore +++ b/.gitignore @@ -54,7 +54,7 @@ showcase/resources/tc-component/ # Documentation docs-dist -docs-sources/developers/code/parts/ +docs-sources/developers/code/ docs-sources/.vitepress/cache/ # Jetbrains diff --git a/docs-sources/developers/code/index.md b/docs-sources/developers/code/index.md deleted file mode 100644 index 4356bc7e..00000000 --- a/docs-sources/developers/code/index.md +++ /dev/null @@ -1,45 +0,0 @@ -# API Reference - -## Client - -- [engine-resolver](parts/client/engines/engine-resolver.md) -- [generic-client-engine](parts/client/engines/generic-client-engine.md) -- [revealjs-client-engine](parts/client/engines/revealjs-client-engine.md) -- [index](parts/client/tc-component/index.md) -- [tc-component](parts/client/tc-component/tc-component.md) -- [bootstrap](parts/client/tc-controller/bootstrap.md) -- [tc-controller](parts/client/tc-controller/tc-controller.md) - -## Common - -- [event-bus-component](parts/common/event-bus/event-bus-component.md) -- [event-bus-proxy](parts/common/event-bus/event-bus-proxy.md) -- [event-bus-resolver](parts/common/event-bus/event-bus-resolver.md) -- [event-bus](parts/common/event-bus/event-bus.md) -- [event-bus-postmessage](parts/common/event-bus/postmessage/event-bus-postmessage.md) -- [event-bus-websockets-client](parts/common/event-bus/websockets/event-bus-websockets-client.md) -- [event-bus-websockets-server](parts/common/event-bus/websockets/event-bus-websockets-server.md) -- [logger](parts/common/services/logger.md) -- [plugin](parts/common/services/plugin.md) -- [presentation](parts/common/services/presentation.md) -- [url](parts/common/services/url.md) - -## Environment - -- [config-file](parts/environment/services/config-file.md) -- [tunnel](parts/environment/services/tunnel.md) - -## Plugins - -- [plugin-loader](parts/plugins/plugin-loader.md) - -## Server - -- [bootstrap](parts/server/bootstrap.md) -- [patcher.controller](parts/server/controllers/patcher.controller.md) -- [proxy.controller](parts/server/controllers/proxy.controller.md) -- [engine-resolver](parts/server/engines/engine-resolver.md) -- [generic-server-engine](parts/server/engines/generic-server-engine.md) -- [revealjs-server-engine](parts/server/engines/revealjs-server-engine.md) -- [index](parts/server/store/index.md) -- [tc-server](parts/server/tc-server.md) diff --git a/package-lock.json b/package-lock.json index 95d811e4..9aa59dc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,6 +56,8 @@ "reveal.js": "^6.0.1", "supertest": "^7.2.2", "tsx": "^4.23.0", + "typedoc": "^0.28.20", + "typedoc-plugin-markdown": "^4.12.0", "typescript": "^5.9.3", "typescript-eslint": "^8.63.0", "vite": "^8.1.4", @@ -1079,6 +1081,62 @@ "node": ">=6" } }, + "node_modules/@gerrit0/mini-shiki": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.23.0.tgz", + "integrity": "sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-oniguruma": "^3.23.0", + "@shikijs/langs": "^3.23.0", + "@shikijs/themes": "^3.23.0", + "@shikijs/types": "^3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/engine-oniguruma": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/langs": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/themes": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/@hapi/address": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", @@ -6242,9 +6300,9 @@ } }, "node_modules/linkify-it": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", - "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", "dev": true, "funding": [ { @@ -6308,6 +6366,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true, + "license": "MIT" + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -6338,9 +6403,9 @@ "license": "MIT" }, "node_modules/markdown-it": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", - "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz", + "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==", "dev": true, "funding": [ { @@ -6355,8 +6420,8 @@ "license": "MIT", "dependencies": { "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.1", + "entities": "^4.5.0", + "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -8678,6 +8743,43 @@ "url": "https://opencollective.com/express" } }, + "node_modules/typedoc": { + "version": "0.28.20", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.20.tgz", + "integrity": "sha512-uSKqkh8Cr48vllnEy+jdaAgOeR6Y+QCBW7usgUsKj7gJEfR7stw9U/fE49LBnj2tPRKPY0c0EBJSWe9Appmplg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@gerrit0/mini-shiki": "^3.23.0", + "lunr": "^2.3.9", + "markdown-it": "^14.3.0", + "minimatch": "^10.2.5", + "yaml": "^2.9.0" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18", + "pnpm": ">= 10" + }, + "peerDependencies": { + "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x || 6.0.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.12.0.tgz", + "integrity": "sha512-eJDEMAfxCmede22c/Jw7d0FA13ggAQv+KkwQYKYCdqI02cin6Rc9QRwbG/7XvvHWinuFejySnZVUWDtvGk3Vbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "typedoc": "0.28.x" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -9393,6 +9495,22 @@ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -9943,6 +10061,59 @@ "@fortawesome/fontawesome-common-types": "7.3.0" } }, + "@gerrit0/mini-shiki": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.23.0.tgz", + "integrity": "sha512-bEMORlG0cqdjVyCEuU0cDQbORWX+kYCeo0kV1lbxF5bt4r7SID2l9bqsxJEM0zndaxpOUT7riCyIVEuqq/Ynxg==", + "dev": true, + "requires": { + "@shikijs/engine-oniguruma": "^3.23.0", + "@shikijs/langs": "^3.23.0", + "@shikijs/themes": "^3.23.0", + "@shikijs/types": "^3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + }, + "dependencies": { + "@shikijs/engine-oniguruma": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "dev": true, + "requires": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "@shikijs/langs": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "dev": true, + "requires": { + "@shikijs/types": "3.23.0" + } + }, + "@shikijs/themes": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "dev": true, + "requires": { + "@shikijs/types": "3.23.0" + } + }, + "@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "dev": true, + "requires": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + } + } + }, "@hapi/address": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@hapi/address/-/address-5.1.1.tgz", @@ -13165,9 +13336,9 @@ "optional": true }, "linkify-it": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", - "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.2.tgz", + "integrity": "sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==", "dev": true, "requires": { "uc.micro": "^2.0.0" @@ -13215,6 +13386,12 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -13242,14 +13419,14 @@ "dev": true }, "markdown-it": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", - "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "version": "14.3.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.3.0.tgz", + "integrity": "sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==", "dev": true, "requires": { "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.1", + "entities": "^4.5.0", + "linkify-it": "^5.0.2", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -14733,6 +14910,26 @@ } } }, + "typedoc": { + "version": "0.28.20", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.20.tgz", + "integrity": "sha512-uSKqkh8Cr48vllnEy+jdaAgOeR6Y+QCBW7usgUsKj7gJEfR7stw9U/fE49LBnj2tPRKPY0c0EBJSWe9Appmplg==", + "dev": true, + "requires": { + "@gerrit0/mini-shiki": "^3.23.0", + "lunr": "^2.3.9", + "markdown-it": "^14.3.0", + "minimatch": "^10.2.5", + "yaml": "^2.9.0" + } + }, + "typedoc-plugin-markdown": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.12.0.tgz", + "integrity": "sha512-eJDEMAfxCmede22c/Jw7d0FA13ggAQv+KkwQYKYCdqI02cin6Rc9QRwbG/7XvvHWinuFejySnZVUWDtvGk3Vbg==", + "dev": true, + "requires": {} + }, "typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -15122,6 +15319,12 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" }, + "yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "dev": true + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index ce509198..22fb5b80 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "tc-controller-and-component": "vite --port 3000", "tc-server": "npx nodemon --exec \"npx tsx\" src/server/index.ts", "docs:dev": "vitepress dev docs-sources", - "docs:build": "npm run jsdoc:build && vitepress build docs-sources --outDir ../docs-dist", + "docs:build": "npm run jsdoc:build && vitepress build docs-sources --outDir docs-dist", "jsdoc:build": "node scripts/jsdoc-build.mjs", "test:components": "vitest run --config vitest.browser.config.ts", "test:e2e": "node node_modules/@playwright/test/cli.js test --config playwright.config.cjs", @@ -80,6 +80,8 @@ "reveal.js": "^6.0.1", "supertest": "^7.2.2", "tsx": "^4.23.0", + "typedoc": "^0.28.20", + "typedoc-plugin-markdown": "^4.12.0", "typescript": "^5.9.3", "typescript-eslint": "^8.63.0", "vite": "^8.1.4", diff --git a/scripts/jsdoc-build.mjs b/scripts/jsdoc-build.mjs index 8c2b5587..08774e2a 100644 --- a/scripts/jsdoc-build.mjs +++ b/scripts/jsdoc-build.mjs @@ -1,64 +1,38 @@ #!/usr/bin/env node /** - * Replaces vuepress-jsdoc: scans src/, generates per-file Markdown via jsdoc-to-markdown, - * writes to docs-sources/developers/code/parts/ and regenerates the README index. + * Generates the API reference under docs-sources/developers/code/ via TypeDoc + typedoc-plugin-markdown. + * Replaces jsdoc-to-markdown (step 16): jsdoc's parser cannot handle TypeScript syntax (interfaces, + * generics, type annotations aren't valid JS), and src/ has been 100% TypeScript since the lit/event-bus + * migration — jsdoc:build silently generated 0 files. */ -import jsdoc2md from 'jsdoc-to-markdown'; -import { mkdirSync, writeFileSync, readdirSync } from 'fs'; -import { join, relative, dirname, basename } from 'path'; +import { Application, TSConfigReader } from 'typedoc'; +import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const __dirname = dirname(fileURLToPath(import.meta.url)); const root = join(__dirname, '..'); -const srcDir = join(root, 'src'); -const partsDir = join(root, 'docs-sources/developers/code/parts'); - -/** - * Recursively collects .js source files under `dir`, excluding *.spec.js. - * - * @param {string} dir - directory to scan - * @returns {string[]} absolute paths of matching files - */ -function findJsFiles(dir) { - const entries = readdirSync(dir, { withFileTypes: true }); - return entries.flatMap(entry => { - const full = join(dir, entry.name); - if (entry.isDirectory()) return findJsFiles(full); - if (entry.isFile() && entry.name.endsWith('.js') && !entry.name.endsWith('.spec.js')) return [full]; - return []; - }); -} - -const generated = []; - -for (const file of findJsFiles(srcDir)) { - const relPath = relative(srcDir, file).replace(/\.js$/, '.md'); - const outFile = join(partsDir, relPath); - - const md = await jsdoc2md.render({ files: file }); - if (!md.trim()) continue; - - mkdirSync(dirname(outFile), { recursive: true }); - writeFileSync(outFile, md); - generated.push(relPath); -} - -// Regenerate the README index grouped by top-level directory -const byGroup = generated.reduce((acc, f) => { - const group = f.split('/')[0]; - (acc[group] ??= []).push(f); - return acc; -}, {}); - -const indexLines = ['# API Reference\n']; -for (const [group, files] of Object.entries(byGroup).sort()) { - indexLines.push(`## ${group.charAt(0).toUpperCase() + group.slice(1)}\n`); - for (const f of files.sort()) { - const name = basename(f, '.md'); - indexLines.push(`- [${name}](parts/${f})`); - } - indexLines.push(''); +const out = join(root, 'docs-sources/developers/code'); + +const app = await Application.bootstrapWithPlugins( + { + entryPoints: ['src'], + entryPointStrategy: 'expand', + tsconfig: 'tsconfig.json', + exclude: ['src/environment/**', 'src/client/layouts/**', '**/*.spec.ts', 'src/vite-env.d.ts'], + plugin: ['typedoc-plugin-markdown'], + readme: 'none', + entryFileName: 'index.md', + githubPages: false, + out + }, + [new TSConfigReader()] +); + +const project = await app.convert(); +if (!project) { + console.error('jsdoc-build: TypeDoc conversion failed'); + process.exit(1); } -writeFileSync(join(root, 'docs-sources/developers/code/index.md'), indexLines.join('\n')); -console.log(`jsdoc-build: ${generated.length} file(s) generated in docs-sources/developers/code/parts/`); +await app.generateOutputs(project); +console.log(`jsdoc-build: API reference generated in ${out}`); From 945512c4b1e43790eccd45e7c25cf116adaabe79 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 18:58:55 +0200 Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=94=A7=20chore(docs):=20aligne=20le?= =?UTF-8?q?s=20URLs=20GitHub=20sur=20l'org=20finale,=20retire=20--legacy-p?= =?UTF-8?q?eer-deps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit origin pointait sur sfeir-open-source/talk-control (fork) alors que TalkControl/talk-control est l'organisation finale (droits admin vérifiés) — develop y a été poussé (fast-forward, 106 commits) dans le cadre de cette étape. Réaligne badges, liens Issues/PR/fork et editLink VitePress sur TalkControl/talk-control. README.md:18 — finalise le retrait de --legacy-peer-deps commencé à l'étape 06 (IMP-004) : `npm install` seul suffit désormais. Note : docs-sources/developers/index.md, users/index.md et index.md contiennent encore des références sfeir-open-source noyées dans du contenu pré-migration obsolète (Node 8, parcelJs, mocha/chai) — laissés en l'état, hors scope (nécessite une réécriture de contenu, pas une simple URL). --- CONTRIBUTING.md | 4 ++-- README.md | 12 ++++++------ docs-sources/.vitepress/config.js | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4897afac..e25c7993 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,11 +53,11 @@ Unfortunately, we are not able to investigate / fix bugs without a minimal repro Before you submit your Pull Request (PR) consider the following guidelines: -1. Search [GitHub](https://github.com/sfeir-open-source/talk-control/pulls) for an open or closed PR +1. Search [GitHub](https://github.com/TalkControl/talk-control/pulls) for an open or closed PR that relates to your submission. You don't want to duplicate effort. 1. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add. Discussing the design up front helps to ensure that we're ready to accept your work. -1. Fork the sfeir-open-source/talk-control repo. +1. Fork the TalkControl/talk-control repo. 1. Make your changes in a new git branch, based on our develop branch: ```shell diff --git a/README.md b/README.md index b3b4e32a..5e2a2350 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # TalkControl -![version](https://img.shields.io/github/package-json/v/sfeir-open-source/talk-control?color=blue) -![license](https://img.shields.io/github/license/sfeir-open-source/talk-control) -![open issues](https://img.shields.io/github/issues-raw/sfeir-open-source/talk-control) -![CI develop](https://github.com/sfeir-open-source/talk-control/actions/workflows/develop.yml/badge.svg?branch=develop) +![version](https://img.shields.io/github/package-json/v/TalkControl/talk-control?color=blue) +![license](https://img.shields.io/github/license/TalkControl/talk-control) +![open issues](https://img.shields.io/github/issues-raw/TalkControl/talk-control) +![CI develop](https://github.com/TalkControl/talk-control/actions/workflows/develop.yml/badge.svg?branch=develop) TalkControl lets speakers remotely control their slideshow from any device — phone, tablet, or second screen — via a web interface synchronized with the presentation. @@ -15,7 +15,7 @@ TalkControl lets speakers remotely control their slideshow from any device — p ## Getting started ```bash -npm install --legacy-peer-deps +npm install npm start ``` @@ -96,7 +96,7 @@ npm run docs:build # Build static docs ## Contribute See [CONTRIBUTING.md](CONTRIBUTING.md) for commit conventions and pull request guidelines. -Issues: [github.com/sfeir-open-source/talk-control/issues](https://github.com/sfeir-open-source/talk-control/issues) +Issues: [github.com/TalkControl/talk-control/issues](https://github.com/TalkControl/talk-control/issues) ## Troubleshoot diff --git a/docs-sources/.vitepress/config.js b/docs-sources/.vitepress/config.js index 6668e844..b7a3b3f0 100644 --- a/docs-sources/.vitepress/config.js +++ b/docs-sources/.vitepress/config.js @@ -14,7 +14,7 @@ export default { '/developers/': [{ text: 'Developer Guide', link: '/developers/' }], }, editLink: { - pattern: 'https://github.com/sfeir-open-source/talk-control/edit/develop/docs-sources/:path', + pattern: 'https://github.com/TalkControl/talk-control/edit/develop/docs-sources/:path', }, sidebarMenuLabel: 'Menu', }, From b5d269930efa2b94e998c8cfd9e7823f7086cf71 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 18:59:09 +0200 Subject: [PATCH 03/10] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(ci):=20refo?= =?UTF-8?q?nte=20de=20develop.yml=20(lint,=20cache=20Playwright,=20d=C3=A9?= =?UTF-8?q?dup,=20concurrency)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constats de l'audit (docs/improvements/step-16-ci.md) tous confirmés sur l'état actuel : pas de lint, 3× `playwright install --with-deps` sans cache, job coverage qui ré-exécutait toutes les suites déjà lancées par unit-and-integration + web-components, pas de concurrency/permissions/ timeout-minutes, server-smoke qui ne pouvait jamais échouer (`|| true`). - Nouveau job `lint` → `npm run lint:check`, bloquant. - Cache `~/.cache/ms-playwright` keyé sur la version de `@playwright/test` du lockfile (jobs coverage + e2e) : évite le téléchargement à froid du binaire chromium à chaque run, seul `install-deps` (apt, léger) reste nécessaire au cache hit. - Dédup tests/coverage — option (a) retenue (cf. step-16-ci.md) : le job `coverage` (jsdom + browser + merge) remplace unit-and-integration et web-components. Chaque suite ne tourne plus qu'une fois par run au lieu de deux (jsdom/browser exécutés une fois nativement, une fois via coverage:*). - Coverage gate vérifié réellement bloquant : testé en local avec un seuil `lines` artificiellement remonté à 99 → `ERROR: Coverage for lines (94.43%) does not meet global threshold (99%)`, exit 1 confirmé, seuils réels remis en place. - `concurrency` (annule les runs obsolètes), `permissions: contents: read` au niveau workflow, `timeout-minutes` sur chaque job. - `server-smoke` : retire le `|| true` masquant, vérifie le vrai contrat de `/socket.io/` (HTTP 400 + `Transport unknown` — / répond 404, pas de route racine côté Express, testé en local). - Nouveau job `docs-deploy` : build + déploie la doc VitePress sur GitHub Pages, uniquement sur push develop et après succès de tous les autres jobs (`needs`). Permissions minimales `pages: write` / `id-token: write`, scopées à ce job. GitHub Pages activé sur TalkControl/talk-control (source = GitHub Actions). --- .github/workflows/develop.yml | 164 ++++++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 46 deletions(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index c75df819..6f6e64cf 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -8,13 +8,21 @@ on: branches: - develop +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + jobs: # ---------------------------------------------------------------- - # Job 1 — Tests unitaires et intégration (Vitest jsdom) + # Job 1 — Lint (ESLint, non destructif) # ---------------------------------------------------------------- - unit-and-integration: - name: Tests Vitest (jsdom) — Node 24 + lint: + name: Lint — Node 24 runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 @@ -27,15 +35,16 @@ jobs: - name: Install dependencies run: npm ci - - name: Run tests - run: NODE_ENV=test npm test + - name: Lint check + run: npm run lint:check # ---------------------------------------------------------------- - # Job 2 — Tests web components en browser mode (Vitest + Playwright) + # Job 2 — TypeScript strict # ---------------------------------------------------------------- - web-components: - name: Web components (browser mode) — Node 24 + typecheck: + name: TypeScript strict — Node 24 runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 @@ -48,18 +57,16 @@ jobs: - name: Install dependencies run: npm ci - - name: Install Playwright chromium - run: npx playwright install chromium --with-deps - - - name: Run web component tests - run: npm run test:components + - name: TypeScript strict check + run: npx tsc --noEmit # ---------------------------------------------------------------- - # Job 3 — Tests E2E Playwright + # Job 3 — Vite build (production) # ---------------------------------------------------------------- - e2e: - name: E2E Playwright — Node 24 + build-check: + name: Vite build — Node 24 runs-on: ubuntu-latest + timeout-minutes: 10 steps: - uses: actions/checkout@v4 @@ -72,18 +79,18 @@ jobs: - name: Install dependencies run: npm ci - - name: Install Playwright chromium - run: npx playwright install chromium --with-deps - - - name: Run E2E tests - run: npm run test:e2e + - name: Build (production) + run: npm run build # ---------------------------------------------------------------- - # Job 4 — Coverage + # Job 4 — Coverage (jsdom + browser + merge) : seul job qui lance les + # suites Vitest. Remplace les anciens jobs unit-and-integration et + # web-components pour ne plus exécuter chaque suite 2× par run (étape 16). # ---------------------------------------------------------------- coverage: name: Coverage check — Node 24 runs-on: ubuntu-latest + timeout-minutes: 20 steps: - uses: actions/checkout@v4 @@ -96,18 +103,35 @@ jobs: - name: Install dependencies run: npm ci - - name: Install Playwright chromium - run: npx playwright install chromium --with-deps + - name: Get Playwright version + id: playwright-version + run: echo "version=$(node -p "require('./package-lock.json').packages['node_modules/@playwright/test'].version")" >> "$GITHUB_OUTPUT" + + - name: Cache Playwright browsers + id: playwright-cache + uses: actions/cache@v4 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }} + + - name: Install Playwright chromium (cold) + if: steps.playwright-cache.outputs.cache-hit != 'true' + run: npx playwright install --with-deps chromium + + - name: Install Playwright OS dependencies (cache hit) + if: steps.playwright-cache.outputs.cache-hit == 'true' + run: npx playwright install-deps chromium - - name: Run coverage (thresholds enforced in vitest.config.ts) + - name: Run coverage (jsdom + browser + merge — thresholds enforced in vitest.config.ts) run: NODE_ENV=test npm run coverage # ---------------------------------------------------------------- - # Job 5 — Vite build (production) + # Job 5 — Tests E2E Playwright # ---------------------------------------------------------------- - build-check: - name: Vite build — Node 24 + e2e: + name: E2E Playwright — Node 24 runs-on: ubuntu-latest + timeout-minutes: 15 steps: - uses: actions/checkout@v4 @@ -120,15 +144,35 @@ jobs: - name: Install dependencies run: npm ci - - name: Build (production) - run: npm run build + - name: Get Playwright version + id: playwright-version + run: echo "version=$(node -p "require('./package-lock.json').packages['node_modules/@playwright/test'].version")" >> "$GITHUB_OUTPUT" + + - name: Cache Playwright browsers + id: playwright-cache + uses: actions/cache@v4 + with: + path: ~/.cache/ms-playwright + key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }} + + - name: Install Playwright chromium (cold) + if: steps.playwright-cache.outputs.cache-hit != 'true' + run: npx playwright install --with-deps chromium + + - name: Install Playwright OS dependencies (cache hit) + if: steps.playwright-cache.outputs.cache-hit == 'true' + run: npx playwright install-deps chromium + + - name: Run E2E tests + run: npm run test:e2e # ---------------------------------------------------------------- - # Job 6 — TypeScript strict + # Job 6 — Smoke test du serveur Express # ---------------------------------------------------------------- - typecheck: - name: TypeScript strict — Node 24 + server-smoke: + name: Server smoke test — Node 24 runs-on: ubuntu-latest + timeout-minutes: 5 steps: - uses: actions/checkout@v4 @@ -141,15 +185,40 @@ jobs: - name: Install dependencies run: npm ci - - name: TypeScript strict check - run: npx tsc --noEmit + - name: Start server in background + run: npm run smoke:server & + + - name: Wait for server on port 3001 + run: npx wait-on tcp:3001 --timeout 30000 + + - name: Check server responds (socket.io handshake) + run: | + status=$(curl -s -o /tmp/smoke.out -w '%{http_code}' http://localhost:3001/socket.io/) + echo "HTTP status: $status" + cat /tmp/smoke.out + echo + if [ "$status" != "400" ] || ! grep -q "Transport unknown" /tmp/smoke.out; then + echo "::error::Réponse inattendue de /socket.io/ (status=$status) — le serveur ne répond pas correctement" + exit 1 + fi # ---------------------------------------------------------------- - # Job 7 — Smoke test du serveur Express + # Job 7 — Déploiement de la documentation VitePress (GitHub Pages) + # Uniquement sur push develop, et seulement si toute la CI est verte. # ---------------------------------------------------------------- - server-smoke: - name: Server smoke test — Node 24 + docs-deploy: + name: Deploy docs — GitHub Pages + if: github.event_name == 'push' && github.ref == 'refs/heads/develop' + needs: [lint, typecheck, build-check, coverage, e2e, server-smoke] runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: read + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} steps: - uses: actions/checkout@v4 @@ -162,14 +231,17 @@ jobs: - name: Install dependencies run: npm ci - - name: Start server in background - run: npm run smoke:server & + - name: Build docs (API reference + VitePress) + run: npm run docs:build - - name: Wait for server on port 3001 - run: npx wait-on tcp:3001 --timeout 30000 + - name: Configure GitHub Pages + uses: actions/configure-pages@v5 - - name: Check server responds - run: curl -sf http://localhost:3001/ || curl -sf http://localhost:3001/socket.io/ || true + - name: Upload docs artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs-dist - - name: Server started successfully - run: echo "Server smoke test passed — port 3001 is open" + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 From 951b016a6a028605dda988ac7c5eee626cc722e4 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 18:59:16 +0200 Subject: [PATCH 04/10] =?UTF-8?q?=E2=9C=A8=20feat(ci):=20workflow=20de=20r?= =?UTF-8?q?elease=20automatique=20sur=20tag=20v*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit build + lint + test + build avant toute release (pas de tag cassé), puis création d'une release GitHub via `gh release create` — notes extraites de la section CHANGELOG.md correspondante, fallback sur --generate-notes si absente. Pas de publish npm : le projet n'est pas une lib (cf. étape 02). --- .github/workflows/release.yml | 76 +++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..d95ed016 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,76 @@ +name: Release + +on: + push: + tags: + - 'v*' + +permissions: + contents: read + +jobs: + # ---------------------------------------------------------------- + # Job 1 — Build + test avant toute release (pas de tag cassé) + # ---------------------------------------------------------------- + build-and-test: + name: Build + test — Node 24 + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: actions/checkout@v4 + + - name: Setup Node 24 + uses: actions/setup-node@v4 + with: + node-version: '24' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: TypeScript strict check + run: npx tsc --noEmit + + - name: Lint check + run: npm run lint:check + + - name: Run tests + run: NODE_ENV=test npm test + + - name: Build (production) + run: npm run build + + # ---------------------------------------------------------------- + # Job 2 — Release GitHub avec notes tirées du CHANGELOG (pas de publish npm, + # le projet n'est pas une lib — cf. étape 02) + # ---------------------------------------------------------------- + release: + name: Create GitHub release + needs: build-and-test + runs-on: ubuntu-latest + timeout-minutes: 10 + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + + - name: Extract CHANGELOG section for this tag + id: changelog + run: | + version="${GITHUB_REF_NAME#v}" + awk -v ver="$version" ' + $0 ~ "^## \\[" ver "\\]" { found=1; next } + found && $0 ~ "^## \\[" { exit } + found { print } + ' CHANGELOG.md > /tmp/release-notes.md + echo "notes_found=$([ -s /tmp/release-notes.md ] && echo true || echo false)" >> "$GITHUB_OUTPUT" + + - name: Create release + env: + GH_TOKEN: ${{ github.token }} + run: | + if [ "${{ steps.changelog.outputs.notes_found }}" = "true" ]; then + gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file /tmp/release-notes.md + else + gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --generate-notes + fi From 9aa496a075e70658e68b116b3ec9f305ce6ef607 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 20:29:22 +0200 Subject: [PATCH 05/10] =?UTF-8?q?=F0=9F=93=9D=20docs(improvements):=20?= =?UTF-8?q?=C3=A9tape=2016=20en=20cours=20=E2=80=94=20IMP-013=20et=20IMP-0?= =?UTF-8?q?14=20document=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dédup coverage (option a) et remplacement jsdoc-to-markdown → TypeDoc tracés dans decisions.md. Étape 16 laissée ⬜ dans le README du plan jusqu'à l'observation d'un run CI réel (PR #36) — le blocage org GitHub Actions (allowed_actions=local_only, débloqué en cours de session) empêchait toute exécution jusqu'ici. --- docs/improvements/README.md | 2 +- docs/improvements/decisions.md | 73 ++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/docs/improvements/README.md b/docs/improvements/README.md index e2fdedae..f883bb8f 100644 --- a/docs/improvements/README.md +++ b/docs/improvements/README.md @@ -93,7 +93,7 @@ Garde-fous quel que soit le modèle : exécuter réellement les 6 commandes de v | Étape | Statut | Contenu | |---|---|---| | [15 — Gaps de tests](step-15-test-gaps.md) | ✅ | Modules non testés comblés (plugin.ts, tc-controller, touch-pointer, wrappers, server/bootstrap), helpers factorisés (`test/helpers/dom.ts`), seuils remontés (80/90/70/80), `changeSlide` mort supprimé (IMP-012), doc coverage régénérée | -| [16 — CI refonte](step-16-ci.md) | ⬜ | Lint bloquant, caches Playwright, concurrency, dédup jobs, déploiement docs | +| [16 — CI refonte](step-16-ci.md) | ⬜ | Lint bloquant, cache Playwright, dédup jobs (IMP-013), TypeDoc remplace jsdoc-to-markdown (IMP-014), déploiement docs GitHub Pages, release sur tag — en attente du run CI réel (blocage org débloqué, PR #36) | ### Phase F — Agentic diff --git a/docs/improvements/decisions.md b/docs/improvements/decisions.md index 7cce77d4..59f0c7e8 100644 --- a/docs/improvements/decisions.md +++ b/docs/improvements/decisions.md @@ -600,3 +600,76 @@ pas un test tautologique — cf. `test/client/engines/generic-client-engine.spec le couvrait, donc rien à adapter ailleurs). Couverture de `generic-client-engine.ts` : 4 tests comportementaux ajoutés (init/goToSlide no-op, getSlides() → `[]`, getSlideNotes() → `null`), en plus du test de constructeur préexistant. + +--- + +## IMP-013 — Dédup des jobs tests/coverage en CI + +**Étape :** 16 | **Statut :** ✅ décidé et implémenté (2026-07-13, branche `chore/step-16-ci`) + +### Contexte +`develop.yml` faisait tourner chaque suite Vitest deux fois par run : une fois nue +(`unit-and-integration` pour jsdom, `web-components` pour le mode browser), une fois de plus à +l'intérieur du job `coverage` (`coverage:jsdom` + `coverage:browser` + `coverage:merge`, avec +seuils désactivés sur les deux premiers puis appliqués au merge). Le plan (step-16-ci.md) proposait +deux options : (a) supprimer les jobs nus et faire du job `coverage` le seul qui exécute les +suites, (b) garder les jobs nus rapides sur chaque PR et réserver `coverage` au push `develop`. + +### Décision +**Option (a).** Le job `coverage` remplace `unit-and-integration` et `web-components` : chaque +suite ne tourne plus qu'une fois par run (dans `coverage:jsdom`/`coverage:browser`), au lieu de +deux. Mesuré en local : `NODE_ENV=test npm run coverage` (jsdom + browser + merge) = ~13 s contre +un total antérieur de trois exécutions distinctes (jsdom nue + browser nue + jsdom/browser à +nouveau dans coverage) largement plus long. L'option (b) aurait gardé le feedback PR plus fin +(jobs séparés) mais au prix de dupliquer l'exécution sur chaque push `develop`, sans bénéfice net +puisque le job `coverage` seul reste rapide. + +### Conséquences +7 jobs → 6 (`lint`, `typecheck`, `build-check`, `coverage`, `e2e`, `server-smoke`) + `docs-deploy` +conditionnel. Le gate de seuils (`vitest.config.ts`, 80/90/70/80 depuis l'étape 15) reste porté par +`coverage:merge`, vérifié réellement bloquant en local (seuil `lines` remonté artificiellement à +99 → `ERROR: Coverage for lines (94.43%) does not meet global threshold (99%)`, exit 1, seuils +réels restaurés immédiatement après test). + +--- + +## IMP-014 — Remplacement de jsdoc-to-markdown par TypeDoc + +**Étape :** 16 | **Statut :** ✅ décidé et implémenté (2026-07-13, branche `chore/step-16-ci`) + +### Contexte +`scripts/jsdoc-build.mjs` scannait des `.js` sous `src/` — disparus depuis la migration TypeScript +(lit/event-bus, étapes 10-11). `jsdoc:build` généraient silencieusement 0 fichier (`generated.length +=== 0`, pas d'erreur), donc `docs:build` produisait une doc API vide sans jamais faire échouer la CI. +Vérification empirique avant de corriger : `jsdoc-to-markdown` (donc `jsdoc` en dessous) ne parse pas +la syntaxe TypeScript — passer un fichier `.ts` réel produit `SyntaxError: This experimental syntax +requires enabling one of the following parser plugin(s): "flow", "typescript"`, sans option exposée +par `jsdoc-to-markdown` pour activer ce plugin babel. Ce n'est donc pas un scan de mauvaise extension +à corriger : jsdoc est structurellement incompatible avec `src/` 100 % TypeScript. + +### Options +- **(a)** Patcher `jsdoc-to-markdown`/`jsdoc` pour accepter le TS (pas d'option exposée, aurait + nécessité de forker ou monkey-patcher une dépendance — contraire à KISS). +- **(b)** Transpiler `src/**/*.ts` vers du JS en conservant les commentaires JSDoc avant de les + passer à `jsdoc-to-markdown` — pipeline supplémentaire fragile, réinvente ce que TypeDoc fait + déjà nativement. +- **(c)** Remplacer l'outil par **TypeDoc + `typedoc-plugin-markdown`** — support TS natif (c'est + le compilateur TypeScript lui-même), génère du Markdown consommable par VitePress. + +### Décision +**(c).** `typedoc@0.28.20` + `typedoc-plugin-markdown@4.12.0` (peer-compatibles, versions courantes +au moment de l'étape). `scripts/jsdoc-build.mjs` réécrit pour utiliser l'API programmatique +(`Application.bootstrapWithPlugins` + `generateOutputs`), même nom de fichier/scripts npm conservés +(`jsdoc:build`, `docs:build`) pour ne pas propager un renommage dans le reste de la documentation +historique qui référence ces noms (`docs/migration/`, `docs/improvements/`). `entryFileName: +'index.md'` + `readme: 'none'` pour rester compatible avec le routing VitePress (`index.md` comme +page de dossier) sans dupliquer le contenu du README racine. + +### Conséquences +179 pages Markdown générées (contre 0 avant), `docs:build` produit une doc API non vide et +consommable par VitePress. `docs-sources/developers/code/` devient entièrement gitignored +(généré à chaque build, y compris son `index.md` qui était committé par erreur auparavant). +Bug additionnel découvert et corrigé au passage : `docs:build` écrivait `docs-dist` **hors du +repo** (`--outDir ../docs-dist` résolu relativement au cwd du script npm — la racine du repo — +et non à `docs-sources` comme l'intention du script le suggérait), rendant tout déploiement +impossible ; corrigé en `--outDir docs-dist`. From 2ba1984669e6e9ee4dfcd422429e89e9af42ef24 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 20:32:19 +0200 Subject: [PATCH 06/10] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20chore(ci):=20monte?= =?UTF-8?q?=20les=20actions=20officielles=20=C3=A0=20leur=20derni=C3=A8re?= =?UTF-8?q?=20version=20majeure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le premier run réel sur TalkControl/talk-control (PR #36) montre des avertissements de dépréciation : checkout@v4/setup-node@v4 ciblent Node 20 (déprécié), forcés sur Node 24 par GitHub. Monte checkout v4→v7, setup-node v4→v6, cache v4→v6, configure-pages v5→v6, upload-pages-artifact v3→v5, deploy-pages v4→v5 (dernières versions majeures disponibles). --- .github/workflows/develop.yml | 38 +++++++++++++++++------------------ .github/workflows/release.yml | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 6f6e64cf..8257adfb 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -24,10 +24,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -46,10 +46,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -68,10 +68,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -92,10 +92,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -109,7 +109,7 @@ jobs: - name: Cache Playwright browsers id: playwright-cache - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.cache/ms-playwright key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }} @@ -133,10 +133,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -150,7 +150,7 @@ jobs: - name: Cache Playwright browsers id: playwright-cache - uses: actions/cache@v4 + uses: actions/cache@v6 with: path: ~/.cache/ms-playwright key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }} @@ -174,10 +174,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 5 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -220,10 +220,10 @@ jobs: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -235,13 +235,13 @@ jobs: run: npm run docs:build - name: Configure GitHub Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@v6 - name: Upload docs artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v5 with: path: docs-dist - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d95ed016..dc92d8fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,10 +17,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Setup Node 24 - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: '24' cache: 'npm' @@ -52,7 +52,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Extract CHANGELOG section for this tag id: changelog From 603cbd792cbb48574ed0562e262dbb93081e3733 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 20:34:28 +0200 Subject: [PATCH 07/10] =?UTF-8?q?=F0=9F=93=9D=20docs(improvements):=20r?= =?UTF-8?q?=C3=A9sultats=20de=20validation=20step-16-ci=20(run=20r=C3=A9el?= =?UTF-8?q?,=20blocage=20org,=20coverage=20gate)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documente le blocage allowed_actions=local_only découvert au niveau organisation TalkControl (aucune CI n'avait jamais pu tourner), les durées du premier run réel (PR #36), et la vérification en local que le coverage gate échoue réellement sur un seuil non tenu (test + revert immédiat). --- docs/improvements/step-16-ci.md | 76 +++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/docs/improvements/step-16-ci.md b/docs/improvements/step-16-ci.md index fb43a9f2..60db1e5d 100644 --- a/docs/improvements/step-16-ci.md +++ b/docs/improvements/step-16-ci.md @@ -73,3 +73,79 @@ Le `jsdoc:build` est aussi cassé (scanne des `.js` disparus) — à corriger ic - Le déploiement docs nécessite les bons `permissions` (`pages: write`, `id-token: write`) — le documenter. - Tester le workflow sur une PR de la branche elle-même (la CI se déclenche sur `develop`, donc la PR de cette étape valide directement les changements). + +## Résultats de validation (2026-07-13, branche `chore/step-16-ci`, PR #36) + +### Écart supplémentaire découvert (non listé dans le plan initial) + +Le repo `TalkControl/talk-control` (l'organisation finale — `origin` pointait sur le fork +`sfeir-open-source` en début de session, corrigé ici, `develop` poussé en fast-forward, 106 commits +jamais publiés jusqu'alors) a l'organisation entière configurée en `allowed_actions: local_only` : +**aucune Action GitHub officielle** (`actions/checkout`, `actions/setup-node`, etc.) ne pouvait +s'exécuter, sur aucun repo de l'organisation, avant cette étape — `startup_failure`, 0 job planifié, +confirmé identique avec l'ancien `develop.yml` (avant toute modification de cette étape) sur le +premier push de `develop`. Politique organisation changée par un Owner TalkControl vers « Allow +TalkControl, and select non-TalkControl, actions and reusable workflows » + « Allow actions created +by GitHub » — portée minimale (namespace `actions/*` uniquement, aucune action tierce Marketplace). +Documenté ici plutôt que dans decisions.md : c'est un blocage d'infra/organisation, pas une décision +d'architecture applicative. + +### Run CI réel observé + +Premier run réel obtenu après déblocage (PR #36, commit `9aa496a`) : **succès**, 7 jobs (6 + `docs-deploy` +correctement skippé — condition `push` sur `develop` uniquement, pas sur `pull_request`). Durées +individuelles (cache Playwright à froid, premier run avec cette clé) : + +| Job | Durée | +|---|---| +| Lint | 16s | +| TypeScript strict | 17s | +| Vite build | 20s | +| Server smoke test | 22s | +| Coverage (jsdom+browser+merge) | 1m6s | +| E2E Playwright | 1m9s | +| **Total run (parallèle, wall-clock)** | **1m9s** (borné par le plus long, E2E) | + +Avertissement de dépréciation Node 20 relevé sur ce run (`actions/checkout@v4`, `actions/setup-node@v4` +forcés sur Node 24) → actions montées à leur dernière version majeure dans un commit suivant +(`checkout` v4→v7, `setup-node` v4→v6, `cache` v4→v6, `configure-pages` v5→v6, +`upload-pages-artifact` v3→v5, `deploy-pages` v4→v5). + +### Cache Playwright (avant/après) + +- **1er run** (cache froid) : step « Install Playwright chromium (cold) » exécutée dans `coverage` et + `e2e` — téléchargement complet du binaire chromium. +- **2e run** (même clé de cache — lockfile inchangé) : `[coverage/e2e] cache hit` attendu → seule + l'étape « Install Playwright OS dependencies (cache hit) » (apt, léger) s'exécute, le téléchargement + du binaire est sauté. + + + +### Concurrency + +Un 2e commit poussé alors que le run précédent tournait encore (commit ``, run ``) — +vérifie que `cancel-in-progress: true` annule bien le run devenu obsolète. + + + +### Coverage gate + +Vérifié réellement bloquant **en local** (pas seulement en lecture du YAML) : seuil `lines` remonté +artificiellement de 80 à 99 dans `vitest.config.ts`, `npx vitest --mergeReports=... --coverage` +échoue avec `ERROR: Coverage for lines (94.43%) does not meet global threshold (99%)`, exit code 1. +Seuil réel (80/90/70/80, remonté à l'étape 15) restauré immédiatement après le test, jamais commité. + +### Validations locales + +``` +npx tsc --noEmit → 0 erreur +npm run lint → 0 erreur +NODE_ENV=test npm test → 392/392 +npm run test:components → 35/35 +npm run coverage → 93.02%/90.76%/86.57%/94.43% (stmt/branch/func/lines) vs seuils 80/90/70/80 +npm run build → OK +npm audit → 0 vulnérabilité +npm run test:e2e → 35/35 (échec initial dû à un process `serve` orphelin sur le port 3000, + sans lien avec les changements de cette étape — tué, tests relancés) +npm run docs:build → 179 pages Markdown générées (TypeDoc), doc API non vide +``` From f99c7506f0cc6bf9fc4fcd604a5b000beb3de42f Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 20:35:50 +0200 Subject: [PATCH 08/10] =?UTF-8?q?=F0=9F=93=9D=20docs(improvements):=20chif?= =?UTF-8?q?fres=20cache=20Playwright=20avant/apr=C3=A8s=20(run=20r=C3=A9el?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Confirme via l'API GitHub Actions que le 2e run (même clé de cache) skip bien le téléchargement chromium ("Install Playwright chromium (cold)" → skipped, "cache hit" → success), avec un gain mesuré (~7s sur coverage et e2e). --- docs/improvements/step-16-ci.md | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/docs/improvements/step-16-ci.md b/docs/improvements/step-16-ci.md index 60db1e5d..541483cb 100644 --- a/docs/improvements/step-16-ci.md +++ b/docs/improvements/step-16-ci.md @@ -113,20 +113,18 @@ forcés sur Node 24) → actions montées à leur dernière version majeure dans ### Cache Playwright (avant/après) -- **1er run** (cache froid) : step « Install Playwright chromium (cold) » exécutée dans `coverage` et - `e2e` — téléchargement complet du binaire chromium. -- **2e run** (même clé de cache — lockfile inchangé) : `[coverage/e2e] cache hit` attendu → seule - l'étape « Install Playwright OS dependencies (cache hit) » (apt, léger) s'exécute, le téléchargement - du binaire est sauté. - - +- **1er run** (`9aa496a`, cache froid) : step « Install Playwright chromium (cold) » exécutée dans + `coverage` et `e2e` — téléchargement complet du binaire chromium. `coverage` 1m6s, `e2e` 1m9s. +- **2e run** (`2ba1984`, même clé de cache — lockfile inchangé) : confirmé via l'API des steps — + « Install Playwright chromium (cold) » → `skipped`, « Install Playwright OS dependencies (cache + hit) » → `success`. Le téléchargement du binaire chromium est bien sauté. `coverage` 1m1s, `e2e` + 1m1s (vs 1m6s/1m9s à froid) — run total 1m2s vs 1m9s. ### Concurrency -Un 2e commit poussé alors que le run précédent tournait encore (commit ``, run ``) — -vérifie que `cancel-in-progress: true` annule bien le run devenu obsolète. - - +Commit `603cbd7` poussé alors que le run précédent (déclenché par `2ba1984`, `databaseId +29274995957`) était encore `in_progress` — vérifie que `cancel-in-progress: true` annule bien le run +devenu obsolète plutôt que de le laisser tourner en parallèle du nouveau. ### Coverage gate From a48ac6f97211a343f5553c3a5342ff1cc70160b4 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 20:36:20 +0200 Subject: [PATCH 09/10] =?UTF-8?q?=F0=9F=94=A7=20chore:=20trigger=20concurr?= =?UTF-8?q?ency=20test=20(2e=20commit=20pendant=20run=20en=20cours)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/improvements/step-16-ci.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/improvements/step-16-ci.md b/docs/improvements/step-16-ci.md index 541483cb..4d17c4c7 100644 --- a/docs/improvements/step-16-ci.md +++ b/docs/improvements/step-16-ci.md @@ -147,3 +147,4 @@ npm run test:e2e → 35/35 (échec initial dû à un process `serve` sans lien avec les changements de cette étape — tué, tests relancés) npm run docs:build → 179 pages Markdown générées (TypeDoc), doc API non vide ``` + From 074b9b6def407a420bd3bc75177ffa62a3b72d77 Mon Sep 17 00:00:00 2001 From: jefbinomed Date: Mon, 13 Jul 2026 20:38:51 +0200 Subject: [PATCH 10/10] =?UTF-8?q?=F0=9F=93=9D=20docs(improvements):=20?= =?UTF-8?q?=C3=A9tape=2016=20coch=C3=A9e,=20concurrency=20valid=C3=A9e=20e?= =?UTF-8?q?n=20conditions=20r=C3=A9elles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Confirme via l'API GitHub Actions que cancel-in-progress annule bien le run devenu obsolète (29275092170 → cancelled) au profit du plus récent (29275125106 → succès), déclenché par un 2e push pendant que le 1er tournait encore. Toutes les validations de l'étape 16 sont désormais faites en conditions réelles (run CI GitHub Actions), pas seulement en lecture de YAML. --- docs/improvements/README.md | 2 +- docs/improvements/step-16-ci.md | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/improvements/README.md b/docs/improvements/README.md index f883bb8f..eefc6b39 100644 --- a/docs/improvements/README.md +++ b/docs/improvements/README.md @@ -93,7 +93,7 @@ Garde-fous quel que soit le modèle : exécuter réellement les 6 commandes de v | Étape | Statut | Contenu | |---|---|---| | [15 — Gaps de tests](step-15-test-gaps.md) | ✅ | Modules non testés comblés (plugin.ts, tc-controller, touch-pointer, wrappers, server/bootstrap), helpers factorisés (`test/helpers/dom.ts`), seuils remontés (80/90/70/80), `changeSlide` mort supprimé (IMP-012), doc coverage régénérée | -| [16 — CI refonte](step-16-ci.md) | ⬜ | Lint bloquant, cache Playwright, dédup jobs (IMP-013), TypeDoc remplace jsdoc-to-markdown (IMP-014), déploiement docs GitHub Pages, release sur tag — en attente du run CI réel (blocage org débloqué, PR #36) | +| [16 — CI refonte](step-16-ci.md) | ✅ | Lint bloquant, cache Playwright, dédup jobs (IMP-013), TypeDoc remplace jsdoc-to-markdown (IMP-014), déploiement docs GitHub Pages, release sur tag — run CI réel validé (PR #36) | ### Phase F — Agentic diff --git a/docs/improvements/step-16-ci.md b/docs/improvements/step-16-ci.md index 4d17c4c7..3db05eb8 100644 --- a/docs/improvements/step-16-ci.md +++ b/docs/improvements/step-16-ci.md @@ -122,9 +122,14 @@ forcés sur Node 24) → actions montées à leur dernière version majeure dans ### Concurrency -Commit `603cbd7` poussé alors que le run précédent (déclenché par `2ba1984`, `databaseId -29274995957`) était encore `in_progress` — vérifie que `cancel-in-progress: true` annule bien le run -devenu obsolète plutôt que de le laisser tourner en parallèle du nouveau. +Commit `a48ac6f` poussé alors que le run précédent (déclenché par `f99c750`, run `29275092170`) +était encore `in_progress`. Résultat observé via l'API GitHub Actions : +- `29275092170` (run obsolète) → `status: completed`, `conclusion: cancelled`. +- `29275125106` (nouveau run) → passe de `pending` à `in_progress` dès l'annulation du précédent, + termine en succès. + +`cancel-in-progress: true` confirmé fonctionnel : le run devenu obsolète est bien annulé au profit +du plus récent, au lieu de tourner en parallèle et de gâcher des minutes CI. ### Coverage gate