@overcrow/mcp 0.0.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +91 -1
- package/dist/audit/index.js +103 -0
- package/dist/audit/lexer.js +417 -0
- package/dist/audit/project.js +200 -0
- package/dist/audit/rules.js +661 -0
- package/dist/bootstrap/download.js +229 -0
- package/dist/bootstrap/install.js +280 -0
- package/dist/bootstrap/pin.js +85 -0
- package/dist/bootstrap/pin.json +119 -0
- package/dist/bootstrap/zip.js +258 -0
- package/dist/cli.js +200 -0
- package/dist/confine.js +244 -0
- package/dist/content/docs/en/cli.md +768 -0
- package/dist/content/docs/en/creator-space.md +78 -0
- package/dist/content/docs/en/dev-channel.md +130 -0
- package/dist/content/docs/en/elements.md +469 -0
- package/dist/content/docs/en/forms.md +328 -0
- package/dist/content/docs/en/guide.md +252 -0
- package/dist/content/docs/en/index.md +85 -0
- package/dist/content/docs/en/limits.md +241 -0
- package/dist/content/docs/en/logic.md +446 -0
- package/dist/content/docs/en/manifest.md +388 -0
- package/dist/content/docs/en/mcp.md +165 -0
- package/dist/content/docs/en/package.md +131 -0
- package/dist/content/docs/en/publish-a-widget.md +94 -0
- package/dist/content/docs/en/publish-keys.md +95 -0
- package/dist/content/docs/en/publishing.md +167 -0
- package/dist/content/docs/en/reference.md +55 -0
- package/dist/content/docs/en/result-shapes.md +332 -0
- package/dist/content/docs/en/sdk.md +295 -0
- package/dist/content/docs/en/security.md +115 -0
- package/dist/content/docs/en/service-reference.md +344 -0
- package/dist/content/docs/en/services.md +517 -0
- package/dist/content/docs/en/style-properties.md +270 -0
- package/dist/content/docs/en/style.md +266 -0
- package/dist/content/docs/en/testing.md +400 -0
- package/dist/content/docs/en/verified-domain.md +46 -0
- package/dist/content/docs/en/view.md +338 -0
- package/dist/content/docs/en/widget-listing.md +65 -0
- package/dist/content/docs/en/widget-review.md +57 -0
- package/dist/content/docs/en/widget-statistics.md +134 -0
- package/dist/content/docs/en/widgets.md +76 -0
- package/dist/content/docs/fr/cli.md +802 -0
- package/dist/content/docs/fr/creator-space.md +83 -0
- package/dist/content/docs/fr/dev-channel.md +140 -0
- package/dist/content/docs/fr/elements.md +475 -0
- package/dist/content/docs/fr/forms.md +341 -0
- package/dist/content/docs/fr/guide.md +263 -0
- package/dist/content/docs/fr/index.md +90 -0
- package/dist/content/docs/fr/limits.md +244 -0
- package/dist/content/docs/fr/logic.md +461 -0
- package/dist/content/docs/fr/manifest.md +401 -0
- package/dist/content/docs/fr/mcp.md +173 -0
- package/dist/content/docs/fr/package.md +139 -0
- package/dist/content/docs/fr/publish-a-widget.md +101 -0
- package/dist/content/docs/fr/publish-keys.md +97 -0
- package/dist/content/docs/fr/publishing.md +177 -0
- package/dist/content/docs/fr/reference.md +59 -0
- package/dist/content/docs/fr/result-shapes.md +333 -0
- package/dist/content/docs/fr/sdk.md +301 -0
- package/dist/content/docs/fr/security.md +129 -0
- package/dist/content/docs/fr/service-reference.md +346 -0
- package/dist/content/docs/fr/services.md +540 -0
- package/dist/content/docs/fr/style-properties.md +272 -0
- package/dist/content/docs/fr/style.md +281 -0
- package/dist/content/docs/fr/testing.md +417 -0
- package/dist/content/docs/fr/verified-domain.md +49 -0
- package/dist/content/docs/fr/view.md +352 -0
- package/dist/content/docs/fr/widget-listing.md +69 -0
- package/dist/content/docs/fr/widget-review.md +59 -0
- package/dist/content/docs/fr/widget-statistics.md +141 -0
- package/dist/content/docs/fr/widgets.md +81 -0
- package/dist/content/examples/clock/LICENSE +21 -0
- package/dist/content/examples/clock/README.md +75 -0
- package/dist/content/examples/clock/listing.json +19 -0
- package/dist/content/examples/clock/locales/en.json +4 -0
- package/dist/content/examples/clock/locales/fr.json +4 -0
- package/dist/content/examples/clock/logic.ts +85 -0
- package/dist/content/examples/clock/manifest.json +44 -0
- package/dist/content/examples/clock/package.json +16 -0
- package/dist/content/examples/clock/style.ocss +26 -0
- package/dist/content/examples/clock/tests/hidden.scenario.json +68 -0
- package/dist/content/examples/clock/tests/load-logic.mjs +22 -0
- package/dist/content/examples/clock/tests/logic.test.mjs +89 -0
- package/dist/content/examples/clock/tests/options.scenario.json +108 -0
- package/dist/content/examples/clock/tests/preview.scenario.json +25 -0
- package/dist/content/examples/clock/tests/render.scenario.json +94 -0
- package/dist/content/examples/clock/tests/summer-time.scenario.json +74 -0
- package/dist/content/examples/clock/tests/ticks.scenario.json +120 -0
- package/dist/content/examples/clock/tsconfig.json +16 -0
- package/dist/content/examples/clock/view.ocml +8 -0
- package/dist/content/examples/countdown/LICENSE +20 -0
- package/dist/content/examples/countdown/listing.json +10 -0
- package/dist/content/examples/countdown/locales/en.json +15 -0
- package/dist/content/examples/countdown/locales/fr.json +15 -0
- package/dist/content/examples/countdown/logic.ts +179 -0
- package/dist/content/examples/countdown/manifest.json +34 -0
- package/dist/content/examples/countdown/package.json +15 -0
- package/dist/content/examples/countdown/style.ocss +94 -0
- package/dist/content/examples/countdown/tsconfig.json +16 -0
- package/dist/content/examples/countdown/view.ocml +42 -0
- package/dist/content/examples/fps/LICENSE +21 -0
- package/dist/content/examples/fps/README.md +64 -0
- package/dist/content/examples/fps/listing.json +19 -0
- package/dist/content/examples/fps/locales/en.json +11 -0
- package/dist/content/examples/fps/locales/fr.json +11 -0
- package/dist/content/examples/fps/logic.ts +64 -0
- package/dist/content/examples/fps/manifest.json +30 -0
- package/dist/content/examples/fps/package.json +16 -0
- package/dist/content/examples/fps/style.ocss +31 -0
- package/dist/content/examples/fps/submission.json +8 -0
- package/dist/content/examples/fps/tests/label.scenario.json +63 -0
- package/dist/content/examples/fps/tests/load-logic.mjs +22 -0
- package/dist/content/examples/fps/tests/logic.test.mjs +60 -0
- package/dist/content/examples/fps/tests/preview.scenario.json +29 -0
- package/dist/content/examples/fps/tests/refused.scenario.json +20 -0
- package/dist/content/examples/fps/tests/render.scenario.json +96 -0
- package/dist/content/examples/fps/tests/stale.scenario.json +91 -0
- package/dist/content/examples/fps/tests/unavailable.scenario.json +111 -0
- package/dist/content/examples/fps/tsconfig.json +16 -0
- package/dist/content/examples/fps/view.ocml +11 -0
- package/dist/content/examples/media/LICENSE +21 -0
- package/dist/content/examples/media/README.md +147 -0
- package/dist/content/examples/media/listing.json +19 -0
- package/dist/content/examples/media/locales/en.json +11 -0
- package/dist/content/examples/media/locales/fr.json +11 -0
- package/dist/content/examples/media/logic.ts +191 -0
- package/dist/content/examples/media/manifest.json +35 -0
- package/dist/content/examples/media/package.json +16 -0
- package/dist/content/examples/media/style.ocss +148 -0
- package/dist/content/examples/media/submission.json +12 -0
- package/dist/content/examples/media/tests/covers.scenario.json +144 -0
- package/dist/content/examples/media/tests/gesture.scenario.json +173 -0
- package/dist/content/examples/media/tests/load-logic.mjs +22 -0
- package/dist/content/examples/media/tests/logic.test.mjs +176 -0
- package/dist/content/examples/media/tests/marquee.scenario.json +127 -0
- package/dist/content/examples/media/tests/preview.scenario.json +52 -0
- package/dist/content/examples/media/tests/read-only.scenario.json +53 -0
- package/dist/content/examples/media/tests/refused.scenario.json +22 -0
- package/dist/content/examples/media/tests/refused.test.mjs +31 -0
- package/dist/content/examples/media/tests/render.scenario.json +136 -0
- package/dist/content/examples/media/tests/states.scenario.json +257 -0
- package/dist/content/examples/media/tests/unavailable.scenario.json +120 -0
- package/dist/content/examples/media/tsconfig.json +16 -0
- package/dist/content/examples/media/view.ocml +41 -0
- package/dist/content/examples/notes/LICENSE +21 -0
- package/dist/content/examples/notes/README.md +219 -0
- package/dist/content/examples/notes/listing.json +19 -0
- package/dist/content/examples/notes/locales/en.json +25 -0
- package/dist/content/examples/notes/locales/fr.json +25 -0
- package/dist/content/examples/notes/logic.ts +799 -0
- package/dist/content/examples/notes/manifest.json +40 -0
- package/dist/content/examples/notes/package.json +16 -0
- package/dist/content/examples/notes/style.ocss +469 -0
- package/dist/content/examples/notes/submission.json +12 -0
- package/dist/content/examples/notes/tests/checks.scenario.json +237 -0
- package/dist/content/examples/notes/tests/create.scenario.json +260 -0
- package/dist/content/examples/notes/tests/delete.scenario.json +342 -0
- package/dist/content/examples/notes/tests/drafts.scenario.json +714 -0
- package/dist/content/examples/notes/tests/editor.scenario.json +232 -0
- package/dist/content/examples/notes/tests/frame.scenario.json +93 -0
- package/dist/content/examples/notes/tests/interactive.scenario.json +344 -0
- package/dist/content/examples/notes/tests/limits.scenario.json +1351 -0
- package/dist/content/examples/notes/tests/load-logic.mjs +22 -0
- package/dist/content/examples/notes/tests/logic.test.mjs +514 -0
- package/dist/content/examples/notes/tests/preview.scenario.json +99 -0
- package/dist/content/examples/notes/tests/read-only.scenario.json +105 -0
- package/dist/content/examples/notes/tests/refused.scenario.json +33 -0
- package/dist/content/examples/notes/tests/save.scenario.json +378 -0
- package/dist/content/examples/notes/tests/states.scenario.json +640 -0
- package/dist/content/examples/notes/tests/typing.scenario.json +562 -0
- package/dist/content/examples/notes/tests/unavailable.scenario.json +246 -0
- package/dist/content/examples/notes/tsconfig.json +16 -0
- package/dist/content/examples/notes/view.ocml +154 -0
- package/dist/content/examples/performance/LICENSE +21 -0
- package/dist/content/examples/performance/README.md +134 -0
- package/dist/content/examples/performance/listing.json +19 -0
- package/dist/content/examples/performance/locales/en.json +20 -0
- package/dist/content/examples/performance/locales/fr.json +20 -0
- package/dist/content/examples/performance/logic.ts +210 -0
- package/dist/content/examples/performance/manifest.json +83 -0
- package/dist/content/examples/performance/package.json +16 -0
- package/dist/content/examples/performance/style.ocss +75 -0
- package/dist/content/examples/performance/submission.json +12 -0
- package/dist/content/examples/performance/tests/fahrenheit.scenario.json +110 -0
- package/dist/content/examples/performance/tests/horizontal.scenario.json +96 -0
- package/dist/content/examples/performance/tests/load-logic.mjs +22 -0
- package/dist/content/examples/performance/tests/logic.test.mjs +226 -0
- package/dist/content/examples/performance/tests/menu.scenario.json +170 -0
- package/dist/content/examples/performance/tests/no-fps-source.scenario.json +47 -0
- package/dist/content/examples/performance/tests/preview.scenario.json +45 -0
- package/dist/content/examples/performance/tests/refused.scenario.json +20 -0
- package/dist/content/examples/performance/tests/refused.test.mjs +19 -0
- package/dist/content/examples/performance/tests/region.scenario.json +89 -0
- package/dist/content/examples/performance/tests/render.scenario.json +112 -0
- package/dist/content/examples/performance/tests/sources.scenario.json +151 -0
- package/dist/content/examples/performance/tests/stale.scenario.json +111 -0
- package/dist/content/examples/performance/tests/telemetry-only.scenario.json +44 -0
- package/dist/content/examples/performance/tests/thresholds.scenario.json +147 -0
- package/dist/content/examples/performance/tests/waiting.scenario.json +105 -0
- package/dist/content/examples/performance/tsconfig.json +16 -0
- package/dist/content/examples/performance/view.ocml +18 -0
- package/dist/content/examples/playervox-journal/LICENSE +21 -0
- package/dist/content/examples/playervox-journal/README.md +150 -0
- package/dist/content/examples/playervox-journal/listing.json +19 -0
- package/dist/content/examples/playervox-journal/locales/en.json +25 -0
- package/dist/content/examples/playervox-journal/locales/fr.json +25 -0
- package/dist/content/examples/playervox-journal/logic.ts +556 -0
- package/dist/content/examples/playervox-journal/manifest.json +19 -0
- package/dist/content/examples/playervox-journal/package.json +16 -0
- package/dist/content/examples/playervox-journal/style.ocss +142 -0
- package/dist/content/examples/playervox-journal/submission.json +12 -0
- package/dist/content/examples/playervox-journal/tests/changes.scenario.json +482 -0
- package/dist/content/examples/playervox-journal/tests/delete.scenario.json +432 -0
- package/dist/content/examples/playervox-journal/tests/frame.scenario.json +169 -0
- package/dist/content/examples/playervox-journal/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-journal/tests/logic.test.mjs +349 -0
- package/dist/content/examples/playervox-journal/tests/paging.scenario.json +428 -0
- package/dist/content/examples/playervox-journal/tests/preview.scenario.json +184 -0
- package/dist/content/examples/playervox-journal/tests/read-only.scenario.json +157 -0
- package/dist/content/examples/playervox-journal/tests/refused.scenario.json +39 -0
- package/dist/content/examples/playervox-journal/tests/scale.scenario.json +286 -0
- package/dist/content/examples/playervox-journal/tests/signed-out.scenario.json +134 -0
- package/dist/content/examples/playervox-journal/tests/states.scenario.json +741 -0
- package/dist/content/examples/playervox-journal/tests/unavailable.scenario.json +183 -0
- package/dist/content/examples/playervox-journal/tsconfig.json +16 -0
- package/dist/content/examples/playervox-journal/view.ocml +52 -0
- package/dist/content/examples/playervox-rating/LICENSE +21 -0
- package/dist/content/examples/playervox-rating/README.md +166 -0
- package/dist/content/examples/playervox-rating/listing.json +19 -0
- package/dist/content/examples/playervox-rating/locales/en.json +35 -0
- package/dist/content/examples/playervox-rating/locales/fr.json +35 -0
- package/dist/content/examples/playervox-rating/logic.ts +581 -0
- package/dist/content/examples/playervox-rating/manifest.json +19 -0
- package/dist/content/examples/playervox-rating/package.json +16 -0
- package/dist/content/examples/playervox-rating/style.ocss +333 -0
- package/dist/content/examples/playervox-rating/submission.json +12 -0
- package/dist/content/examples/playervox-rating/tests/account.scenario.json +125 -0
- package/dist/content/examples/playervox-rating/tests/bounds.scenario.json +73 -0
- package/dist/content/examples/playervox-rating/tests/draft.scenario.json +199 -0
- package/dist/content/examples/playervox-rating/tests/form.scenario.json +142 -0
- package/dist/content/examples/playervox-rating/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-rating/tests/logic.test.mjs +346 -0
- package/dist/content/examples/playervox-rating/tests/offline.scenario.json +142 -0
- package/dist/content/examples/playervox-rating/tests/preview.scenario.json +44 -0
- package/dist/content/examples/playervox-rating/tests/publish-keyboard.scenario.json +221 -0
- package/dist/content/examples/playervox-rating/tests/publish-pointer.scenario.json +314 -0
- package/dist/content/examples/playervox-rating/tests/read-only.scenario.json +70 -0
- package/dist/content/examples/playervox-rating/tests/refused.scenario.json +45 -0
- package/dist/content/examples/playervox-rating/tests/states.scenario.json +362 -0
- package/dist/content/examples/playervox-rating/tsconfig.json +16 -0
- package/dist/content/examples/playervox-rating/view.ocml +62 -0
- package/dist/content/examples/playervox-reviews/LICENSE +21 -0
- package/dist/content/examples/playervox-reviews/README.md +194 -0
- package/dist/content/examples/playervox-reviews/listing.json +19 -0
- package/dist/content/examples/playervox-reviews/locales/en.json +32 -0
- package/dist/content/examples/playervox-reviews/locales/fr.json +32 -0
- package/dist/content/examples/playervox-reviews/logic.ts +822 -0
- package/dist/content/examples/playervox-reviews/manifest.json +30 -0
- package/dist/content/examples/playervox-reviews/package.json +16 -0
- package/dist/content/examples/playervox-reviews/style.ocss +260 -0
- package/dist/content/examples/playervox-reviews/submission.json +8 -0
- package/dist/content/examples/playervox-reviews/tests/account.scenario.json +249 -0
- package/dist/content/examples/playervox-reviews/tests/bounds.scenario.json +336 -0
- package/dist/content/examples/playervox-reviews/tests/changes.scenario.json +515 -0
- package/dist/content/examples/playervox-reviews/tests/filter.scenario.json +400 -0
- package/dist/content/examples/playervox-reviews/tests/frame.scenario.json +185 -0
- package/dist/content/examples/playervox-reviews/tests/keyboard.scenario.json +188 -0
- package/dist/content/examples/playervox-reviews/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-reviews/tests/logic.test.mjs +559 -0
- package/dist/content/examples/playervox-reviews/tests/offline-start.scenario.json +152 -0
- package/dist/content/examples/playervox-reviews/tests/offline.scenario.json +311 -0
- package/dist/content/examples/playervox-reviews/tests/paging.scenario.json +497 -0
- package/dist/content/examples/playervox-reviews/tests/preview.scenario.json +286 -0
- package/dist/content/examples/playervox-reviews/tests/reading.scenario.json +591 -0
- package/dist/content/examples/playervox-reviews/tests/refused.scenario.json +54 -0
- package/dist/content/examples/playervox-reviews/tests/scale.scenario.json +303 -0
- package/dist/content/examples/playervox-reviews/tests/states.scenario.json +700 -0
- package/dist/content/examples/playervox-reviews/tests/unavailable.scenario.json +192 -0
- package/dist/content/examples/playervox-reviews/tsconfig.json +16 -0
- package/dist/content/examples/playervox-reviews/view.ocml +110 -0
- package/dist/content/examples/playervox-score/LICENSE +21 -0
- package/dist/content/examples/playervox-score/README.md +131 -0
- package/dist/content/examples/playervox-score/listing.json +19 -0
- package/dist/content/examples/playervox-score/locales/en.json +23 -0
- package/dist/content/examples/playervox-score/locales/fr.json +23 -0
- package/dist/content/examples/playervox-score/logic.ts +430 -0
- package/dist/content/examples/playervox-score/manifest.json +47 -0
- package/dist/content/examples/playervox-score/package.json +16 -0
- package/dist/content/examples/playervox-score/style.ocss +247 -0
- package/dist/content/examples/playervox-score/submission.json +8 -0
- package/dist/content/examples/playervox-score/tests/grades.scenario.json +279 -0
- package/dist/content/examples/playervox-score/tests/load-logic.mjs +22 -0
- package/dist/content/examples/playervox-score/tests/logic.test.mjs +229 -0
- package/dist/content/examples/playervox-score/tests/options.scenario.json +302 -0
- package/dist/content/examples/playervox-score/tests/preview.scenario.json +68 -0
- package/dist/content/examples/playervox-score/tests/pulse.scenario.json +157 -0
- package/dist/content/examples/playervox-score/tests/refused.scenario.json +21 -0
- package/dist/content/examples/playervox-score/tests/signed-out.scenario.json +46 -0
- package/dist/content/examples/playervox-score/tests/states.scenario.json +450 -0
- package/dist/content/examples/playervox-score/tests/unavailable.scenario.json +84 -0
- package/dist/content/examples/playervox-score/tsconfig.json +16 -0
- package/dist/content/examples/playervox-score/view.ocml +51 -0
- package/dist/content/examples/session/LICENSE +21 -0
- package/dist/content/examples/session/README.md +57 -0
- package/dist/content/examples/session/listing.json +19 -0
- package/dist/content/examples/session/locales/en.json +3 -0
- package/dist/content/examples/session/locales/fr.json +3 -0
- package/dist/content/examples/session/logic.ts +26 -0
- package/dist/content/examples/session/manifest.json +19 -0
- package/dist/content/examples/session/package.json +16 -0
- package/dist/content/examples/session/style.ocss +16 -0
- package/dist/content/examples/session/submission.json +8 -0
- package/dist/content/examples/session/tests/hidden.scenario.json +45 -0
- package/dist/content/examples/session/tests/load-logic.mjs +22 -0
- package/dist/content/examples/session/tests/logic.test.mjs +37 -0
- package/dist/content/examples/session/tests/preview.scenario.json +28 -0
- package/dist/content/examples/session/tests/refused.scenario.json +20 -0
- package/dist/content/examples/session/tests/refused.test.mjs +16 -0
- package/dist/content/examples/session/tests/render.scenario.json +95 -0
- package/dist/content/examples/session/tests/ticks.scenario.json +139 -0
- package/dist/content/examples/session/tests/unknown.scenario.json +37 -0
- package/dist/content/examples/session/tsconfig.json +16 -0
- package/dist/content/examples/session/view.ocml +11 -0
- package/dist/content/examples/stopwatch/LICENSE +21 -0
- package/dist/content/examples/stopwatch/README.md +99 -0
- package/dist/content/examples/stopwatch/listing.json +19 -0
- package/dist/content/examples/stopwatch/locales/en.json +8 -0
- package/dist/content/examples/stopwatch/locales/fr.json +8 -0
- package/dist/content/examples/stopwatch/logic.ts +93 -0
- package/dist/content/examples/stopwatch/manifest.json +19 -0
- package/dist/content/examples/stopwatch/package.json +16 -0
- package/dist/content/examples/stopwatch/style.ocss +54 -0
- package/dist/content/examples/stopwatch/submission.json +12 -0
- package/dist/content/examples/stopwatch/tests/errors.scenario.json +121 -0
- package/dist/content/examples/stopwatch/tests/gesture.scenario.json +154 -0
- package/dist/content/examples/stopwatch/tests/hidden.scenario.json +57 -0
- package/dist/content/examples/stopwatch/tests/hundredths.scenario.json +173 -0
- package/dist/content/examples/stopwatch/tests/load-logic.mjs +22 -0
- package/dist/content/examples/stopwatch/tests/logic.test.mjs +99 -0
- package/dist/content/examples/stopwatch/tests/preview.scenario.json +36 -0
- package/dist/content/examples/stopwatch/tests/read-only.scenario.json +42 -0
- package/dist/content/examples/stopwatch/tests/read-only.test.mjs +18 -0
- package/dist/content/examples/stopwatch/tests/refused.scenario.json +22 -0
- package/dist/content/examples/stopwatch/tests/refused.test.mjs +18 -0
- package/dist/content/examples/stopwatch/tests/render.scenario.json +105 -0
- package/dist/content/examples/stopwatch/tests/states.scenario.json +246 -0
- package/dist/content/examples/stopwatch/tests/unknown.scenario.json +40 -0
- package/dist/content/examples/stopwatch/tsconfig.json +16 -0
- package/dist/content/examples/stopwatch/view.ocml +29 -0
- package/dist/content/examples/twitch-chat/LICENSE +21 -0
- package/dist/content/examples/twitch-chat/README.md +283 -0
- package/dist/content/examples/twitch-chat/listing.json +19 -0
- package/dist/content/examples/twitch-chat/locales/en.json +52 -0
- package/dist/content/examples/twitch-chat/locales/fr.json +52 -0
- package/dist/content/examples/twitch-chat/logic.ts +887 -0
- package/dist/content/examples/twitch-chat/manifest.json +33 -0
- package/dist/content/examples/twitch-chat/package.json +16 -0
- package/dist/content/examples/twitch-chat/style.ocss +544 -0
- package/dist/content/examples/twitch-chat/submission.json +12 -0
- package/dist/content/examples/twitch-chat/tests/account.scenario.json +325 -0
- package/dist/content/examples/twitch-chat/tests/burst.scenario.json +1866 -0
- package/dist/content/examples/twitch-chat/tests/channel-refused.scenario.json +372 -0
- package/dist/content/examples/twitch-chat/tests/channel.scenario.json +480 -0
- package/dist/content/examples/twitch-chat/tests/draft.scenario.json +279 -0
- package/dist/content/examples/twitch-chat/tests/fade.scenario.json +269 -0
- package/dist/content/examples/twitch-chat/tests/failures.scenario.json +420 -0
- package/dist/content/examples/twitch-chat/tests/favorites.scenario.json +376 -0
- package/dist/content/examples/twitch-chat/tests/frame.scenario.json +152 -0
- package/dist/content/examples/twitch-chat/tests/lifetime.scenario.json +186 -0
- package/dist/content/examples/twitch-chat/tests/load-logic.mjs +22 -0
- package/dist/content/examples/twitch-chat/tests/logic.test.mjs +1053 -0
- package/dist/content/examples/twitch-chat/tests/passive.scenario.json +536 -0
- package/dist/content/examples/twitch-chat/tests/preview.scenario.json +147 -0
- package/dist/content/examples/twitch-chat/tests/read-only.scenario.json +202 -0
- package/dist/content/examples/twitch-chat/tests/read-only.test.mjs +63 -0
- package/dist/content/examples/twitch-chat/tests/refused.scenario.json +65 -0
- package/dist/content/examples/twitch-chat/tests/refused.test.mjs +43 -0
- package/dist/content/examples/twitch-chat/tests/render.scenario.json +347 -0
- package/dist/content/examples/twitch-chat/tests/reply.scenario.json +384 -0
- package/dist/content/examples/twitch-chat/tests/send-refused.scenario.json +383 -0
- package/dist/content/examples/twitch-chat/tests/send.scenario.json +300 -0
- package/dist/content/examples/twitch-chat/tests/states.scenario.json +455 -0
- package/dist/content/examples/twitch-chat/tests/unavailable.scenario.json +256 -0
- package/dist/content/examples/twitch-chat/tests/unread.scenario.json +997 -0
- package/dist/content/examples/twitch-chat/tsconfig.json +16 -0
- package/dist/content/examples/twitch-chat/view.ocml +141 -0
- package/dist/content/examples/warframe-market/LICENSE +21 -0
- package/dist/content/examples/warframe-market/README.md +176 -0
- package/dist/content/examples/warframe-market/listing.json +19 -0
- package/dist/content/examples/warframe-market/locales/en.json +44 -0
- package/dist/content/examples/warframe-market/locales/fr.json +44 -0
- package/dist/content/examples/warframe-market/logic.ts +1265 -0
- package/dist/content/examples/warframe-market/manifest.json +92 -0
- package/dist/content/examples/warframe-market/package.json +16 -0
- package/dist/content/examples/warframe-market/style.ocss +422 -0
- package/dist/content/examples/warframe-market/submission.json +24 -0
- package/dist/content/examples/warframe-market/tests/bounds.scenario.json +60 -0
- package/dist/content/examples/warframe-market/tests/cached.scenario.json +70 -0
- package/dist/content/examples/warframe-market/tests/detail.scenario.json +251 -0
- package/dist/content/examples/warframe-market/tests/errors.scenario.json +105 -0
- package/dist/content/examples/warframe-market/tests/fixtures.json +295 -0
- package/dist/content/examples/warframe-market/tests/load-logic.mjs +22 -0
- package/dist/content/examples/warframe-market/tests/logic.test.mjs +505 -0
- package/dist/content/examples/warframe-market/tests/no-clipboard.scenario.json +104 -0
- package/dist/content/examples/warframe-market/tests/passive.scenario.json +87 -0
- package/dist/content/examples/warframe-market/tests/preview.scenario.json +146 -0
- package/dist/content/examples/warframe-market/tests/refresh.scenario.json +56 -0
- package/dist/content/examples/warframe-market/tests/refused.scenario.json +74 -0
- package/dist/content/examples/warframe-market/tests/render.scenario.json +210 -0
- package/dist/content/examples/warframe-market/tests/search.scenario.json +189 -0
- package/dist/content/examples/warframe-market/tests/unavailable.scenario.json +54 -0
- package/dist/content/examples/warframe-market/tsconfig.json +16 -0
- package/dist/content/examples/warframe-market/view.ocml +116 -0
- package/dist/content/examples/weather/LICENSE +20 -0
- package/dist/content/examples/weather/listing.json +10 -0
- package/dist/content/examples/weather/locales/en.json +9 -0
- package/dist/content/examples/weather/locales/fr.json +9 -0
- package/dist/content/examples/weather/logic.ts +62 -0
- package/dist/content/examples/weather/manifest.json +51 -0
- package/dist/content/examples/weather/package.json +15 -0
- package/dist/content/examples/weather/style.ocss +29 -0
- package/dist/content/examples/weather/submission.json +17 -0
- package/dist/content/examples/weather/tsconfig.json +16 -0
- package/dist/content/examples/weather/view.ocml +12 -0
- package/dist/content/index.json +3705 -0
- package/dist/content/reference/errors.json +1924 -0
- package/dist/content/reference/limits.json +1154 -0
- package/dist/content/reference/manifest.md +223 -0
- package/dist/content/reference/permissions.json +413 -0
- package/dist/content/templates/blank/locales/en.json +3 -0
- package/dist/content/templates/blank/locales/fr.json +3 -0
- package/dist/content/templates/blank/logic.ts +7 -0
- package/dist/content/templates/blank/manifest.json +16 -0
- package/dist/content/templates/blank/style.ocss +10 -0
- package/dist/content/templates/blank/tests/example.scenario.json +10 -0
- package/dist/content/templates/blank/view.ocml +6 -0
- package/dist/content/templates/chart/locales/en.json +3 -0
- package/dist/content/templates/chart/locales/fr.json +3 -0
- package/dist/content/templates/chart/logic.ts +27 -0
- package/dist/content/templates/chart/manifest.json +16 -0
- package/dist/content/templates/chart/style.ocss +27 -0
- package/dist/content/templates/chart/tests/example.scenario.json +10 -0
- package/dist/content/templates/chart/view.ocml +10 -0
- package/dist/content/templates/counter/locales/en.json +4 -0
- package/dist/content/templates/counter/locales/fr.json +4 -0
- package/dist/content/templates/counter/logic.ts +20 -0
- package/dist/content/templates/counter/manifest.json +16 -0
- package/dist/content/templates/counter/style.ocss +26 -0
- package/dist/content/templates/counter/tests/example.scenario.json +11 -0
- package/dist/content/templates/counter/view.ocml +13 -0
- package/dist/content/templates/list/locales/en.json +8 -0
- package/dist/content/templates/list/locales/fr.json +8 -0
- package/dist/content/templates/list/logic.ts +35 -0
- package/dist/content/templates/list/manifest.json +16 -0
- package/dist/content/templates/list/style.ocss +42 -0
- package/dist/content/templates/list/tests/example.scenario.json +10 -0
- package/dist/content/templates/list/view.ocml +17 -0
- package/dist/content/templates/shared/LICENSE +20 -0
- package/dist/content/templates/shared/package.json +14 -0
- package/dist/content/templates/shared/tsconfig.json +16 -0
- package/dist/content.js +68 -0
- package/dist/env.js +156 -0
- package/dist/fingerprint.js +32 -0
- package/dist/hidden.js +47 -0
- package/dist/ids.js +27 -0
- package/dist/index.js +82 -0
- package/dist/knowledge.js +222 -0
- package/dist/npm.js +149 -0
- package/dist/prompts.js +47 -0
- package/dist/resources.js +82 -0
- package/dist/run.js +120 -0
- package/dist/server.js +43 -0
- package/dist/session.js +205 -0
- package/dist/sources.js +218 -0
- package/dist/text.js +80 -0
- package/dist/texts.js +44 -0
- package/dist/tools/audit.js +105 -0
- package/dist/tools/build.js +453 -0
- package/dist/tools/common.js +122 -0
- package/dist/tools/docs.js +196 -0
- package/dist/tools/preview.js +87 -0
- package/dist/tools/project.js +183 -0
- package/dist/tools/setup.js +146 -0
- package/dist/tools/submission.js +369 -0
- package/dist/version.js +3 -0
- package/npm-shrinkwrap.json +402 -0
- package/package.json +50 -4
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Widgets de référence
|
|
2
|
+
|
|
3
|
+
Les widgets intégrés de PlayerVox OverCrow sont des widgets ordinaires,
|
|
4
|
+
écrits avec le SDK public, empaquetés par `overcrow-widget` et publiés dans
|
|
5
|
+
le catalogue signé comme les vôtres. Leurs sources se trouvent dans
|
|
6
|
+
[`widgets/`](../../../widgets/), dans le dépôt public, sous licence MIT :
|
|
7
|
+
lisez-les, copiez-les et servez-vous-en comme point de départ.
|
|
8
|
+
|
|
9
|
+
<!-- generated:widgets -->
|
|
10
|
+
| Widget | Description | ID | Permissions | Sources |
|
|
11
|
+
| --- | --- | --- | --- | --- |
|
|
12
|
+
| **Horloge** | Affiche l’heure locale et, en option, la date, au format 24 heures. | `com.playervox.overcrow.clock` | aucune | [widgets/clock/](../../../widgets/clock/) |
|
|
13
|
+
| **FPS** | Affiche la fréquence d’images présentée par le jeu, quand l’hôte dispose d’une source. | `com.playervox.overcrow.fps` | `fps.read` | [widgets/fps/](../../../widgets/fps/) |
|
|
14
|
+
| **Média** | Le morceau que joue votre lecteur de musique, avec sa pochette, et les boutons précédent, lecture/pause et suivant en mode interactif. | `com.playervox.overcrow.media` | `media.read`, `media.control` | [widgets/media/](../../../widgets/media/) |
|
|
15
|
+
| **Notes** | Vos notes et listes de tâches par-dessus le jeu : jusqu’à huit notes, chacune avec un texte libre et une liste de tâches, les mêmes pour tous les jeux. Lisez-les en mode passif ; en mode interactif, choisissez, créez, supprimez et modifiez-les dans le widget, et cochez les éléments. Elles restent sur cet ordinateur. | `com.playervox.overcrow.notes` | `notes.read`, `notes.write` | [widgets/notes/](../../../widgets/notes/) |
|
|
16
|
+
| **Performances** | CPU et mémoire du jeu, et les températures que cet ordinateur expose. | `com.playervox.overcrow.performance` | `telemetry.read`, `fps.read` | [widgets/performance/](../../../widgets/performance/) |
|
|
17
|
+
| **Journal de sessions** | Les sessions de jeu terminées de votre jeu, de la plus récente à la plus ancienne : date, heure de début et durée, cinq par page. Enregistrées sur votre appareil sans compte, fusionnées avec votre journal PlayerVox si vous synchronisez. Supprimez une session après confirmation. | `com.playervox.overcrow.playervox.journal` | `journal.read`, `journal.delete` | [widgets/playervox-journal/](../../../widgets/playervox-journal/) |
|
|
18
|
+
| **Ma note** | Votre note PlayerVox du jeu Steam auquel vous jouez : son grade et son score, et en mode interactif trois critères et un avis facultatif à publier ou mettre à jour. Nécessite votre compte PlayerVox. | `com.playervox.overcrow.playervox.rating` | `playervox.rating.read`, `playervox.rating.write` | [widgets/playervox-rating/](../../../widgets/playervox-rating/) |
|
|
19
|
+
| **Avis des joueurs** | Ce que les joueurs de PlayerVox pensent du jeu auquel vous jouez : trois avis par page avec la note et le score de chaque joueur, dans votre langue quand une traduction existe. Limitez-les aux joueurs que vous suivez depuis le menu du widget. Nécessite votre compte PlayerVox. | `com.playervox.overcrow.playervox.reviews` | `playervox.reviews.read` | [widgets/playervox-reviews/](../../../widgets/playervox-reviews/) |
|
|
20
|
+
| **Note PlayerVox** | La note de la communauté PlayerVox pour votre jeu Steam, avec son score, son nombre de votes et trois critères. Sans compte ; le badge reste toujours visible. | `com.playervox.overcrow.playervox.score` | `playervox.score.read` | [widgets/playervox-score/](../../../widgets/playervox-score/) |
|
|
21
|
+
| **Session** | Affiche la durée de la session de jeu en cours. | `com.playervox.overcrow.session` | `session.read` | [widgets/session/](../../../widgets/session/) |
|
|
22
|
+
| **Chronomètre** | Un chronomètre au centième de seconde, démarré, mis en pause et réinitialisé par ses boutons ou les raccourcis de l’hôte. | `com.playervox.overcrow.stopwatch` | `stopwatch.read`, `stopwatch.control` | [widgets/stopwatch/](../../../widgets/stopwatch/) |
|
|
23
|
+
| **Chat Twitch** | Lisez et envoyez des messages dans le chat Twitch public de votre choix : vos chaînes favorites, l’historique défilant avec emotes et réponses en mode interactif, les derniers messages qui s’effacent en mode passif. Nécessite votre compte Twitch. | `com.playervox.overcrow.twitch.chat` | `twitch.chat.read`, `twitch.chat.compose` | [widgets/twitch-chat/](../../../widgets/twitch-chat/) |
|
|
24
|
+
| **Marché Warframe** | Recherche les objets PC publics dans un catalogue en cache, affiche les vendeurs et acheteurs en ligne d’un objet dans deux onglets et copie un message d’échange sur un clic. | `com.playervox.overcrow.warframe.market` | `network`, `storage`, `clipboardWrite` | [widgets/warframe-market/](../../../widgets/warframe-market/) |
|
|
25
|
+
<!-- /generated:widgets -->
|
|
26
|
+
|
|
27
|
+
## Ce que contient le dossier d’un widget
|
|
28
|
+
|
|
29
|
+
- les sources du paquet : `manifest.json`, `view.ocml`, `style.ocss`,
|
|
30
|
+
`logic.ts`, `locales/`, `LICENSE` ;
|
|
31
|
+
- `listing.json`, son texte pour la marketplace ;
|
|
32
|
+
- `assets/preview.png`, son aperçu dans la marketplace : l’image de son
|
|
33
|
+
scénario `preview`, cadrée et mise en scène par
|
|
34
|
+
`node scripts/compose-previews.mjs` ;
|
|
35
|
+
- `tests/` : les tests unitaires de la logique, et des scénarios avec leurs
|
|
36
|
+
images de référence dans les deux thèmes, les deux langues et deux
|
|
37
|
+
échelles, joués par `overcrow-widget test` dans le runtime headless
|
|
38
|
+
d’OverCrow ;
|
|
39
|
+
- `README.md` : ce qu’il affiche, son menu, ses permissions, son
|
|
40
|
+
fonctionnement et son coût.
|
|
41
|
+
|
|
42
|
+
## Ce que chacun montre
|
|
43
|
+
|
|
44
|
+
| Pour voir comment… | Lisez |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| se déclencher à chaque minute ou seconde de l’heure locale, suivre une option du menu | Horloge |
|
|
47
|
+
| s’abonner à un service et afficher une valeur manquante | FPS, Session |
|
|
48
|
+
| disposer une liste de valeurs en grille, masquer une ligne du menu que la machine ne peut pas alimenter | Performances |
|
|
49
|
+
| afficher une image fournie par OverCrow, relancer un abonnement qui s’est terminé | Média |
|
|
50
|
+
| commander un service sur une action de l’utilisateur, laisser OverCrow faire avancer une durée | Chronomètre |
|
|
51
|
+
| modifier du texte avec un formulaire lié à un intent d’écriture, conserver des brouillons | Notes, Ma note |
|
|
52
|
+
| dessiner sur un canvas | Note PlayerVox, Ma note |
|
|
53
|
+
| parcourir un service page par page et réagir à une révision | Avis des joueurs, Journal de sessions |
|
|
54
|
+
| maintenir une longue liste défilante sur sa fin, envoyer un message | Chat Twitch |
|
|
55
|
+
| appeler une API HTTP, la mettre en cache dans le stockage, copier dans le presse-papiers | Marché Warframe |
|
|
56
|
+
|
|
57
|
+
Marché Warframe n’est pas un widget intégré : widget PlayerVox du catalogue,
|
|
58
|
+
installé à la demande, il montre des routes réseau avec une limite de
|
|
59
|
+
réponse déclarée, le stockage pour un catalogue en cache et une copie dans
|
|
60
|
+
le presse-papiers sur un clic.
|
|
61
|
+
|
|
62
|
+
## Travailler sur l’un d’eux
|
|
63
|
+
|
|
64
|
+
Depuis une copie de travail du dépôt, liez aux widgets le SDK de cette
|
|
65
|
+
révision, puis vérifiez l’un d’eux, empaquetez-le et lancez ses tests
|
|
66
|
+
unitaires :
|
|
67
|
+
|
|
68
|
+
```sh
|
|
69
|
+
node scripts/prepare-widgets.mjs
|
|
70
|
+
overcrow-widget check widgets/clock
|
|
71
|
+
overcrow-widget package widgets/clock
|
|
72
|
+
node --test widgets/clock/tests/logic.test.mjs
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`prepare-widgets.mjs` demande que le SDK soit construit d’abord (`npm ci`
|
|
76
|
+
puis `npm run build` dans `sdk/`). Les quatre templates
|
|
77
|
+
d’`overcrow-widget init` se trouvent dans
|
|
78
|
+
[`templates/`](../../../templates/), et deux exemples complets, écrits pour
|
|
79
|
+
ces pages, dans [`docs/content/examples/`](../examples/) : `weather` appelle
|
|
80
|
+
une API HTTP et `countdown` utilise un minuteur, un canvas, un menu
|
|
81
|
+
contextuel et le stockage.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Valhallab SASU
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Clock
|
|
2
|
+
|
|
3
|
+
`com.playervox.overcrow.clock` — the local time of day and, optionally, the
|
|
4
|
+
date on a second line. A built-in of OverCrow, written against the public
|
|
5
|
+
`@overcrow/sdk` and packaged with `overcrow-widget` like any creator's
|
|
6
|
+
widget. MIT.
|
|
7
|
+
|
|
8
|
+
## What it shows
|
|
9
|
+
|
|
10
|
+
| State | Shows |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| Default | `14:08` over `17/07/2026` |
|
|
13
|
+
| Seconds on | `14:08:42` |
|
|
14
|
+
| Date off | the time alone |
|
|
15
|
+
| Date format | `dd/mm/yyyy` (default), `yyyy-mm-dd` or `mm/dd/yyyy`, whatever the user's regional date order |
|
|
16
|
+
|
|
17
|
+
Always 24-hour and zero padded, in English and French alike. The time is
|
|
18
|
+
local: the VM's clock is UTC, and the SDK applies the host's UTC offset
|
|
19
|
+
(`host.region`), which the host sends again at each summer time change.
|
|
20
|
+
|
|
21
|
+
## Menu
|
|
22
|
+
|
|
23
|
+
| Row | Type | Default |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Show seconds / Afficher les secondes | toggle `show-seconds` | off |
|
|
26
|
+
| Show date / Afficher la date | toggle `show-date` | on |
|
|
27
|
+
| Date format / Format de date | choice `date-format`, shown while the date is | `day-month-year` |
|
|
28
|
+
|
|
29
|
+
## Permissions
|
|
30
|
+
|
|
31
|
+
None. The widget reads no service.
|
|
32
|
+
|
|
33
|
+
## How it works
|
|
34
|
+
|
|
35
|
+
- `timers.atEach("minute" | "second", tick)`: one repeating host timer
|
|
36
|
+
aligned on the local boundary, one VM turn per tick; a tick that drifted
|
|
37
|
+
re-aligns it. No tick while hidden; the time is current at once when the
|
|
38
|
+
widget is shown again.
|
|
39
|
+
- `onHost`: a menu change re-arms the timer at the new unit at once, and a
|
|
40
|
+
new UTC offset shows at once.
|
|
41
|
+
- The accessible label is "Local time {time}, {date}" /
|
|
42
|
+
"Heure locale {time}, {date}".
|
|
43
|
+
|
|
44
|
+
## Tests
|
|
45
|
+
|
|
46
|
+
- `tests/logic.test.mjs`: the logic on `@overcrow/sdk/testing` (formats,
|
|
47
|
+
defaults, the timer and its re-arming).
|
|
48
|
+
- Scenarios, played by `overcrow-widget test` in OverCrow's headless
|
|
49
|
+
runtime, with their reference images: `render` (both themes and
|
|
50
|
+
languages at 100 and 150 %), `options` (each menu row), `ticks` (minutes,
|
|
51
|
+
seconds, midnight), `hidden`, `summer-time` (both changes).
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
node ../../scripts/prepare-widgets.mjs
|
|
55
|
+
overcrow-widget check && overcrow-widget package
|
|
56
|
+
node --test tests/*.test.mjs
|
|
57
|
+
overcrow-widget test --runtime <overcrow-widget-headless>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Cost
|
|
61
|
+
|
|
62
|
+
Measured on 2026-09-30 with OverCrow's release build, on an AMD Ryzen 7
|
|
63
|
+
5800X3D Linux workstation and in a Windows 11 virtual machine (2 vCPU):
|
|
64
|
+
|
|
65
|
+
| | Linux | Windows (VM) |
|
|
66
|
+
| --- | --- | --- |
|
|
67
|
+
| VM start (spawn → ready) | 1.9 ms | 13.5–14.5 ms, sandboxed |
|
|
68
|
+
| Widget start, warm, into the overlay's runtime | 7 ms at most | — |
|
|
69
|
+
| VM memory | 0.55 MiB anonymous | 0.83 MiB private working set |
|
|
70
|
+
| VM CPU per tick, seconds shown | about 95 µs, one VM turn | — |
|
|
71
|
+
| Overlay frames | one each minute (each second with seconds) | — |
|
|
72
|
+
|
|
73
|
+
With the Session and FPS widgets beside it, the overlay's process grows by
|
|
74
|
+
about 2 MB per widget and stays at 0.1 % of one core; nothing runs while
|
|
75
|
+
the overlay is hidden.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "PlayerVox",
|
|
3
|
+
"spdxLicense": "MIT",
|
|
4
|
+
"sourceUrl": "https://github.com/Valhallab/playervox-overcrow-releases/tree/main/widgets/clock",
|
|
5
|
+
"preview": "assets/preview.png",
|
|
6
|
+
"defaultLocale": "en",
|
|
7
|
+
"localizations": [
|
|
8
|
+
{
|
|
9
|
+
"locale": "en",
|
|
10
|
+
"name": "Clock",
|
|
11
|
+
"description": "Shows the local time of day and, optionally, the date, in a 24-hour format."
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"locale": "fr",
|
|
15
|
+
"name": "Horloge",
|
|
16
|
+
"description": "Affiche l’heure locale et, en option, la date, au format 24 heures."
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Clock: the local time of day, 24-hour, and the date in the order the user
|
|
2
|
+
// chose in the widget menu. The VM's clock is UTC: the SDK formats from the
|
|
3
|
+
// host's UTC offset, and its timer wakes at each minute (or second) of local
|
|
4
|
+
// time.
|
|
5
|
+
import {
|
|
6
|
+
formatDate,
|
|
7
|
+
formatTime,
|
|
8
|
+
initState,
|
|
9
|
+
onHost,
|
|
10
|
+
option,
|
|
11
|
+
t,
|
|
12
|
+
timers,
|
|
13
|
+
type DateOrder,
|
|
14
|
+
type Timer,
|
|
15
|
+
} from "@overcrow/sdk";
|
|
16
|
+
|
|
17
|
+
/** The `date-format` menu values and the date order each one means. */
|
|
18
|
+
export const DATE_ORDERS: Readonly<Record<string, DateOrder>> = {
|
|
19
|
+
"day-month-year": "dmy",
|
|
20
|
+
"year-month-day": "ymd",
|
|
21
|
+
"month-day-year": "mdy",
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
declare module "@overcrow/sdk" {
|
|
25
|
+
interface WidgetState {
|
|
26
|
+
now: number;
|
|
27
|
+
seconds: boolean;
|
|
28
|
+
showDate: boolean;
|
|
29
|
+
order: DateOrder;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The menu values, with their defaults. */
|
|
34
|
+
export function menuValues(): { seconds: boolean; showDate: boolean; order: DateOrder } {
|
|
35
|
+
return {
|
|
36
|
+
seconds: option("show-seconds", false),
|
|
37
|
+
showDate: option("show-date", true),
|
|
38
|
+
order: DATE_ORDERS[option("date-format", "day-month-year")] ?? "dmy",
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const state = initState({ now: Date.now(), ...menuValues() });
|
|
43
|
+
|
|
44
|
+
export function clockTime(now: number, seconds: boolean): string {
|
|
45
|
+
return formatTime(now, { seconds });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function clockDate(now: number, order: DateOrder): string {
|
|
49
|
+
return formatDate(now, { order });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function clockLabel(now: number, seconds: boolean, showDate: boolean, order: DateOrder): string {
|
|
53
|
+
const time = clockTime(now, seconds);
|
|
54
|
+
return showDate ? t("label-date", { time, date: clockDate(now, order) }) : t("label", { time });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
let clock: Timer | undefined;
|
|
58
|
+
|
|
59
|
+
function tick(): void {
|
|
60
|
+
state.now = Date.now();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** Ticks at each second or minute of local time, and shows the time now. */
|
|
64
|
+
function start(): void {
|
|
65
|
+
clock?.cancel();
|
|
66
|
+
clock = timers.atEach(state.seconds ? "second" : "minute", tick);
|
|
67
|
+
tick();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onHost((changed) => {
|
|
71
|
+
if (changed.includes("options")) {
|
|
72
|
+
const values = menuValues();
|
|
73
|
+
const unitChanged = values.seconds !== state.seconds;
|
|
74
|
+
Object.assign(state, values);
|
|
75
|
+
if (unitChanged) {
|
|
76
|
+
start();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// A new UTC offset (time zone or summer time) shows at once.
|
|
80
|
+
if (changed.includes("region")) {
|
|
81
|
+
tick();
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
start();
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"apiVersion": 1,
|
|
4
|
+
"id": "com.playervox.overcrow.clock",
|
|
5
|
+
"version": "1.0.2",
|
|
6
|
+
"name": {
|
|
7
|
+
"en": "Clock",
|
|
8
|
+
"fr": "Horloge"
|
|
9
|
+
},
|
|
10
|
+
"sizing": {
|
|
11
|
+
"fit": "both",
|
|
12
|
+
"preferred": { "width": 110, "height": 60 },
|
|
13
|
+
"min": { "width": 40, "height": 24 },
|
|
14
|
+
"max": { "width": 480, "height": 240 }
|
|
15
|
+
},
|
|
16
|
+
"wrapper": {
|
|
17
|
+
"menu": [
|
|
18
|
+
{
|
|
19
|
+
"type": "toggle",
|
|
20
|
+
"id": "show-seconds",
|
|
21
|
+
"label": { "en": "Show seconds", "fr": "Afficher les secondes" },
|
|
22
|
+
"default": false
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"type": "toggle",
|
|
26
|
+
"id": "show-date",
|
|
27
|
+
"label": { "en": "Show date", "fr": "Afficher la date" },
|
|
28
|
+
"default": true
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": "choice",
|
|
32
|
+
"id": "date-format",
|
|
33
|
+
"label": { "en": "Date format", "fr": "Format de date" },
|
|
34
|
+
"visibleWhen": "show-date",
|
|
35
|
+
"choices": [
|
|
36
|
+
{ "value": "day-month-year", "label": { "en": "dd/mm/yyyy", "fr": "jj/mm/aaaa" } },
|
|
37
|
+
{ "value": "year-month-day", "label": { "en": "yyyy-mm-dd", "fr": "aaaa-mm-jj" } },
|
|
38
|
+
{ "value": "month-day-year", "label": { "en": "mm/dd/yyyy", "fr": "mm/jj/aaaa" } }
|
|
39
|
+
],
|
|
40
|
+
"default": "day-month-year"
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "overcrow-widget-clock",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"private": true,
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"check": "overcrow-widget check",
|
|
9
|
+
"package": "overcrow-widget package",
|
|
10
|
+
"test": "node --test tests/*.test.mjs"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@overcrow/sdk": "1.0.0",
|
|
14
|
+
"typescript": "6.0.3"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/* One compact column: the time over the date, 1 px apart. The wrapper
|
|
2
|
+
draws the panel and its 8 px margin; the content adds 2 px on the
|
|
3
|
+
sides: the built-in's 10 × 8 px margin. */
|
|
4
|
+
.clock {
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
align-items: start;
|
|
7
|
+
row-gap: 1px;
|
|
8
|
+
padding: 0 2px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Values use the UI font with tabular figures, so they never shift. */
|
|
12
|
+
.time {
|
|
13
|
+
font-family: var(--font-ui);
|
|
14
|
+
font-size: var(--font-size-value);
|
|
15
|
+
font-variant-numeric: tabular-nums;
|
|
16
|
+
color: var(--color-text);
|
|
17
|
+
white-space: nowrap;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.date {
|
|
21
|
+
font-family: var(--font-ui);
|
|
22
|
+
font-size: var(--font-size-small);
|
|
23
|
+
font-variant-numeric: tabular-nums;
|
|
24
|
+
color: var(--color-text-muted);
|
|
25
|
+
white-space: nowrap;
|
|
26
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scenarioVersion": 1,
|
|
3
|
+
"name": "hidden",
|
|
4
|
+
"description": "Hidden, the clock gets no tick; shown again, it shows the current time at once.",
|
|
5
|
+
"host": {
|
|
6
|
+
"zone": {
|
|
7
|
+
"offsetMinutes": 120
|
|
8
|
+
},
|
|
9
|
+
"startAt": 1784290122000,
|
|
10
|
+
"options": {
|
|
11
|
+
"show-seconds": true
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"steps": [
|
|
15
|
+
{
|
|
16
|
+
"expect": {
|
|
17
|
+
"text": [
|
|
18
|
+
"14:08:42"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"host": {
|
|
24
|
+
"visible": false
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"advance": {
|
|
29
|
+
"ms": 300000
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"expect": {
|
|
34
|
+
"text": [
|
|
35
|
+
"14:08:42"
|
|
36
|
+
],
|
|
37
|
+
"noText": [
|
|
38
|
+
"14:13:42"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"host": {
|
|
44
|
+
"visible": true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"expect": {
|
|
49
|
+
"text": [
|
|
50
|
+
"14:13:42"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"advance": {
|
|
56
|
+
"ms": 1000
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"expect": {
|
|
61
|
+
"text": [
|
|
62
|
+
"14:13:43"
|
|
63
|
+
],
|
|
64
|
+
"fault": "none"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Compiles this widget's logic.ts with the project's TypeScript into
|
|
2
|
+
// dist/ and imports it, after the test installed its runtime
|
|
3
|
+
// (`@overcrow/sdk/testing`), as the VM runs logic.js after its prelude.
|
|
4
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
5
|
+
import ts from "typescript";
|
|
6
|
+
|
|
7
|
+
export async function loadLogic() {
|
|
8
|
+
const root = new URL("../", import.meta.url);
|
|
9
|
+
const source = readFileSync(new URL("logic.ts", root), "utf8");
|
|
10
|
+
const { outputText } = ts.transpileModule(source, {
|
|
11
|
+
compilerOptions: {
|
|
12
|
+
module: ts.ModuleKind.ES2022,
|
|
13
|
+
target: ts.ScriptTarget.ES2023,
|
|
14
|
+
verbatimModuleSyntax: true,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
mkdirSync(new URL("dist/", root), { recursive: true });
|
|
18
|
+
// One file per test process: test files run in parallel.
|
|
19
|
+
const output = new URL(`dist/logic-${process.pid}.mjs`, root);
|
|
20
|
+
writeFileSync(output, outputText);
|
|
21
|
+
return import(output.href);
|
|
22
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Unit tests of the Clock's logic on @overcrow/sdk/testing: virtual time,
|
|
2
|
+
// the host's region and menu values, no VM.
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { test } from "node:test";
|
|
5
|
+
import { installRuntime } from "@overcrow/sdk/testing";
|
|
6
|
+
|
|
7
|
+
import { loadLogic } from "./load-logic.mjs";
|
|
8
|
+
|
|
9
|
+
// 14:08:42.250 in UTC+2, 2026-07-17.
|
|
10
|
+
const START = Date.UTC(2026, 6, 17, 12, 8, 42, 250);
|
|
11
|
+
const vm = installRuntime({
|
|
12
|
+
now: START,
|
|
13
|
+
host: {
|
|
14
|
+
region: { numberFormat: "us", dateOrder: "mdy", offsetMinutes: 120 },
|
|
15
|
+
messages: { label: "Local time {time}", "label-date": "Local time {time}, {date}" },
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
const logic = await loadLogic();
|
|
19
|
+
const { state } = await import("@overcrow/sdk");
|
|
20
|
+
|
|
21
|
+
test("defaults: date on, day/month/year, no seconds, whatever the region's order", () => {
|
|
22
|
+
assert.deepEqual(
|
|
23
|
+
{ seconds: state.seconds, showDate: state.showDate, order: state.order },
|
|
24
|
+
{ seconds: false, showDate: true, order: "dmy" },
|
|
25
|
+
);
|
|
26
|
+
assert.equal(logic.clockTime(state.now, state.seconds), "14:08");
|
|
27
|
+
assert.equal(logic.clockDate(state.now, state.order), "17/07/2026");
|
|
28
|
+
assert.equal(
|
|
29
|
+
logic.clockLabel(state.now, false, true, "dmy"),
|
|
30
|
+
"Local time 14:08, 17/07/2026",
|
|
31
|
+
);
|
|
32
|
+
assert.equal(logic.clockLabel(state.now, true, false, "dmy"), "Local time 14:08:42");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("the three date formats and an unknown stored value", () => {
|
|
36
|
+
const formats = {};
|
|
37
|
+
for (const [value, order] of Object.entries(logic.DATE_ORDERS)) {
|
|
38
|
+
formats[value] = logic.clockDate(START, order);
|
|
39
|
+
}
|
|
40
|
+
assert.deepEqual(formats, {
|
|
41
|
+
"day-month-year": "17/07/2026",
|
|
42
|
+
"year-month-day": "2026-07-17",
|
|
43
|
+
"month-day-year": "07/17/2026",
|
|
44
|
+
});
|
|
45
|
+
vm.setHost({ options: { "date-format": "week-day" } });
|
|
46
|
+
assert.equal(state.order, "dmy", "an unknown value falls back to the default");
|
|
47
|
+
vm.setHost({ options: {} });
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test("24-hour, zero padded", () => {
|
|
51
|
+
const night = Date.UTC(2026, 0, 1, 23, 5, 9);
|
|
52
|
+
assert.equal(logic.clockTime(night, true), "01:05:09");
|
|
53
|
+
assert.equal(logic.clockTime(Date.UTC(2026, 0, 1, 11, 0, 0), false), "13:00");
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("one timer at the next local minute, then each minute", () => {
|
|
57
|
+
assert.equal(vm.timers.length, 1);
|
|
58
|
+
assert.equal(vm.timers[0].dueAt, Date.UTC(2026, 6, 17, 12, 9));
|
|
59
|
+
vm.advance(Date.UTC(2026, 6, 17, 12, 9) - vm.now);
|
|
60
|
+
assert.equal(logic.clockTime(state.now, state.seconds), "14:09");
|
|
61
|
+
assert.deepEqual(
|
|
62
|
+
vm.timers.map(({ intervalMs, repeat }) => ({ intervalMs, repeat })),
|
|
63
|
+
[{ intervalMs: 60_000, repeat: true }],
|
|
64
|
+
);
|
|
65
|
+
assert.equal(vm.advance(120_000), 2);
|
|
66
|
+
assert.equal(logic.clockTime(state.now, state.seconds), "14:11");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("turning seconds on re-arms at once on seconds, and off again on minutes", () => {
|
|
70
|
+
vm.advance(7_500);
|
|
71
|
+
vm.setHost({ options: { "show-seconds": true } });
|
|
72
|
+
assert.equal(state.seconds, true);
|
|
73
|
+
assert.equal(logic.clockTime(state.now, state.seconds), "14:11:07", "shown at once");
|
|
74
|
+
assert.equal(vm.timers.length, 1, "the minute timer is gone");
|
|
75
|
+
vm.advance(500);
|
|
76
|
+
assert.equal(logic.clockTime(state.now, state.seconds), "14:11:08");
|
|
77
|
+
vm.advance(1_000);
|
|
78
|
+
assert.equal(logic.clockTime(state.now, state.seconds), "14:11:09");
|
|
79
|
+
vm.setHost({ options: { "show-seconds": false, "show-date": false } });
|
|
80
|
+
assert.equal(state.showDate, false);
|
|
81
|
+
assert.equal(vm.timers.length, 1);
|
|
82
|
+
assert.equal(vm.timers[0].dueAt, Date.UTC(2026, 6, 17, 12, 12));
|
|
83
|
+
vm.setHost({ options: {} });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("a new UTC offset shows at once", () => {
|
|
87
|
+
vm.setHost({ region: { numberFormat: "us", dateOrder: "mdy", offsetMinutes: -240 } });
|
|
88
|
+
assert.equal(logic.clockTime(state.now, state.seconds), "08:11");
|
|
89
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scenarioVersion": 1,
|
|
3
|
+
"name": "options",
|
|
4
|
+
"description": "Each menu row, applied from the menu at 14:08:42 local time: seconds, the three date orders, the date hidden.",
|
|
5
|
+
"host": {
|
|
6
|
+
"zone": {
|
|
7
|
+
"offsetMinutes": 120
|
|
8
|
+
},
|
|
9
|
+
"startAt": 1784290122000
|
|
10
|
+
},
|
|
11
|
+
"steps": [
|
|
12
|
+
{
|
|
13
|
+
"menu": {
|
|
14
|
+
"id": "show-seconds",
|
|
15
|
+
"value": true
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"expect": {
|
|
20
|
+
"text": [
|
|
21
|
+
"14:08:42",
|
|
22
|
+
"17/07/2026"
|
|
23
|
+
],
|
|
24
|
+
"image": "seconds-dark"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"host": {
|
|
29
|
+
"theme": "light"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"expect": {
|
|
34
|
+
"image": "seconds-light"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"host": {
|
|
39
|
+
"theme": "dark"
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"menu": {
|
|
44
|
+
"id": "show-seconds",
|
|
45
|
+
"value": false
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"menu": {
|
|
50
|
+
"id": "date-format",
|
|
51
|
+
"value": "year-month-day"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"expect": {
|
|
56
|
+
"text": [
|
|
57
|
+
"14:08",
|
|
58
|
+
"2026-07-17"
|
|
59
|
+
],
|
|
60
|
+
"image": "year-month-day"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"menu": {
|
|
65
|
+
"id": "date-format",
|
|
66
|
+
"value": "month-day-year"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"expect": {
|
|
71
|
+
"text": [
|
|
72
|
+
"14:08",
|
|
73
|
+
"07/17/2026"
|
|
74
|
+
],
|
|
75
|
+
"image": "month-day-year"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"menu": {
|
|
80
|
+
"id": "show-date",
|
|
81
|
+
"value": false
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"expect": {
|
|
86
|
+
"text": [
|
|
87
|
+
"14:08"
|
|
88
|
+
],
|
|
89
|
+
"noText": [
|
|
90
|
+
"07/17/2026"
|
|
91
|
+
],
|
|
92
|
+
"image": "time-only-dark"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"host": {
|
|
97
|
+
"theme": "light",
|
|
98
|
+
"scale": 1500
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"expect": {
|
|
103
|
+
"image": "time-only-light-150",
|
|
104
|
+
"fault": "none"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|