@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,94 @@
|
|
|
1
|
+
.countdown {
|
|
2
|
+
flex-direction: column;
|
|
3
|
+
gap: var(--space-3);
|
|
4
|
+
padding: var(--space-4);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/* The time sits in the middle of the ring: both share one grid cell. */
|
|
8
|
+
.dial {
|
|
9
|
+
display: grid;
|
|
10
|
+
grid-template-columns: 72px;
|
|
11
|
+
grid-template-rows: 72px;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
justify-items: center;
|
|
14
|
+
align-items: center;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ring {
|
|
18
|
+
grid-column: 1;
|
|
19
|
+
grid-row: 1;
|
|
20
|
+
width: 72px;
|
|
21
|
+
height: 72px;
|
|
22
|
+
color: var(--color-accent);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.ring.done {
|
|
26
|
+
color: var(--color-success);
|
|
27
|
+
animation: countdown-pulse 800ms ease-in-out 3 alternate;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@keyframes countdown-pulse {
|
|
31
|
+
from { opacity: 1; }
|
|
32
|
+
to { opacity: 0.4; }
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.time {
|
|
36
|
+
grid-column: 1;
|
|
37
|
+
grid-row: 1;
|
|
38
|
+
font-family: var(--font-mono);
|
|
39
|
+
font-size: var(--font-size-body);
|
|
40
|
+
font-variant-numeric: tabular-nums;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.controls {
|
|
44
|
+
align-items: center;
|
|
45
|
+
gap: var(--space-2);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.duration {
|
|
49
|
+
flex-grow: 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.start {
|
|
53
|
+
width: var(--control-height);
|
|
54
|
+
height: var(--control-height);
|
|
55
|
+
justify-content: center;
|
|
56
|
+
align-items: center;
|
|
57
|
+
border-radius: var(--radius-md);
|
|
58
|
+
background: var(--color-surface-raised);
|
|
59
|
+
transition: background-color var(--duration-fast) ease-out;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.start:hover {
|
|
63
|
+
background: var(--color-surface-hover);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.start:focus {
|
|
67
|
+
border: 1px solid var(--color-accent);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.repeat:checked {
|
|
71
|
+
color: var(--color-accent);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.stat {
|
|
75
|
+
justify-content: space-between;
|
|
76
|
+
font-size: var(--font-size-small);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.stat-name {
|
|
80
|
+
color: var(--color-text-muted);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.dots {
|
|
84
|
+
height: 12px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.menu-row {
|
|
88
|
+
padding: var(--space-2) var(--space-4);
|
|
89
|
+
border-radius: var(--radius-sm);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.menu-row:hover {
|
|
93
|
+
background: var(--color-surface-hover);
|
|
94
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2023",
|
|
4
|
+
"lib": ["ES2023"],
|
|
5
|
+
"types": [],
|
|
6
|
+
"module": "ES2022",
|
|
7
|
+
"moduleResolution": "bundler",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"noEmit": true,
|
|
10
|
+
"isolatedModules": true,
|
|
11
|
+
"verbatimModuleSyntax": true,
|
|
12
|
+
"noUncheckedIndexedAccess": true,
|
|
13
|
+
"exactOptionalPropertyTypes": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["logic.ts"]
|
|
16
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!-- A countdown: a ring that empties, a duration chosen in a list, and the
|
|
2
|
+
finished rounds drawn as dots. A right click opens a small menu. -->
|
|
3
|
+
<component name="stat" props="name value">
|
|
4
|
+
<box class="stat">
|
|
5
|
+
<text class="stat-name">{name}</text>
|
|
6
|
+
<text class="stat-value">{value}</text>
|
|
7
|
+
</box>
|
|
8
|
+
</component>
|
|
9
|
+
|
|
10
|
+
<box ref="panel" class="countdown" on:contextmenu={openMenu}>
|
|
11
|
+
<box class="dial">
|
|
12
|
+
<gauge class={ringClass(state.remainingMs)} value={state.remainingMs} max={total(state.minutes)} label={t("remaining")}/>
|
|
13
|
+
<text class="time">{timeLeft(state.remainingMs)}</text>
|
|
14
|
+
</box>
|
|
15
|
+
<box class="controls">
|
|
16
|
+
<select class="duration" value={minutesValue(state.minutes)} label={t("duration")} disabled={state.running} on:change={setMinutes}>
|
|
17
|
+
<for each={state.durations} as="minutes" key={minutes}>
|
|
18
|
+
<option value={minutesValue(minutes)}>{t("minutes", { count: minutes })}</option>
|
|
19
|
+
</for>
|
|
20
|
+
</select>
|
|
21
|
+
<button class="start" label={startLabel(state.running)} on:activate={toggle}>
|
|
22
|
+
<if test={state.running}>
|
|
23
|
+
<icon name="pause"/>
|
|
24
|
+
</if>
|
|
25
|
+
<else>
|
|
26
|
+
<icon name="play"/>
|
|
27
|
+
</else>
|
|
28
|
+
</button>
|
|
29
|
+
<toggle class="repeat" label={t("repeat")} tooltip={t("repeat")} checked={state.repeat} on:change={setRepeat}/>
|
|
30
|
+
</box>
|
|
31
|
+
<stat name={t("state")} value={stateText(state.running, state.remainingMs)}/>
|
|
32
|
+
<if test={state.showRounds}>
|
|
33
|
+
<stat name={t("rounds")} value={state.rounds}/>
|
|
34
|
+
<canvas ref="dots" class="dots" label={t("rounds-drawn", { count: state.rounds })}/>
|
|
35
|
+
</if>
|
|
36
|
+
</box>
|
|
37
|
+
|
|
38
|
+
<popover anchor="panel" placement="pointer" open={state.menu} on:dismiss={closeMenu}>
|
|
39
|
+
<button class="menu-row" on:activate={resetRounds}>
|
|
40
|
+
<text class="menu-text">{t("reset-rounds")}</text>
|
|
41
|
+
</button>
|
|
42
|
+
</popover>
|
|
@@ -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,64 @@
|
|
|
1
|
+
# FPS
|
|
2
|
+
|
|
3
|
+
`com.playervox.overcrow.fps` — the frame rate the game presents, observed
|
|
4
|
+
from outside the game. 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
|
+
| A reading | `144 FPS` (the unit muted, 12 px semibold) |
|
|
13
|
+
| A gap of the capture | the last reading, exactly as it was |
|
|
14
|
+
| No reading yet | `— FPS`, muted |
|
|
15
|
+
| Label off | the value alone |
|
|
16
|
+
|
|
17
|
+
Hovering the widget in Interactive mode shows one sentence, the
|
|
18
|
+
measurement status's (`ready`, `waiting`, `unsupported`,
|
|
19
|
+
`permission_denied`, `ambiguous`, `events_lost`, `unavailable`).
|
|
20
|
+
|
|
21
|
+
## Menu
|
|
22
|
+
|
|
23
|
+
| Row | Type | Default |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Show “FPS” label / Afficher le libellé « FPS » | toggle `show-label` | on |
|
|
26
|
+
|
|
27
|
+
## Permissions
|
|
28
|
+
|
|
29
|
+
`fps.read` (not sensitive), and `requires: ["fps"]`: on a machine without a
|
|
30
|
+
frame-rate source OverCrow neither starts nor shows the widget, and keeps
|
|
31
|
+
its place for when the source comes back.
|
|
32
|
+
|
|
33
|
+
## How it works
|
|
34
|
+
|
|
35
|
+
`fps.subscribe` gives `{ fps, stale, status }`; the host keeps the last
|
|
36
|
+
value of the game through a gap of its capture until the next one, so the
|
|
37
|
+
widget runs no timer and shows the value as it is: a value shown never
|
|
38
|
+
disappears and shows no sign of its age (`stale` is not drawn). The
|
|
39
|
+
accessible label is "144 frames per second" or "Frame rate unavailable".
|
|
40
|
+
|
|
41
|
+
## Tests
|
|
42
|
+
|
|
43
|
+
- `tests/logic.test.mjs`: the logic on `@overcrow/sdk/testing` (value,
|
|
44
|
+
colour, sentences, labels, updates, the label row).
|
|
45
|
+
- Scenarios with their reference images: `render` (both themes and
|
|
46
|
+
languages at 100 and 150 %), `stale` (a reading kept through a gap looks
|
|
47
|
+
unchanged), `unavailable` (the statuses, the
|
|
48
|
+
service stopping), `label`, `refused`.
|
|
49
|
+
|
|
50
|
+
## Cost
|
|
51
|
+
|
|
52
|
+
Measured on 2026-09-30 with OverCrow's release build, on an AMD Ryzen 7
|
|
53
|
+
5800X3D Linux workstation and in a Windows 11 virtual machine (2 vCPU):
|
|
54
|
+
|
|
55
|
+
| | Linux | Windows (VM) |
|
|
56
|
+
| --- | --- | --- |
|
|
57
|
+
| Widget start, warm, into the overlay's runtime | 7 ms at most | — |
|
|
58
|
+
| VM memory | 0.55–0.59 MiB anonymous | similar to the Clock's 0.83 MiB private working set |
|
|
59
|
+
| VM CPU | one short turn per new reading | — |
|
|
60
|
+
| Overlay frames | one per new reading | — |
|
|
61
|
+
|
|
62
|
+
With the Clock and Session widgets beside it, the overlay's process grows
|
|
63
|
+
by about 2 MB per widget and stays at 0.15 % of one core with a reading
|
|
64
|
+
each second; nothing runs while 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/fps",
|
|
5
|
+
"preview": "assets/preview.png",
|
|
6
|
+
"defaultLocale": "en",
|
|
7
|
+
"localizations": [
|
|
8
|
+
{
|
|
9
|
+
"locale": "en",
|
|
10
|
+
"name": "FPS",
|
|
11
|
+
"description": "Shows the game’s presented frame rate, when the host has a frame rate source."
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"locale": "fr",
|
|
15
|
+
"name": "FPS",
|
|
16
|
+
"description": "Affiche la fréquence d’images présentée par le jeu, quand l’hôte dispose d’une source."
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"label": "{fps} frames per second",
|
|
3
|
+
"label-none": "Frame rate unavailable",
|
|
4
|
+
"hint-ready": "Frames the game presented, observed from outside the game: its presentation rate, not the refresh rate of the display.",
|
|
5
|
+
"hint-waiting": "Waiting for frames from the game window. A paused game keeps this value unavailable.",
|
|
6
|
+
"hint-unsupported": "The frame rate of this game window cannot be measured on this system.",
|
|
7
|
+
"hint-permission_denied": "OverCrow was denied access to the game's frame events.",
|
|
8
|
+
"hint-ambiguous": "Several presentation sources prevent a reliable FPS measurement.",
|
|
9
|
+
"hint-events_lost": "Frame events were lost. No reliable FPS measurement is available.",
|
|
10
|
+
"hint-unavailable": "FPS capture is not available. See Diagnostics in the Control Center."
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"label": "{fps} images par seconde",
|
|
3
|
+
"label-none": "FPS indisponibles",
|
|
4
|
+
"hint-ready": "Images présentées par le jeu, observées de l’extérieur du jeu : son rythme de présentation, pas la fréquence de l’écran.",
|
|
5
|
+
"hint-waiting": "En attente d’images de la fenêtre de jeu. Un jeu en pause laisse cette valeur indisponible.",
|
|
6
|
+
"hint-unsupported": "Les FPS de cette fenêtre de jeu ne peuvent pas être mesurés sur ce système.",
|
|
7
|
+
"hint-permission_denied": "OverCrow s’est vu refuser l’accès aux événements d’image du jeu.",
|
|
8
|
+
"hint-ambiguous": "Plusieurs sources de présentation empêchent une mesure fiable des FPS.",
|
|
9
|
+
"hint-events_lost": "Des événements d’image ont été perdus. Aucune mesure fiable des FPS n’est disponible.",
|
|
10
|
+
"hint-unavailable": "La capture FPS n’est pas disponible. Ouvrez Diagnostic dans le Centre de contrôle."
|
|
11
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// FPS: the game's presented frame rate. The host measures it outside the
|
|
2
|
+
// game and keeps the last value through a gap until the next one; the
|
|
3
|
+
// widget shows it as it is, with no sign of its age (a value shown never
|
|
4
|
+
// disappears or changes look while the game runs), and a sentence for each
|
|
5
|
+
// measurement status.
|
|
6
|
+
import { fps, hasGrant, initState, onHost, option, t, type Fps } from "@overcrow/sdk";
|
|
7
|
+
|
|
8
|
+
type Status = Fps["status"];
|
|
9
|
+
|
|
10
|
+
declare module "@overcrow/sdk" {
|
|
11
|
+
interface WidgetState {
|
|
12
|
+
fps: number | null;
|
|
13
|
+
status: Status;
|
|
14
|
+
showLabel: boolean;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const state = initState({
|
|
19
|
+
fps: null as number | null,
|
|
20
|
+
status: "waiting" as Status,
|
|
21
|
+
showLabel: option("show-label", true),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
/** The integer value, or an em dash without one. */
|
|
25
|
+
export function fpsValue(value: number | null): string {
|
|
26
|
+
return value === null ? "—" : String(Math.round(value));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A value is primary, fresh or kept through a gap; no value is muted. */
|
|
30
|
+
export function valueClass(value: number | null): string {
|
|
31
|
+
return value === null ? "value muted" : "value";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function fpsLabel(value: number | null): string {
|
|
35
|
+
return value === null ? t("label-none") : t("label", { fps: fpsValue(value) });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** The hover sentence of the measurement status. */
|
|
39
|
+
export function fpsTooltip(status: Status): string {
|
|
40
|
+
return t(`hint-${status}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The state an update, or a failure of the subscription, leaves. */
|
|
44
|
+
export function reading(
|
|
45
|
+
update: { ok: true; value: Fps } | { ok: false },
|
|
46
|
+
): Pick<Fps, "fps" | "status"> {
|
|
47
|
+
return update.ok
|
|
48
|
+
? { fps: update.value.fps, status: update.value.status }
|
|
49
|
+
: { fps: null, status: "unavailable" };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onHost((changed) => {
|
|
53
|
+
if (changed.includes("options")) {
|
|
54
|
+
state.showLabel = option("show-label", true);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (hasGrant("fps.read")) {
|
|
59
|
+
fps.subscribe((update) => {
|
|
60
|
+
Object.assign(state, reading(update));
|
|
61
|
+
});
|
|
62
|
+
} else {
|
|
63
|
+
state.status = "unavailable";
|
|
64
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"apiVersion": 1,
|
|
4
|
+
"id": "com.playervox.overcrow.fps",
|
|
5
|
+
"version": "1.0.3",
|
|
6
|
+
"name": {
|
|
7
|
+
"en": "FPS",
|
|
8
|
+
"fr": "FPS"
|
|
9
|
+
},
|
|
10
|
+
"sizing": {
|
|
11
|
+
"fit": "both",
|
|
12
|
+
"preferred": { "width": 110, "height": 44 },
|
|
13
|
+
"min": { "width": 40, "height": 24 },
|
|
14
|
+
"max": { "width": 480, "height": 240 }
|
|
15
|
+
},
|
|
16
|
+
"requires": ["fps"],
|
|
17
|
+
"permissions": {
|
|
18
|
+
"capabilities": ["fps.read"]
|
|
19
|
+
},
|
|
20
|
+
"wrapper": {
|
|
21
|
+
"menu": [
|
|
22
|
+
{
|
|
23
|
+
"type": "toggle",
|
|
24
|
+
"id": "show-label",
|
|
25
|
+
"label": { "en": "Show “FPS” label", "fr": "Afficher le libellé « FPS »" },
|
|
26
|
+
"default": true
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "overcrow-widget-fps",
|
|
3
|
+
"version": "1.0.3",
|
|
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,31 @@
|
|
|
1
|
+
/* One line; the wrapper draws the panel and its 8 px margin, the content
|
|
2
|
+
adds 2 px on the sides: the built-in's 10 × 8 px margin. */
|
|
3
|
+
.fps {
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
align-items: start;
|
|
6
|
+
padding: 0 2px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.line {
|
|
10
|
+
font-family: var(--font-ui);
|
|
11
|
+
font-variant-numeric: tabular-nums;
|
|
12
|
+
color: var(--color-text-muted);
|
|
13
|
+
white-space: nowrap;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* A value is primary; no value is muted. */
|
|
17
|
+
.value {
|
|
18
|
+
font-size: var(--font-size-value);
|
|
19
|
+
color: var(--color-text);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.value.muted {
|
|
23
|
+
color: var(--color-text-muted);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* The unit: 12 px semibold, between the small and button sizes, as the
|
|
27
|
+
built-in drew it. */
|
|
28
|
+
.small {
|
|
29
|
+
font-size: 12px;
|
|
30
|
+
font-weight: 600;
|
|
31
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scenarioVersion": 1,
|
|
3
|
+
"name": "label",
|
|
4
|
+
"description": "The “Show FPS label” menu row: the value alone, fresh and kept through a gap (unchanged), then the unit back.",
|
|
5
|
+
"fixtures": {
|
|
6
|
+
"subscriptions": {
|
|
7
|
+
"fps.subscribe": {
|
|
8
|
+
"fps": 144,
|
|
9
|
+
"stale": false,
|
|
10
|
+
"status": "ready"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"steps": [
|
|
15
|
+
{
|
|
16
|
+
"menu": {
|
|
17
|
+
"id": "show-label",
|
|
18
|
+
"value": false
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"expect": {
|
|
23
|
+
"text": [
|
|
24
|
+
"144"
|
|
25
|
+
],
|
|
26
|
+
"noText": [
|
|
27
|
+
" FPS"
|
|
28
|
+
],
|
|
29
|
+
"image": "value-only"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"publish": {
|
|
34
|
+
"service": "fps.subscribe",
|
|
35
|
+
"value": {
|
|
36
|
+
"fps": 144,
|
|
37
|
+
"stale": true,
|
|
38
|
+
"status": "ready"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"expect": {
|
|
44
|
+
"image": "value-only-kept"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"menu": {
|
|
49
|
+
"id": "show-label",
|
|
50
|
+
"value": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"expect": {
|
|
55
|
+
"text": [
|
|
56
|
+
" FPS"
|
|
57
|
+
],
|
|
58
|
+
"image": "kept-with-label",
|
|
59
|
+
"fault": "none"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
@@ -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,60 @@
|
|
|
1
|
+
// Unit tests of the FPS widget's logic on @overcrow/sdk/testing.
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { test } from "node:test";
|
|
4
|
+
import { installRuntime } from "@overcrow/sdk/testing";
|
|
5
|
+
|
|
6
|
+
import { loadLogic } from "./load-logic.mjs";
|
|
7
|
+
|
|
8
|
+
const MESSAGES = {"label": "{fps} frames per second", "label-none": "Frame rate unavailable", "hint-ready": "Frames the game presented, observed from outside the game: its presentation rate, not the refresh rate of the display.", "hint-waiting": "Waiting for frames from the game window. A paused game keeps this value unavailable.", "hint-unsupported": "The frame rate of this game window cannot be measured on this system.", "hint-permission_denied": "OverCrow was denied access to the game's frame events.", "hint-ambiguous": "Several presentation sources prevent a reliable FPS measurement.", "hint-events_lost": "Frame events were lost. No reliable FPS measurement is available.", "hint-unavailable": "FPS capture is not available. See Diagnostics in the Control Center."};
|
|
9
|
+
const STATUSES = ["ready", "waiting", "unsupported", "permission_denied", "ambiguous", "events_lost", "unavailable"];
|
|
10
|
+
|
|
11
|
+
const vm = installRuntime({ host: { grants: ["fps.read"], messages: MESSAGES } });
|
|
12
|
+
const logic = await loadLogic();
|
|
13
|
+
const { state } = await import("@overcrow/sdk");
|
|
14
|
+
|
|
15
|
+
test("it subscribes once and waits for a first reading", () => {
|
|
16
|
+
assert.deepEqual(vm.subscriptions.map(({ service }) => service), ["fps.subscribe"]);
|
|
17
|
+
assert.deepEqual(
|
|
18
|
+
{ fps: state.fps, status: state.status, showLabel: state.showLabel },
|
|
19
|
+
{ fps: null, status: "waiting", showLabel: true },
|
|
20
|
+
);
|
|
21
|
+
assert.equal(vm.timers.length, 0, "the host keeps a reading through a gap: no timer");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("value and colour: a value kept through a gap looks as it did", () => {
|
|
25
|
+
assert.equal(logic.fpsValue(null), "—");
|
|
26
|
+
assert.equal(logic.fpsValue(144), "144");
|
|
27
|
+
assert.equal(logic.valueClass(144), "value");
|
|
28
|
+
assert.equal(logic.valueClass(null), "value muted");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("each status has its own sentence", () => {
|
|
32
|
+
const sentences = STATUSES.map((status) => logic.fpsTooltip(status));
|
|
33
|
+
assert.equal(new Set(sentences).size, STATUSES.length);
|
|
34
|
+
assert.ok(sentences.every((sentence) => !sentence.startsWith("hint-")), "every key exists");
|
|
35
|
+
assert.equal(logic.fpsTooltip("ready"), MESSAGES["hint-ready"]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("accessible labels", () => {
|
|
39
|
+
assert.equal(logic.fpsLabel(144), "144 frames per second");
|
|
40
|
+
assert.equal(logic.fpsLabel(null), "Frame rate unavailable");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("updates, a reading kept through a gap and the end of the subscription", () => {
|
|
44
|
+
vm.push("fps.subscribe", { fps: 144, stale: false, status: "ready" });
|
|
45
|
+
assert.deepEqual([state.fps, state.status], [144, "ready"]);
|
|
46
|
+
// The host keeps the value through a gap, marked stale: nothing changes.
|
|
47
|
+
vm.push("fps.subscribe", { fps: 144, stale: true, status: "ready" });
|
|
48
|
+
assert.deepEqual([state.fps, state.status], [144, "ready"]);
|
|
49
|
+
vm.push("fps.subscribe", { fps: null, stale: false, status: "unavailable" });
|
|
50
|
+
assert.deepEqual([state.fps, state.status], [null, "unavailable"], "the service stopped (W.2)");
|
|
51
|
+
vm.fail("fps.subscribe", "permission_denied");
|
|
52
|
+
assert.deepEqual([state.fps, state.status], [null, "unavailable"]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("the label row applies at once", () => {
|
|
56
|
+
vm.setHost({ options: { "show-label": false } });
|
|
57
|
+
assert.equal(state.showLabel, false);
|
|
58
|
+
vm.setHost({ options: {} });
|
|
59
|
+
assert.equal(state.showLabel, true);
|
|
60
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scenarioVersion": 1,
|
|
3
|
+
"name": "preview",
|
|
4
|
+
"description": "A fresh reading of 144 frames per second. The marketplace preview: dark theme, English, 150 %, on the stage colour; scripts/compose-previews.mjs frames it into assets/preview.png.",
|
|
5
|
+
"host": {
|
|
6
|
+
"scale": 1500,
|
|
7
|
+
"background": "#1e242e"
|
|
8
|
+
},
|
|
9
|
+
"fixtures": {
|
|
10
|
+
"subscriptions": {
|
|
11
|
+
"fps.subscribe": {
|
|
12
|
+
"fps": 144,
|
|
13
|
+
"stale": false,
|
|
14
|
+
"status": "ready"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"steps": [
|
|
19
|
+
{
|
|
20
|
+
"expect": {
|
|
21
|
+
"state": "running",
|
|
22
|
+
"text": [
|
|
23
|
+
"144"
|
|
24
|
+
],
|
|
25
|
+
"image": "preview"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"scenarioVersion": 1,
|
|
3
|
+
"name": "refused",
|
|
4
|
+
"description": "Without the fps.read grant the widget asks nothing and shows no value.",
|
|
5
|
+
"host": {
|
|
6
|
+
"grants": []
|
|
7
|
+
},
|
|
8
|
+
"steps": [
|
|
9
|
+
{
|
|
10
|
+
"expect": {
|
|
11
|
+
"state": "running",
|
|
12
|
+
"text": [
|
|
13
|
+
"—"
|
|
14
|
+
],
|
|
15
|
+
"calls": [],
|
|
16
|
+
"fault": "none"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|