Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 11 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,16 @@ jobs:
- name: Run Playwright Smoke
run: npm run test:e2e:smoke

- name: Run Route Width Screenshot Matrix
run: npm run test:e2e:route-width

- name: Upload Route Width Screenshots
if: always()
uses: actions/upload-artifact@v6
with:
name: route-width-screenshots
path: test-results/route-width
if-no-files-found: error

- name: Run PWA Smoke
run: npm run test:e2e:pwa
15 changes: 15 additions & 0 deletions docs/quality/input-intent-taxonomy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Input intent taxonomy

Tool input sizing uses five stable intents:

| Intent | Use |
| --- | --- |
| `scalar` | Numbers, colors, flags, enum-like controls, and other compact values. |
| `shortText` | URLs, names, expressions, and short free-form text. |
| `payload` | User-authored JSON, CSV, tokens, logs, code, and multiline data. |
| `workbench` | Dense editor or split-pane work areas. |
| `generatedOutput` | Read-only generated text or code with copy/export actions. |

`Input`, `Textarea`, Monaco wrappers, and `TextOutputPanel` emit `data-input-intent` at runtime. The create-tool scaffold declares a payload input, a workbench container, and generated output explicitly.

`tests/guards/input-intent-taxonomy.test.ts` parses every TSX file under `src` to inventory shared controls plus raw `input`, `textarea`, and `select` elements. Representative routes must declare an explicit intent. Remaining hardcoded height tokens are frozen by a stable file/tag/token hash, so a new unclassified size fails CI without depending on source line numbers.
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
"scripts": {
"dev": "next dev",
"analyze": "ANALYZE=true next build --webpack",
"validate": "npm run check:sw-version && npm run check:sitemap-lastmod && npm run check:security-headers && npm run check:pwa-manifests && npm run check:runtime-scripts && npm run check:llms-txt && npm run check:bundle-boundaries && npm run check:performance-budget && npm run check:og-tool-images && npm run check:ia-stability && npm run check:analytics-taxonomy && npm run check:registry-manifests && npm run check:tool-index && npm run check:legacy-routes && npm run check:client-tool-lookup && npm run check:privacy-copy && npm run check:i18n && npm run check:i18n-qa && npm run check:types",
"validate": "npm run check:sw-version && npm run check:sitemap-lastmod && npm run check:security-headers && npm run check:pwa-manifests && npm run check:runtime-scripts && npm run check:llms-txt && npm run check:bundle-boundaries && npm run check:performance-budget && npm run check:og-tool-images && npm run check:ia-stability && npm run check:route-width-inventory && npm run check:analytics-taxonomy && npm run check:registry-manifests && npm run check:tool-index && npm run check:legacy-routes && npm run check:client-tool-lookup && npm run check:privacy-copy && npm run check:i18n && npm run check:i18n-qa && npm run check:types",
"build:app": "next build",
"build:post": "npm run check:canonical && npm run check:hreflang && npm run check:legacy-routes && npm run check:metadata-localization && npm run check:jsonld-structured-data && npm run check:performance-budget:report && npm run check:rendered-i18n-copy && npm run check:related-tools && npm run check:content-template:legacy-paths && npm run check:content-template && npm run check:content-template:quality && npm run check:content-template:uniqueness && npm run check:faq-schema && npm run check:content-template:zh-cn && npm run check:content-template:quality:zh-cn && npm run check:faq-schema:zh-cn && npm run check:content-template:zh-tw && npm run check:content-template:quality:zh-tw && npm run check:faq-schema:zh-tw && npm run check:content-template:ja && npm run check:content-template:quality:ja && npm run check:faq-schema:ja && npm run check:content-template:ko && npm run check:content-template:quality:ko && npm run check:faq-schema:ko && npm run check:content-template:de && npm run check:content-template:quality:de && npm run check:faq-schema:de && npm run check:content-template:fr && npm run check:content-template:quality:fr && npm run check:faq-schema:fr && npm run postprocess:export-html-lang && npm run check:export-html-lang && npm run postprocess:export-robots-meta && npm run check:export-robots-meta && npm run check:sitemap-export && npm run build:sw",
"build": "npm run validate && npm run build:app && npm run build:post",
Expand All @@ -60,6 +60,8 @@
"test": "vitest run",
"test:coverage": "vitest run --coverage",
"test:e2e:smoke": "node scripts/e2e/run-playwright-smoke.js",
"test:e2e:first-load": "node scripts/e2e/run-playwright-smoke.js --first-load-only --first-load-artifacts",
"test:e2e:route-width": "node scripts/e2e/run-route-width-matrix.js",
"test:e2e:pwa": "node scripts/e2e/run-playwright-smoke.js --pwa",
"check:i18n": "node scripts/gates/check-i18n.js",
"check:i18n-qa": "node scripts/gates/check-i18n-qa.js",
Expand All @@ -79,6 +81,8 @@
"check:sitemap-lastmod": "node scripts/gates/check-sitemap-lastmod.js",
"generate:ia-baseline": "node scripts/generators/generate-ia-baseline.js",
"check:ia-stability": "node scripts/gates/check-ia-stability.js",
"generate:route-width-inventory": "node scripts/generators/generate-route-width-inventory.js",
"check:route-width-inventory": "node scripts/generators/generate-route-width-inventory.js --check",
"check:analytics-taxonomy": "node scripts/gates/check-analytics-taxonomy.js",
"check:privacy-copy": "node scripts/gates/check-privacy-copy.js",
"check:security-headers": "node scripts/gates/check-security-headers-config.js",
Expand Down Expand Up @@ -147,6 +151,7 @@
"jq-wasm": "^1.1.0-jq-1.8.1",
"js-beautify": "^1.15.4",
"jsbarcode": "^3.12.3",
"jsqr": "^1.4.0",
"jwt-decode": "^4.0.0",
"lorem-ipsum": "^2.0.8",
"lucide-react": "^0.575.0",
Expand Down
144 changes: 144 additions & 0 deletions public/_redirects
Original file line number Diff line number Diff line change
@@ -1,5 +1,142 @@
/security.txt /.well-known/security.txt 301
/en / 301
/json-formatter /en/json-formatter 301
/xml-formatter /en/xml-formatter 301
/sql-formatter /en/sql-formatter 301
/javascript-formatter /en/javascript-formatter 301
/javascript-minifier /en/javascript-minifier 301
/html-minifier /en/html-minifier 301
/html-encoder-decoder /en/html-encoder-decoder 301
/html-css-beautifier /en/html-css-beautifier 301
/html-formatter /en/html-formatter 301
/yaml-json-converter /en/yaml-json-converter 301
/markdown-preview /en/markdown-preview 301
/html-to-markdown /en/html-to-markdown 301
/json-to-typescript /en/json-to-typescript 301
/css-minifier /en/css-minifier 301
/svg-optimizer /en/svg-optimizer 301
/jsonpath-playground /en/jsonpath-playground 301
/openapi-viewer /en/openapi-viewer 301
/json-diff-viewer /en/json-diff-viewer 301
/csv-json-converter /en/csv-json-converter 301
/base64-encode-decode /en/base64-encode-decode 301
/base-encoding-converter /en/base-encoding-converter 301
/url-encode-decode /en/url-encode-decode 301
/jwt-decoder /en/jwt-decoder 301
/jwt-workbench /en/jwt-workbench 301
/hash-generator /en/hash-generator 301
/md5-generator /en/md5-generator 301
/text-diff-checker /en/text-diff-checker 301
/multiple-whitespace-remover /en/multiple-whitespace-remover 301
/letter-counter /en/letter-counter 301
/bionic-reading-converter /en/bionic-reading-converter 301
/google-fonts-pair-finder /en/google-fonts-pair-finder 301
/text-to-handwriting-converter /en/text-to-handwriting-converter 301
/code-to-image-converter /en/code-to-image-converter 301
/image-base64 /en/image-base64 301
/unix-timestamp /en/unix-timestamp 301
/uuid-generator /en/uuid-generator 301
/lorem-ipsum /en/lorem-ipsum 301
/password-generator /en/password-generator 301
/color-converter /en/color-converter 301
/react-native-shadow-generator /en/react-native-shadow-generator 301
/ai-color-palette-generator /en/ai-color-palette-generator 301
/color-mixer /en/color-mixer 301
/color-shades-generator /en/color-shades-generator 301
/image-average-color-finder /en/image-average-color-finder 301
/image-caption-generator /en/image-caption-generator 301
/image-color-extractor /en/image-color-extractor 301
/image-color-picker /en/image-color-picker 301
/image-cropper /en/image-cropper 301
/image-filters /en/image-filters 301
/instagram-filters /en/instagram-filters 301
/instagram-post-generator /en/instagram-post-generator 301
/instagram-story-generator /en/instagram-story-generator 301
/open-graph-meta-generator /en/open-graph-meta-generator 301
/tweet-generator /en/tweet-generator 301
/tweet-to-image-converter /en/tweet-to-image-converter 301
/twitter-ad-revenue-generator /en/twitter-ad-revenue-generator 301
/instagram-photo-downloader /en/instagram-photo-downloader 301
/vimeo-thumbnail-grabber /en/vimeo-thumbnail-grabber 301
/youtube-thumbnail-grabber /en/youtube-thumbnail-grabber 301
/image-resizer /en/image-resizer 301
/photo-censor /en/photo-censor 301
/scanned-pdf-converter /en/scanned-pdf-converter 301
/svg-blob-generator /en/svg-blob-generator 301
/svg-pattern-generator /en/svg-pattern-generator 301
/svg-stroke-to-fill-converter /en/svg-stroke-to-fill-converter 301
/svg-to-png-converter /en/svg-to-png-converter 301
/css-background-pattern-generator /en/css-background-pattern-generator 301
/css-border-radius-generator /en/css-border-radius-generator 301
/css-box-shadow-generator /en/css-box-shadow-generator 301
/css-checkbox-generator /en/css-checkbox-generator 301
/css-clip-path-generator /en/css-clip-path-generator 301
/css-cubic-bezier-generator /en/css-cubic-bezier-generator 301
/css-glassmorphism-generator /en/css-glassmorphism-generator 301
/css-gradient-generator /en/css-gradient-generator 301
/css-loader-generator /en/css-loader-generator 301
/css-switch-generator /en/css-switch-generator 301
/css-text-glitch-effect-generator /en/css-text-glitch-effect-generator 301
/css-triangle-generator /en/css-triangle-generator 301
/qr-code-generator /en/qr-code-generator 301
/barcode-generator /en/barcode-generator 301
/fake-iban-generator /en/fake-iban-generator 301
/list-randomizer /en/list-randomizer 301
/ascii-art-generator /en/ascii-art-generator 301
/env-parser /en/env-parser 301
/id-generator /en/id-generator 301
/regex-tester /en/regex-tester 301
/regex-generator /en/regex-generator 301
/crontab-generator /en/crontab-generator 301
/user-agent-parser /en/user-agent-parser 301
/cron-visualizer /en/cron-visualizer 301
/http-status-codes /en/http-status-codes 301
/chmod-calculator /en/chmod-calculator 301
/cidr-subnet-calculator /en/cidr-subnet-calculator 301
/url-parser /en/url-parser 301
/certificate-decoder /en/certificate-decoder 301
/http-request-builder /en/http-request-builder 301
/curl-to-code /en/curl-to-code 301
/ndjson-formatter /en/ndjson-formatter 301
/jwt-verifier /en/jwt-verifier 301
/slugify-case-converter /en/slugify-case-converter 301
/invisible-characters-detector /en/invisible-characters-detector 301
/robots-txt-tester /en/robots-txt-tester 301
/csp-parser /en/csp-parser 301
/csv-diff /en/csv-diff 301
/header-diff /en/header-diff 301
/security-header-analyzer /en/security-header-analyzer 301
/totp-generator /en/totp-generator 301
/openapi-mock /en/openapi-mock 301
/docker-run-to-compose /en/docker-run-to-compose 301
/local-log-parser /en/local-log-parser 301
/jq-playground /en/jq-playground 301
/log-scrubber /en/log-scrubber 301
/gzip-brotli-lab /en/gzip-brotli-lab 301
/yaml-merge-patch-explorer /en/yaml-merge-patch-explorer 301
/yq-playground /en/yq-playground 301
/structured-data-visualizer /en/structured-data-visualizer 301
/har-viewer-sanitizer /en/har-viewer-sanitizer 301
/pipeline-builder /en/pipeline-builder 301
/saml-decoder /en/saml-decoder 301
/asn1-der-inspector /en/asn1-der-inspector 301
/hex-bytes-workbench /en/hex-bytes-workbench 301
/unicode-inspector /en/unicode-inspector 301
/public-key-jwk-helper /en/public-key-jwk-helper 301
/json-schema-workbench /en/json-schema-workbench 301
/openapi-diff /en/openapi-diff 301
/graphql-workbench /en/graphql-workbench 301
/messagepack-inspector /en/messagepack-inspector 301
/seo-metadata-workbench /en/seo-metadata-workbench 301
/devops-yaml-validator /en/devops-yaml-validator 301
/oauth-jwks-workbench /en/oauth-jwks-workbench 301
/image-privacy-workbench /en/image-privacy-workbench 301
/cron-expression-generator /en/crontab-generator 301
/tls-chain-inspector /en/certificate-decoder 301
/csv-to-json /en/csv-json-converter 301
/web-api /en/web-api-network 301
/design-media /en/images-svg-css 301
/convert-encode /en/all-tools 301
/en/cron-expression-generator /en/crontab-generator 301
/zh-CN/cron-expression-generator /zh-CN/crontab-generator 301
/zh-TW/cron-expression-generator /zh-TW/crontab-generator 301
Expand All @@ -14,6 +151,13 @@
/ko/tls-chain-inspector /ko/certificate-decoder 301
/de/tls-chain-inspector /de/certificate-decoder 301
/fr/tls-chain-inspector /fr/certificate-decoder 301
/en/csv-to-json /en/csv-json-converter 301
/zh-CN/csv-to-json /zh-CN/csv-json-converter 301
/zh-TW/csv-to-json /zh-TW/csv-json-converter 301
/ja/csv-to-json /ja/csv-json-converter 301
/ko/csv-to-json /ko/csv-json-converter 301
/de/csv-to-json /de/csv-json-converter 301
/fr/csv-to-json /fr/csv-json-converter 301
/en/web-api /en/web-api-network 301
/zh-CN/web-api /zh-CN/web-api-network 301
/zh-TW/web-api /zh-TW/web-api-network 301
Expand Down
19 changes: 15 additions & 4 deletions public/runtime/theme-manifest-bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,25 @@
var activeLang = locales.indexOf(seg) >= 0 ? seg : "en";
document.documentElement.setAttribute("lang", activeLang);

var t = localStorage.getItem("theme");
var t = null;
try {
t = localStorage.getItem("theme");
} catch {}
if (t !== "light" && t !== "dark" && t !== "system") t = null;
if (!t) {
var m = document.cookie.match(/(?:^|;\s*)theme=([^;]*)/);
t = m ? m[1] : null;
try {
var m = document.cookie.match(/(?:^|;\s*)theme=([^;]*)/);
t = m ? m[1] : null;
} catch {}
}
if (t !== "light" && t !== "dark" && t !== "system") t = null;
if (!t) t = "dark";
if (t === "system") {
t = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
try {
t = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
} catch {
t = "dark";
}
}
document.documentElement.classList.remove("light", "dark");
document.documentElement.classList.add(t);
Expand Down
Loading