@freeappstore/compliance 0.5.0 → 0.6.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.
Files changed (67) hide show
  1. package/dist/checks/claude-md-slim.d.ts +4 -0
  2. package/dist/checks/claude-md-slim.d.ts.map +1 -0
  3. package/dist/checks/claude-md-slim.js +88 -0
  4. package/dist/checks/claude-md-slim.js.map +1 -0
  5. package/dist/checks/dark-mode.d.ts +1 -1
  6. package/dist/checks/dark-mode.d.ts.map +1 -1
  7. package/dist/checks/dark-mode.js +11 -3
  8. package/dist/checks/dark-mode.js.map +1 -1
  9. package/dist/checks/html-meta.d.ts.map +1 -1
  10. package/dist/checks/html-meta.js +7 -2
  11. package/dist/checks/html-meta.js.map +1 -1
  12. package/dist/checks/license-mit.d.ts.map +1 -1
  13. package/dist/checks/license-mit.js +8 -1
  14. package/dist/checks/license-mit.js.map +1 -1
  15. package/dist/checks/manifest.d.ts +9 -3
  16. package/dist/checks/manifest.d.ts.map +1 -1
  17. package/dist/checks/manifest.js +61 -18
  18. package/dist/checks/manifest.js.map +1 -1
  19. package/dist/checks/no-brand-overrides.d.ts.map +1 -1
  20. package/dist/checks/no-brand-overrides.js +83 -14
  21. package/dist/checks/no-brand-overrides.js.map +1 -1
  22. package/dist/checks/no-env-production.d.ts.map +1 -1
  23. package/dist/checks/no-env-production.js +5 -1
  24. package/dist/checks/no-env-production.js.map +1 -1
  25. package/dist/checks/no-placeholders.d.ts.map +1 -1
  26. package/dist/checks/no-placeholders.js +16 -3
  27. package/dist/checks/no-placeholders.js.map +1 -1
  28. package/dist/checks/no-scroll.js +1 -3
  29. package/dist/checks/no-scroll.js.map +1 -1
  30. package/dist/checks/no-tracking.d.ts.map +1 -1
  31. package/dist/checks/no-tracking.js +68 -16
  32. package/dist/checks/no-tracking.js.map +1 -1
  33. package/dist/checks/pwa-meta.d.ts.map +1 -1
  34. package/dist/checks/pwa-meta.js +6 -2
  35. package/dist/checks/pwa-meta.js.map +1 -1
  36. package/dist/checks/pwa-offline.d.ts +40 -0
  37. package/dist/checks/pwa-offline.d.ts.map +1 -0
  38. package/dist/checks/pwa-offline.js +388 -0
  39. package/dist/checks/pwa-offline.js.map +1 -0
  40. package/dist/checks/store-link.js +1 -1
  41. package/dist/checks/store-link.js.map +1 -1
  42. package/dist/checks/unsafe-vh.d.ts.map +1 -1
  43. package/dist/checks/unsafe-vh.js +18 -6
  44. package/dist/checks/unsafe-vh.js.map +1 -1
  45. package/dist/checks/viewport-support.d.ts +4 -1
  46. package/dist/checks/viewport-support.d.ts.map +1 -1
  47. package/dist/checks/viewport-support.js +29 -19
  48. package/dist/checks/viewport-support.js.map +1 -1
  49. package/dist/index.d.ts +5 -4
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +6 -3
  52. package/dist/index.js.map +1 -1
  53. package/dist/lib/file-source.d.ts.map +1 -1
  54. package/dist/lib/file-source.js +9 -1
  55. package/dist/lib/file-source.js.map +1 -1
  56. package/dist/lib/inline-manifest.d.ts +32 -0
  57. package/dist/lib/inline-manifest.d.ts.map +1 -0
  58. package/dist/lib/inline-manifest.js +109 -0
  59. package/dist/lib/inline-manifest.js.map +1 -0
  60. package/dist/lib/strip.d.ts +60 -0
  61. package/dist/lib/strip.d.ts.map +1 -0
  62. package/dist/lib/strip.js +169 -0
  63. package/dist/lib/strip.js.map +1 -0
  64. package/dist/live/index.d.ts.map +1 -1
  65. package/dist/live/index.js +5 -1
  66. package/dist/live/index.js.map +1 -1
  67. package/package.json +11 -11
@@ -0,0 +1,4 @@
1
+ import type { FileSource } from '../lib/file-source.js';
2
+ import type { CheckResult } from '../types.js';
3
+ export declare function checkClaudeMdSlim(source: FileSource): Promise<CheckResult>;
4
+ //# sourceMappingURL=claude-md-slim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md-slim.d.ts","sourceRoot":"","sources":["../../src/checks/claude-md-slim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAyC/C,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAwDhF"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Per-repo CLAUDE.md is intended to be slim: the H1, a 1-line description,
3
+ * dev/build/deploy commands, and a pointer to SKILLS.md. Anything that
4
+ * belongs in the platform-wide guide (tech stack, brand, deploy mechanism,
5
+ * mobile rules, paths) creates drift surface area and produces stale
6
+ * instructions for AI agents.
7
+ *
8
+ * This check warns (does not fail) when the repo's CLAUDE.md looks
9
+ * boilerplate-heavy. Warn-only so a contributor mid-edit isn't blocked,
10
+ * and so existing repos that haven't been swept yet don't 404 their CI.
11
+ *
12
+ * The SKILLS.md convention section is the source-of-truth for what
13
+ * counts as boilerplate; this check is the enforcement arm.
14
+ */
15
+ const NAME = 'CLAUDE.md is slim (no platform boilerplate)';
16
+ const SKILLS_URL = 'https://raw.githubusercontent.com/freeappstore-online/freeappstore/main/SKILLS.md';
17
+ // Section headers that should NOT appear in a per-repo CLAUDE.md — they
18
+ // belong in SKILLS.md. Match leading-`##` headers, case-insensitive.
19
+ const BOILERPLATE_HEADERS = [
20
+ 'platform: freeappstore',
21
+ 'platform: freegamestore',
22
+ 'tech stack',
23
+ 'brand guidelines',
24
+ 'brand', // bare "## Brand"
25
+ 'rules', // sweeping platform rules; per-repo exceptions can be a "## Notes"
26
+ 'platform docs',
27
+ 'platform docs & publishing',
28
+ 'publishing',
29
+ ];
30
+ // Anything over this many non-blank lines is suspiciously verbose for a
31
+ // slim per-repo file. Tier-3 cases (legitimate per-repo docs like setup
32
+ // instructions, architecture diagrams) can grow naturally; this is a
33
+ // warning, not a hard cap.
34
+ const SOFT_LINE_LIMIT = 60;
35
+ export async function checkClaudeMdSlim(source) {
36
+ const body = await source.read('CLAUDE.md');
37
+ if (body == null) {
38
+ // No CLAUDE.md is fine — agents fall back to SKILLS.md via README/docs.
39
+ return { name: NAME, status: 'pass', detail: 'no CLAUDE.md present' };
40
+ }
41
+ const offendingHeaders = [];
42
+ const seen = new Set();
43
+ for (const raw of body.split('\n')) {
44
+ const m = /^#{2,}\s+(.+?)\s*$/.exec(raw);
45
+ if (!m)
46
+ continue;
47
+ const text = m[1].toLowerCase().replace(/:$/, '');
48
+ for (const banned of BOILERPLATE_HEADERS) {
49
+ if (text === banned || text.startsWith(`${banned} `) || text.startsWith(`${banned}:`)) {
50
+ if (!seen.has(banned)) {
51
+ offendingHeaders.push(m[1]);
52
+ seen.add(banned);
53
+ }
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ const nonBlankLines = body.split('\n').filter((l) => l.trim().length > 0).length;
59
+ const hasSkillsUrl = body.includes(SKILLS_URL);
60
+ const issues = [];
61
+ if (offendingHeaders.length > 0) {
62
+ issues.push(`platform-boilerplate sections: ${offendingHeaders.join(', ')}`);
63
+ }
64
+ if (nonBlankLines > SOFT_LINE_LIMIT) {
65
+ issues.push(`${nonBlankLines} non-blank lines (soft limit ${SOFT_LINE_LIMIT})`);
66
+ }
67
+ if (!hasSkillsUrl) {
68
+ issues.push('missing SKILLS.md pointer');
69
+ }
70
+ if (issues.length === 0) {
71
+ return {
72
+ name: NAME,
73
+ status: 'pass',
74
+ detail: `${nonBlankLines} non-blank lines, SKILLS.md referenced, no banned sections`,
75
+ };
76
+ }
77
+ return {
78
+ name: NAME,
79
+ status: 'warn',
80
+ detail: issues.join('; '),
81
+ suggestions: [
82
+ 'Per-repo CLAUDE.md should hold only what is unique to this repo (description, dev/build/deploy, repo-specific setup).',
83
+ 'Anything platform-wide (tech stack, brand, mobile rules, deploy flow) belongs in SKILLS.md instead.',
84
+ `See the "Per-repo CLAUDE.md convention" section of SKILLS.md: ${SKILLS_URL}`,
85
+ ],
86
+ };
87
+ }
88
+ //# sourceMappingURL=claude-md-slim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-md-slim.js","sourceRoot":"","sources":["../../src/checks/claude-md-slim.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@ import type { CheckResult } from '../types.js';
14
14
  *
15
15
  * Games are exempt — game UIs are full-bleed and pick their own
16
16
  * palette, so the system preference rarely applies. Skipped if
17
- * `@freeappstore/games` is detected.
17
+ * `@freegamestore/games` is detected.
18
18
  */
19
19
  export declare function checkDarkMode(source: FileSource): Promise<CheckResult>;
20
20
  //# sourceMappingURL=dark-mode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dark-mode.d.ts","sourceRoot":"","sources":["../../src/checks/dark-mode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA2B5E"}
1
+ {"version":3,"file":"dark-mode.d.ts","sourceRoot":"","sources":["../../src/checks/dark-mode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAmC5E"}
@@ -1,4 +1,5 @@
1
1
  import { isGameProject } from '../lib/project-type.js';
2
+ import { stripCommentsOnly, stripCssComments } from '../lib/strip.js';
2
3
  /**
3
4
  * Apps on FreeAppStore should respect the user's system colour-scheme
4
5
  * preference — dark interfaces are the default for many users on iOS
@@ -13,7 +14,7 @@ import { isGameProject } from '../lib/project-type.js';
13
14
  *
14
15
  * Games are exempt — game UIs are full-bleed and pick their own
15
16
  * palette, so the system preference rarely applies. Skipped if
16
- * `@freeappstore/games` is detected.
17
+ * `@freegamestore/games` is detected.
17
18
  */
18
19
  export async function checkDarkMode(source) {
19
20
  if (await isGameProject(source)) {
@@ -28,9 +29,16 @@ export async function checkDarkMode(source) {
28
29
  continue;
29
30
  if (!/\.(?:css|scss|tsx?|jsx?|html)$/i.test(path))
30
31
  continue;
31
- const content = await source.read(path);
32
- if (!content)
32
+ const raw = await source.read(path);
33
+ if (!raw)
33
34
  continue;
35
+ // Strip comments so a `// We could use prefers-color-scheme` note
36
+ // doesn't false-pass the check. Preserve string contents — the
37
+ // signal might be in a template literal that injects CSS.
38
+ const lower = path.toLowerCase();
39
+ const content = lower.endsWith('.css') || lower.endsWith('.scss')
40
+ ? stripCssComments(raw)
41
+ : stripCommentsOnly(raw);
34
42
  if (/prefers-color-scheme|data-theme|color-scheme\s*:/i.test(content)) {
35
43
  return { name: 'Dark mode support', status: 'pass', detail: `signal in ${path}` };
36
44
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dark-mode.js","sourceRoot":"","sources":["../../src/checks/dark-mode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB;IACpD,IAAI,MAAM,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO;YACL,IAAI,EAAE,mBAAmB;YACzB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,8BAA8B;SACvC,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QAC3C,IAAI,CAAC,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,mDAAmD,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtE,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,IAAI,EAAE,EAAE,CAAC;QACpF,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,wEAAwE;QAChF,WAAW,EAAE;YACX,iFAAiF;YACjF,yFAAyF;SAC1F;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"dark-mode.js","sourceRoot":"","sources":["../../src/checks/dark-mode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAGtE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB;IACpD,IAAI,MAAM,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,OAAO;YACL,IAAI,EAAE,mBAAmB;YACzB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,8BAA8B;SACvC,CAAC;IACJ,CAAC;IAED,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,SAAS;QAC3C,IAAI,CAAC,iCAAiC,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,kEAAkE;QAClE,+DAA+D;QAC/D,0DAA0D;QAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,OAAO,GACX,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC/C,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC;YACvB,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,mDAAmD,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACtE,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,IAAI,EAAE,EAAE,CAAC;QACpF,CAAC;IACH,CAAC;IACD,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,wEAAwE;QAChF,WAAW,EAAE;YACX,iFAAiF;YACjF,yFAAyF;SAC1F;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"html-meta.d.ts","sourceRoot":"","sources":["../../src/checks/html-meta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA8B5E"}
1
+ {"version":3,"file":"html-meta.d.ts","sourceRoot":"","sources":["../../src/checks/html-meta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAkC5E"}
@@ -1,3 +1,4 @@
1
+ import { stripHtmlComments } from '../lib/strip.js';
1
2
  const HTML_PATH = 'web/index.html';
2
3
  /**
3
4
  * Verifies `web/index.html` declares the basics: a `lang` attribute, a
@@ -12,14 +13,18 @@ const HTML_PATH = 'web/index.html';
12
13
  * something they needed.
13
14
  */
14
15
  export async function checkHtmlMeta(source) {
15
- const html = await source.read(HTML_PATH);
16
- if (html === null) {
16
+ const rawHtml = await source.read(HTML_PATH);
17
+ if (rawHtml === null) {
17
18
  return {
18
19
  name: 'HTML meta tags',
19
20
  status: 'fail',
20
21
  detail: `${HTML_PATH} not found`,
21
22
  };
22
23
  }
24
+ // Strip HTML comment bodies before matching — `<!-- <meta name=
25
+ // "viewport" ...> -->` is not a real viewport meta, and a commented-
26
+ // out `<title>` shouldn't count either.
27
+ const html = stripHtmlComments(rawHtml);
23
28
  const missing = [];
24
29
  if (!/<html[^>]*\blang\s*=/i.test(html))
25
30
  missing.push('lang attribute on <html>');
@@ -1 +1 @@
1
- {"version":3,"file":"html-meta.js","sourceRoot":"","sources":["../../src/checks/html-meta.ts"],"names":[],"mappings":"AAGA,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAEnC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB;IACpD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,SAAS,YAAY;SACjC,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAClF,IAAI,CAAC,0CAA0C,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC1F,kEAAkE;IAClE,2EAA2E;IAC3E,yCAAyC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAEnF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;IAC/F,CAAC;IACD,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACxC,WAAW,EAAE;YACX,wJAAwJ;SACzJ;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"html-meta.js","sourceRoot":"","sources":["../../src/checks/html-meta.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGpD,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAEnC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB;IACpD,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO;YACL,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,SAAS,YAAY;SACjC,CAAC;IACJ,CAAC;IACD,gEAAgE;IAChE,qEAAqE;IACrE,wCAAwC;IACxC,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAExC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAClF,IAAI,CAAC,0CAA0C,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC1F,kEAAkE;IAClE,2EAA2E;IAC3E,yCAAyC;IACzC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAEnF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iCAAiC,EAAE,CAAC;IAC/F,CAAC;IACD,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACxC,WAAW,EAAE;YACX,wJAAwJ;SACzJ;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"license-mit.d.ts","sourceRoot":"","sources":["../../src/checks/license-mit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CA0B9E"}
1
+ {"version":3,"file":"license-mit.d.ts","sourceRoot":"","sources":["../../src/checks/license-mit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAiC9E"}
@@ -8,7 +8,14 @@
8
8
  * MIT text starts with "MIT License" but variations exist.
9
9
  */
10
10
  export async function checkLicenseMit(source) {
11
- const candidates = ['LICENSE', 'LICENSE.md', 'LICENSE.txt', 'license', 'license.md', 'license.txt'];
11
+ const candidates = [
12
+ 'LICENSE',
13
+ 'LICENSE.md',
14
+ 'LICENSE.txt',
15
+ 'license',
16
+ 'license.md',
17
+ 'license.txt',
18
+ ];
12
19
  for (const path of candidates) {
13
20
  const content = await source.read(path);
14
21
  if (content === null)
@@ -1 +1 @@
1
- {"version":3,"file":"license-mit.js","sourceRoot":"","sources":["../../src/checks/license-mit.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAkB;IACtD,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC;IACpG,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,IAAI;YAAE,SAAS;QAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,IAAI,kCAAkC;YACjD,WAAW,EAAE;gBACX,4FAA4F;aAC7F;SACF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,8BAA8B;QACtC,WAAW,EAAE;YACX,0FAA0F;YAC1F,wFAAwF;SACzF;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"license-mit.js","sourceRoot":"","sources":["../../src/checks/license-mit.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAkB;IACtD,MAAM,UAAU,GAAG;QACjB,SAAS;QACT,YAAY;QACZ,aAAa;QACb,SAAS;QACT,YAAY;QACZ,aAAa;KACd,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,IAAI;YAAE,SAAS;QAC/B,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC/D,CAAC;QACD,OAAO;YACL,IAAI,EAAE,aAAa;YACnB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,IAAI,kCAAkC;YACjD,WAAW,EAAE;gBACX,4FAA4F;aAC7F;SACF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,8BAA8B;QACtC,WAAW,EAAE;YACX,0FAA0F;YAC1F,wFAAwF;SACzF;KACF,CAAC;AACJ,CAAC"}
@@ -1,9 +1,15 @@
1
1
  import type { FileSource } from '../lib/file-source.js';
2
2
  import type { CheckResult } from '../types.js';
3
3
  /**
4
- * Verifies the PWA manifest exists at the expected location and parses
5
- * to JSON. Apps without a manifest can't be "Add to Home Screen"-d on
6
- * mobile; required by the platform.
4
+ * Verifies the PWA manifest declares the four required fields (name,
5
+ * short_name, start_url, display). Two valid sources, in order:
6
+ *
7
+ * 1. `web/public/manifest.json` — legacy static apps that ship their
8
+ * own manifest file.
9
+ * 2. The `manifest: { ... }` block inside `VitePWA({...})` in
10
+ * `web/vite.config.ts` — the path every game currently uses.
11
+ *
12
+ * Either is fine; both being missing fails.
7
13
  */
8
14
  export declare function checkManifest(source: FileSource): Promise<CheckResult>;
9
15
  //# sourceMappingURL=manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/checks/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI/C;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAoC5E"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/checks/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAK/C;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAoB5E"}
@@ -1,22 +1,37 @@
1
- const MANIFEST_PATH = 'web/public/manifest.json';
1
+ import { extractInlineManifest } from '../lib/inline-manifest.js';
2
+ const STATIC_MANIFEST_PATH = 'web/public/manifest.json';
3
+ const VITE_CONFIG_PATH = 'web/vite.config.ts';
2
4
  /**
3
- * Verifies the PWA manifest exists at the expected location and parses
4
- * to JSON. Apps without a manifest can't be "Add to Home Screen"-d on
5
- * mobile; required by the platform.
5
+ * Verifies the PWA manifest declares the four required fields (name,
6
+ * short_name, start_url, display). Two valid sources, in order:
7
+ *
8
+ * 1. `web/public/manifest.json` — legacy static apps that ship their
9
+ * own manifest file.
10
+ * 2. The `manifest: { ... }` block inside `VitePWA({...})` in
11
+ * `web/vite.config.ts` — the path every game currently uses.
12
+ *
13
+ * Either is fine; both being missing fails.
6
14
  */
7
15
  export async function checkManifest(source) {
8
- const raw = await source.read(MANIFEST_PATH);
9
- if (raw === null) {
10
- return {
11
- name: 'PWA manifest',
12
- status: 'fail',
13
- detail: `${MANIFEST_PATH} missing`,
14
- suggestions: [
15
- 'Add a manifest.json with at least name, short_name, start_url, display, icons.',
16
- 'See template-standalone for a working example.',
17
- ],
18
- };
16
+ const staticRaw = await source.read(STATIC_MANIFEST_PATH);
17
+ if (staticRaw !== null) {
18
+ return validateStaticManifest(staticRaw);
19
19
  }
20
+ const viteConfig = await source.read(VITE_CONFIG_PATH);
21
+ if (viteConfig !== null && /\bVitePWA\s*\(/.test(viteConfig)) {
22
+ return validateInlineManifest(viteConfig);
23
+ }
24
+ return {
25
+ name: 'PWA manifest',
26
+ status: 'fail',
27
+ detail: `no manifest source found (looked for ${STATIC_MANIFEST_PATH} and a VitePWA(...) block in ${VITE_CONFIG_PATH})`,
28
+ suggestions: [
29
+ 'Add a VitePWA(...) plugin to web/vite.config.ts with an inline manifest:{...} block, OR',
30
+ 'Add a static web/public/manifest.json with at least name, short_name, start_url, display, icons.',
31
+ ],
32
+ };
33
+ }
34
+ function validateStaticManifest(raw) {
20
35
  let parsed;
21
36
  try {
22
37
  parsed = JSON.parse(raw);
@@ -25,7 +40,7 @@ export async function checkManifest(source) {
25
40
  return {
26
41
  name: 'PWA manifest',
27
42
  status: 'fail',
28
- detail: `${MANIFEST_PATH} is not valid JSON`,
43
+ detail: `${STATIC_MANIFEST_PATH} is not valid JSON`,
29
44
  };
30
45
  }
31
46
  const required = ['name', 'short_name', 'start_url', 'display'];
@@ -34,10 +49,38 @@ export async function checkManifest(source) {
34
49
  return {
35
50
  name: 'PWA manifest',
36
51
  status: 'warn',
37
- detail: `missing fields: ${missing.join(', ')}`,
52
+ detail: `missing fields in ${STATIC_MANIFEST_PATH}: ${missing.join(', ')}`,
38
53
  suggestions: [`Add the ${missing.join(', ')} field(s) to manifest.json so installs work.`],
39
54
  };
40
55
  }
41
- return { name: 'PWA manifest', status: 'pass', detail: MANIFEST_PATH };
56
+ return { name: 'PWA manifest', status: 'pass', detail: STATIC_MANIFEST_PATH };
57
+ }
58
+ function validateInlineManifest(viteConfig) {
59
+ const inline = extractInlineManifest(viteConfig);
60
+ if (!inline) {
61
+ return {
62
+ name: 'PWA manifest',
63
+ status: 'fail',
64
+ detail: `VitePWA(...) call found in ${VITE_CONFIG_PATH} but the manifest:{...} block could not be parsed`,
65
+ suggestions: [
66
+ 'Add a top-level `manifest: { name, short_name, start_url, display, icons, ... }` to your VitePWA() options.',
67
+ ],
68
+ };
69
+ }
70
+ const required = ['name', 'short_name', 'start_url', 'display'];
71
+ const missing = required.filter((k) => typeof inline[k] !== 'string' || inline[k] === '');
72
+ if (missing.length > 0) {
73
+ return {
74
+ name: 'PWA manifest',
75
+ status: 'warn',
76
+ detail: `missing fields in inline manifest (${VITE_CONFIG_PATH}): ${missing.join(', ')}`,
77
+ suggestions: [`Add ${missing.join(', ')} to the manifest:{...} inside VitePWA({...}).`],
78
+ };
79
+ }
80
+ return {
81
+ name: 'PWA manifest',
82
+ status: 'pass',
83
+ detail: `inline in ${VITE_CONFIG_PATH} (name="${inline.name}", display="${inline.display}")`,
84
+ };
42
85
  }
43
86
  //# sourceMappingURL=manifest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/checks/manifest.ts"],"names":[],"mappings":"AAGA,MAAM,aAAa,GAAG,0BAA0B,CAAC;AAEjD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAkB;IACpD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,aAAa,UAAU;YAClC,WAAW,EAAE;gBACX,gFAAgF;gBAChF,gDAAgD;aACjD;SACF,CAAC;IACJ,CAAC;IAED,IAAI,MAAwF,CAAC;IAC7F,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,aAAa,oBAAoB;SAC7C,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,CAAU,CAAC;IACzE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;IAC1F,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,IAAI,EAAE,cAAc;YACpB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,mBAAmB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC/C,WAAW,EAAE,CAAC,WAAW,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,8CAA8C,CAAC;SAC3F,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;AACzE,CAAC"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/checks/manifest.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-brand-overrides.d.ts","sourceRoot":"","sources":["../../src/checks/no-brand-overrides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAuCpF;AA2DD,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,MAAM,EAAE,CAmCV"}
1
+ {"version":3,"file":"no-brand-overrides.d.ts","sourceRoot":"","sources":["../../src/checks/no-brand-overrides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAgDpF;AA2DD,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACrC,MAAM,EAAE,CAmDV"}
@@ -1,3 +1,4 @@
1
+ import { stripCommentsOnly, stripCssComments } from '../lib/strip.js';
1
2
  /**
2
3
  * Apps and games on the platform must look consistent with the storefront
3
4
  * and with each other — brand colors, fonts, and layout rhythm come from
@@ -22,9 +23,17 @@ export async function checkNoBrandOverrides(source) {
22
23
  const ext = extOf(path);
23
24
  if (!SCANNED_EXTS.has(ext))
24
25
  continue;
25
- const content = await source.read(path);
26
- if (!content)
26
+ const raw = await source.read(path);
27
+ if (!raw)
27
28
  continue;
29
+ // Strip comment bodies so a `// font-family: "Comic Sans"` note
30
+ // doesn't fire. Preserve string-literal contents — the JSX value
31
+ // `fontFamily: "Comic Sans"` IS a string literal and is the thing
32
+ // we're auditing. For .css/.scss use the css-only stripper (no `//`
33
+ // syntax at the language level).
34
+ const content = ext === '.css' || ext === '.scss'
35
+ ? stripCssComments(raw)
36
+ : stripCommentsOnly(raw);
28
37
  // Canonical theme file: the platform's CSS variables ARE defined here.
29
38
  // Apps own this file post-scaffold (they can technically modify token
30
39
  // values, and we accept the imperfection — the loud places where a
@@ -126,24 +135,84 @@ export function scanContent(filename, content, opts = {}) {
126
135
  }
127
136
  }
128
137
  // 2. font-family overrides.
129
- const fontRe = /(?:font-family|fontFamily)\s*[:=]\s*["'`]?([^;"'`}\n]+)["'`]?/g;
138
+ // Capture the value of every font-family / fontFamily declaration, then
139
+ // extract candidate font names. JSX values can be ternaries
140
+ // (`fontFamily: isFoo ? "Fraunces" : "Manrope"`), so we pull out every
141
+ // quoted string in the value and check each one separately. If there are
142
+ // no quoted strings, the value is treated as a CSS-style comma list
143
+ // (`font-family: Comic Sans, serif`).
144
+ const fontHeadRe = /(font-family|fontFamily)\s*[:=]/g;
145
+ const quotedRe = /(['"`])([^'"`\n]+)\1/g;
130
146
  let m;
131
- while ((m = fontRe.exec(content)) !== null) {
132
- const list = m[1];
133
- const tokens = list
134
- .split(',')
135
- .map((t) => t.trim().replace(/^["']|["']$/g, '').toLowerCase())
136
- .filter(Boolean);
137
- for (const t of tokens) {
138
- if (!ALLOWED_FONT_TOKENS.has(t)) {
139
- const line = lineNumberAt(content, m.index);
140
- out.push(`${filename}:${line} non-brand font "${t}"`);
141
- break;
147
+ while ((m = fontHeadRe.exec(content)) !== null) {
148
+ const isJsx = m[1] === 'fontFamily';
149
+ const start = m.index + m[0].length;
150
+ const value = sliceFontValue(content, start, isJsx);
151
+ const quotedStrings = [...value.matchAll(quotedRe)].map((x) => x[2]);
152
+ const candidates = quotedStrings.length > 0 ? quotedStrings : [value];
153
+ let flagged = false;
154
+ for (const cand of candidates) {
155
+ const tokens = cand
156
+ .split(',')
157
+ .map((t) => t.trim().replace(/^["']|["']$/g, '').toLowerCase())
158
+ .filter(Boolean);
159
+ for (const t of tokens) {
160
+ if (!ALLOWED_FONT_TOKENS.has(t)) {
161
+ const line = lineNumberAt(content, m.index);
162
+ out.push(`${filename}:${line} non-brand font "${t}"`);
163
+ flagged = true;
164
+ break;
165
+ }
142
166
  }
167
+ if (flagged)
168
+ break;
143
169
  }
144
170
  }
145
171
  return out;
146
172
  }
173
+ /**
174
+ * Walk forward from `start` until we hit the end of the font-family value.
175
+ *
176
+ * CSS values end at `;` or `}` or newline.
177
+ * JSX values end at `}` or at a `,` followed by another identifier+colon
178
+ * (the next style property). Commas inside quoted strings or before
179
+ * non-identifiers (e.g. font fallbacks) are part of the value.
180
+ */
181
+ function sliceFontValue(content, start, isJsx) {
182
+ let i = start;
183
+ let quote = null;
184
+ while (i < content.length) {
185
+ const c = content[i];
186
+ if (quote) {
187
+ if (c === '\\') {
188
+ i += 2;
189
+ continue;
190
+ }
191
+ if (c === quote)
192
+ quote = null;
193
+ i++;
194
+ continue;
195
+ }
196
+ if (c === '"' || c === "'" || c === '`') {
197
+ quote = c;
198
+ i++;
199
+ continue;
200
+ }
201
+ if (c === '\n' || c === ';' || c === '}')
202
+ break;
203
+ if (isJsx && c === ',') {
204
+ // Lookahead: is this `,` followed by `identifier:`? If yes, end of value.
205
+ let j = i + 1;
206
+ while (j < content.length && (content[j] === ' ' || content[j] === '\t'))
207
+ j++;
208
+ const rest = content.slice(j, j + 64);
209
+ if (/^[A-Za-z_$][\w$]*\s*:/.test(rest))
210
+ break;
211
+ }
212
+ i++;
213
+ }
214
+ return content.slice(start, i);
215
+ }
147
216
  function extOf(path) {
148
217
  const dot = path.lastIndexOf('.');
149
218
  const slash = path.lastIndexOf('/');
@@ -1 +1 @@
1
- {"version":3,"file":"no-brand-overrides.js","sourceRoot":"","sources":["../../src/checks/no-brand-overrides.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"no-brand-overrides.js","sourceRoot":"","sources":["../../src/checks/no-brand-overrides.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-env-production.d.ts","sourceRoot":"","sources":["../../src/checks/no-env-production.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBnF"}
1
+ {"version":3,"file":"no-env-production.d.ts","sourceRoot":"","sources":["../../src/checks/no-env-production.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAsBnF"}
@@ -18,7 +18,11 @@ export async function checkNoEnvProduction(source) {
18
18
  offenders.push(path);
19
19
  }
20
20
  if (offenders.length === 0) {
21
- return { name: 'No .env.production', status: 'pass', detail: 'no production env files committed' };
21
+ return {
22
+ name: 'No .env.production',
23
+ status: 'pass',
24
+ detail: 'no production env files committed',
25
+ };
22
26
  }
23
27
  return {
24
28
  name: 'No .env.production',
@@ -1 +1 @@
1
- {"version":3,"file":"no-env-production.js","sourceRoot":"","sources":["../../src/checks/no-env-production.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAkB;IAC3D,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACzC,IAAI,IAAI,KAAK,iBAAiB;YAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,mCAAmC,EAAE,CAAC;IACrG,CAAC;IACD,OAAO;QACL,IAAI,EAAE,oBAAoB;QAC1B,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,6BAA6B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC9E,WAAW,EAAE;YACX,0DAA0D;YAC1D,yFAAyF;SAC1F;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"no-env-production.js","sourceRoot":"","sources":["../../src/checks/no-env-production.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAkB;IAC3D,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACzC,IAAI,IAAI,KAAK,iBAAiB;YAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO;YACL,IAAI,EAAE,oBAAoB;YAC1B,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,mCAAmC;SAC5C,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,oBAAoB;QAC1B,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,6BAA6B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC9E,WAAW,EAAE;YACX,0DAA0D;YAC1D,yFAAyF;SAC1F;KACF,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"no-placeholders.d.ts","sourceRoot":"","sources":["../../src/checks/no-placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO/C;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAsBlF"}
1
+ {"version":3,"file":"no-placeholders.d.ts","sourceRoot":"","sources":["../../src/checks/no-placeholders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAoB/C;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAsBlF"}
@@ -1,6 +1,19 @@
1
1
  const TEXT_EXTS = new Set([
2
- '.md', '.txt', '.json', '.ts', '.tsx', '.js', '.jsx',
3
- '.html', '.htm', '.css', '.scss', '.yaml', '.yml', '.toml', '.svg',
2
+ '.md',
3
+ '.txt',
4
+ '.json',
5
+ '.ts',
6
+ '.tsx',
7
+ '.js',
8
+ '.jsx',
9
+ '.html',
10
+ '.htm',
11
+ '.css',
12
+ '.scss',
13
+ '.yaml',
14
+ '.yml',
15
+ '.toml',
16
+ '.svg',
4
17
  ]);
5
18
  /**
6
19
  * Catches the case where APPNAME placeholders from the template were
@@ -14,7 +27,7 @@ export async function checkNoPlaceholders(source) {
14
27
  if (!TEXT_EXTS.has(extOf(path)))
15
28
  continue;
16
29
  const content = await source.read(path);
17
- if (content && content.includes('APPNAME')) {
30
+ if (content?.includes('APPNAME')) {
18
31
  offenders.push(path);
19
32
  if (offenders.length >= 5)
20
33
  break; // don't spam, summarize
@@ -1 +1 @@
1
- {"version":3,"file":"no-placeholders.js","sourceRoot":"","sources":["../../src/checks/no-placeholders.ts"],"names":[],"mappings":"AAGA,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IACpD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CACnE,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAkB;IAC1D,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAAE,SAAS;QAC1C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3C,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC;gBAAE,MAAM,CAAC,wBAAwB;QAC5D,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,IAAI,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IACjG,CAAC;IACD,OAAO;QACL,IAAI,EAAE,0BAA0B;QAChC,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,mCAAmC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACpH,WAAW,EAAE;YACX,0FAA0F;YAC1F,mFAAmF;SACpF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,IAAY;IACzB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1D,CAAC"}
1
+ {"version":3,"file":"no-placeholders.js","sourceRoot":"","sources":["../../src/checks/no-placeholders.ts"],"names":[],"mappings":"AAGA,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,KAAK;IACL,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,OAAO;IACP,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,MAAM;IACN,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAkB;IAC1D,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAAE,SAAS;QAC1C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,OAAO,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrB,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC;gBAAE,MAAM,CAAC,wBAAwB;QAC5D,CAAC;IACH,CAAC;IACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,IAAI,EAAE,0BAA0B,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;IACjG,CAAC;IACD,OAAO;QACL,IAAI,EAAE,0BAA0B;QAChC,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,mCAAmC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QACpH,WAAW,EAAE;YACX,0FAA0F;YAC1F,mFAAmF;SACpF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,IAAY;IACzB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,OAAO,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1D,CAAC"}
@@ -92,9 +92,7 @@ const FORBIDDEN_OVERFLOW = [
92
92
  /(?:^|[\s,{])(?:html|body)\s*\{[^}]*overflow\s*:\s*(?:scroll|auto)/im,
93
93
  /(?:^|[\s,{])(?:html|body)\s*\{[^}]*overflow-(?:x|y)\s*:\s*(?:scroll|auto)/im,
94
94
  ];
95
- const FORBIDDEN_MIN_HEIGHT = [
96
- /(?:^|[\s,{])(?:html|body)\s*\{[^}]*min-height\s*:\s*100vh/im,
97
- ];
95
+ const FORBIDDEN_MIN_HEIGHT = [/(?:^|[\s,{])(?:html|body)\s*\{[^}]*min-height\s*:\s*100vh/im];
98
96
  const VIEWPORT_LOCK = /(?:height|max-height)\s*:\s*100(?:s?vh)|GameShell|@freeappstore\/games/i;
99
97
  function extOf(path) {
100
98
  const dot = path.lastIndexOf('.');