@usequeek/theme-check 0.3.3 → 0.3.6
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/dist/rules/static.js
CHANGED
|
@@ -7,6 +7,10 @@ import { copyViolations, isTestimonialSection } from '../utils/template-copy.js'
|
|
|
7
7
|
import { BUSINESS_KEYS, SERVICE_SLUGS, isBusinessKey } from '../utils/business-vocabulary.js';
|
|
8
8
|
import { themeSourceFiles } from '../context.js';
|
|
9
9
|
import { finding } from '../types.js';
|
|
10
|
+
/** A theme file as a finding names it: relative to the theme, with `/` on every OS (Windows gave `styles\type.css`). */
|
|
11
|
+
function themePath(context, path) {
|
|
12
|
+
return relative(context.dir, path).replace(/\\/g, '/');
|
|
13
|
+
}
|
|
10
14
|
const REQUIRED_FILES = [
|
|
11
15
|
'index.ts', 'manifest.ts', 'theme.config.ts',
|
|
12
16
|
'layout.tsx', 'header.tsx', 'footer.tsx',
|
|
@@ -250,7 +254,7 @@ export const codeQualityRule = {
|
|
|
250
254
|
// mention in a docblock, and three themes do.
|
|
251
255
|
if (path.endsWith('.tsx') && /<img[\s>]/.test(stripComments(source))) {
|
|
252
256
|
findings.push(finding(context, 'theme/code-quality', 'reject', {
|
|
253
|
-
where:
|
|
257
|
+
where: themePath(context, path),
|
|
254
258
|
found: 'renders a raw <img>',
|
|
255
259
|
fix: "Use <Image /> from @usequeek/theme-kit/components/image. It carries the broken-image fallback, the Smart Placeholder for empty slots, and the srcset the backend ships as image_variants — a raw <img> silently gives up all three.",
|
|
256
260
|
docs: `${context.env.docs}#what-themes-must-not-do`,
|
|
@@ -259,7 +263,7 @@ export const codeQualityRule = {
|
|
|
259
263
|
const match = source.match(/from '(?:@\/)?themes\/(?!.*\/)?([\w-]+)/);
|
|
260
264
|
if (match && match[1] !== context.slug) {
|
|
261
265
|
findings.push(finding(context, 'theme/code-quality', 'reject', {
|
|
262
|
-
where:
|
|
266
|
+
where: themePath(context, path),
|
|
263
267
|
found: `imports from the "${match[1]}" theme`,
|
|
264
268
|
fix: 'A theme is self-contained. Copy what you need into your own folder, or ask for it to be promoted into @usequeek/theme-kit if every theme needs it.',
|
|
265
269
|
docs: `${context.env.docs}#what-themes-must-not-do`,
|
|
@@ -286,7 +290,7 @@ export const sdkBoundaryRule = {
|
|
|
286
290
|
const findings = [];
|
|
287
291
|
for (const path of themeSourceFiles(context.dir)) {
|
|
288
292
|
const source = readFileSync(path, 'utf8');
|
|
289
|
-
const where =
|
|
293
|
+
const where = themePath(context, path);
|
|
290
294
|
if (/from '@queekai\/client-sdk'|from '@\/lib\/core\/sdk\//.test(source)) {
|
|
291
295
|
findings.push(finding(context, 'theme/core-boundary', 'reject', {
|
|
292
296
|
where,
|
|
@@ -1138,7 +1142,7 @@ export const vendorFactsRule = {
|
|
|
1138
1142
|
for (const path of themeSourceFiles(context.dir)) {
|
|
1139
1143
|
for (const { fact, words } of vendorFactFallbacks(readFileSync(path, 'utf8'))) {
|
|
1140
1144
|
findings.push(finding(context, 'theme/vendor-facts', 'reject', {
|
|
1141
|
-
where:
|
|
1145
|
+
where: themePath(context, path),
|
|
1142
1146
|
found: `vendor.${fact} falls back to "${words}"`,
|
|
1143
1147
|
fix: `A store with no ${fact} would show these words as its own. Render nothing when it is empty (\`vendor.${fact} ?? ''\`, or leave the element out).`,
|
|
1144
1148
|
docs: `${context.env.docs}#component-rules`,
|
|
@@ -1168,7 +1172,7 @@ export const fontsSelfHostedRule = {
|
|
|
1168
1172
|
const source = stripComments(readFileSync(path, 'utf8'));
|
|
1169
1173
|
if (/from\s+['"]next\/font\/google['"]/.test(source)) {
|
|
1170
1174
|
findings.push(finding(context, 'theme/fonts-self-hosted', 'reject', {
|
|
1171
|
-
where:
|
|
1175
|
+
where: themePath(context, path),
|
|
1172
1176
|
found: 'imports next/font/google',
|
|
1173
1177
|
fix,
|
|
1174
1178
|
docs: `${context.env.docs}#fonts`,
|
|
@@ -1179,7 +1183,7 @@ export const fontsSelfHostedRule = {
|
|
|
1179
1183
|
const css = readFileSync(path, 'utf8').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
1180
1184
|
if (/@import\s+(?:url\()?['"]?https?:\/\/fonts\.googleapis\.com/.test(css)) {
|
|
1181
1185
|
findings.push(finding(context, 'theme/fonts-self-hosted', 'reject', {
|
|
1182
|
-
where:
|
|
1186
|
+
where: themePath(context, path),
|
|
1183
1187
|
found: 'loads a font with @import from fonts.googleapis.com',
|
|
1184
1188
|
fix: `Either the bundler drops it (it only survives as the very first rule of the compiled stylesheet), so the font never loads — atelier, deluxr and lumiere shipped that way until 24/9/26 — or it survives and every page load waits on an extra render-blocking request to Google before the text can paint. ${fix}`,
|
|
1185
1189
|
docs: `${context.env.docs}#fonts`,
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"foods", "local-meals", "shawarma-pizza-snacks", "suya", "boli", "fruits-fresh-natural",
|
|
5
5
|
"meat-fish", "supermarket", "groceries", "shop-groceries", "local-market", "pharmacy",
|
|
6
6
|
"health-wellness-store", "fashion", "beauty-cosmetics", "electronics", "phones-accessories",
|
|
7
|
-
"home-living", "baby-kids", "office-school", "shop", "laundry", "gas-refill", "home-cleaning",
|
|
7
|
+
"home-living", "baby-kids", "office-school", "shop", "shop-4-me", "laundry", "gas-refill", "home-cleaning",
|
|
8
8
|
"car-wash"
|
|
9
9
|
],
|
|
10
10
|
"catalogue": {
|