{"_id":"@buchsuite/buchsuitethemebuild-package","_rev":"4-2fd3cc719c714b43eea5e3c608a348b7","name":"@buchsuite/buchsuitethemebuild-package","dist-tags":{"latest":"1.1.1"},"versions":{"1.0.0":{"name":"@buchsuite/buchsuitethemebuild-package","version":"1.0.0","keywords":["buchsuite","npm","oxid","theme","build","font-preload"],"author":{"name":"buchsuite.de: Mario Lorenz"},"license":"(MIT OR Apache-2.0)","_id":"@buchsuite/buchsuitethemebuild-package@1.0.0","maintainers":[{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"}],"homepage":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package#readme","bugs":{"url":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package/issues"},"bin":{"theme-build":"bin/theme-build.js"},"dist":{"shasum":"9c1b666c2fec67325a28056b0ca95c14f3b783de","tarball":"https://registry.npmjs.org/@buchsuite/buchsuitethemebuild-package/-/buchsuitethemebuild-package-1.0.0.tgz","fileCount":10,"integrity":"sha512-/NyhsmM4wDS02RtySbi5uBJRtOBHeTfI+d9fbCr08CIo6M9ULoiyWw4QXJmEiC+ZAiSZgQkHfsX600pm/7GxMw==","signatures":[{"sig":"MEQCIBC8mmp480Ojw9bG4nyrkvAT2v/80QihTJdugz1zVy+WAiBpiQUe9WBXehNvONYUa8+ZxntDZC692808iD7N5GLauw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34871},"main":"./src/index.js","type":"module","engines":{"node":">=20"},"exports":{".":"./src/index.js","./context":"./src/theme-context.js","./email-css":"./src/email-css.js","./clean-cache":"./src/clean-cache.js","./font-preload":"./src/font-preload.js","./copy-to-source":"./src/copy-to-source.js","./watch-and-copy":"./src/watch-and-copy.js"},"gitHead":"f1cfa1a46b134b8d78905414c4d93863094abd53","_npmUser":{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"},"repository":{"url":"git+https://bitbucket.org/buchsuite/buchsuitethemebuild-package.git","type":"git"},"_npmVersion":"11.16.0","description":"Shared build steps for the buchsuite OXID themes: deploy to source, template cache, email CSS, font preload generation.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"sass":"^1.83.4","cssnano":"^7.0.6","postcss":"^8.5.1","chokidar":"^3.6.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/buchsuitethemebuild-package_1.0.0_1787141610214_0.2710485465379908","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@buchsuite/buchsuitethemebuild-package","version":"1.0.1","keywords":["buchsuite","npm","oxid","theme","build","font-preload"],"author":{"name":"buchsuite.de: Mario Lorenz"},"license":"(MIT OR Apache-2.0)","_id":"@buchsuite/buchsuitethemebuild-package@1.0.1","maintainers":[{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"}],"homepage":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package#readme","bugs":{"url":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package/issues"},"bin":{"theme-build":"bin/theme-build.js"},"dist":{"shasum":"f03eba68e7e4c8cc1be2e524cddaeb246ead66f1","tarball":"https://registry.npmjs.org/@buchsuite/buchsuitethemebuild-package/-/buchsuitethemebuild-package-1.0.1.tgz","fileCount":10,"integrity":"sha512-spAd1PLpLJFqDPwjLNcd2BeCkeROQCUrRF3tPuvrviS1qpUBzt0m69PkxOacpKGWQqFmOsucz1GFJOCgOsOXwQ==","signatures":[{"sig":"MEUCIQCGQpa6LoFtp4AxxGPlqBf1IXUw8URCBb/cA2hj7qBSfgIgK1moRx7ulNN8k3YfLzE1l9BrJLlUpKTAv5qxyotw34Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34889},"main":"./src/index.js","type":"module","engines":{"node":">=20"},"exports":{".":"./src/index.js","./context":"./src/theme-context.js","./email-css":"./src/email-css.js","./clean-cache":"./src/clean-cache.js","./font-preload":"./src/font-preload.js","./copy-to-source":"./src/copy-to-source.js","./watch-and-copy":"./src/watch-and-copy.js"},"gitHead":"5ed8c44a1b633646d7e194f5fa0cebf92e303693","_npmUser":{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"},"repository":{"url":"git+https://bitbucket.org/buchsuite/buchsuitethemebuild-package.git","type":"git"},"_npmVersion":"11.16.0","description":"Shared build steps for the buchsuite OXID themes: deploy to source, template cache, email CSS, font preload generation.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"sass":"^1.83.4","cssnano":"^7.0.6","postcss":"^8.5.1","chokidar":"^3.6.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/buchsuitethemebuild-package_1.0.1_1787142031831_0.6750340182236292","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@buchsuite/buchsuitethemebuild-package","version":"1.1.0","keywords":["buchsuite","npm","oxid","theme","build","font-preload"],"author":{"name":"buchsuite.de: Mario Lorenz"},"license":"(MIT OR Apache-2.0)","_id":"@buchsuite/buchsuitethemebuild-package@1.1.0","maintainers":[{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"}],"homepage":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package#readme","bugs":{"url":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package/issues"},"bin":{"theme-build":"bin/theme-build.js"},"dist":{"shasum":"a5bf06c775c1b1a43ddfc113f20adec7b36bbadf","tarball":"https://registry.npmjs.org/@buchsuite/buchsuitethemebuild-package/-/buchsuitethemebuild-package-1.1.0.tgz","fileCount":10,"integrity":"sha512-sKLjmY4InTN1HFXxw+iLC0xIIl6xyM+p0WAZwh/gLhMeQx6uDyIUru8ZD/FxwB4pKZTcIZ/hDfHiHpzjBhfloA==","signatures":[{"sig":"MEUCIDbqFPFwfcM/gA6dW3mqkZ1h8m8/B5MbkGegyjBM0S0lAiEA5aMpBYD3YLvL33ElNvVEPIN2yyq6ocKa6s4Kll1kMmo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38084},"main":"./src/index.js","type":"module","engines":{"node":">=20"},"exports":{".":"./src/index.js","./context":"./src/theme-context.js","./email-css":"./src/email-css.js","./clean-cache":"./src/clean-cache.js","./font-preload":"./src/font-preload.js","./copy-to-source":"./src/copy-to-source.js","./watch-and-copy":"./src/watch-and-copy.js"},"gitHead":"5fdfd92fca82caf2bf1b23044c152e518996b131","_npmUser":{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"},"repository":{"url":"git+https://bitbucket.org/buchsuite/buchsuitethemebuild-package.git","type":"git"},"_npmVersion":"11.16.0","description":"Shared build steps for the buchsuite OXID themes: deploy to source, template cache, email CSS, font preload generation.","directories":{},"_nodeVersion":"24.12.0","dependencies":{"sass":"^1.83.4","cssnano":"^7.0.6","postcss":"^8.5.1","chokidar":"^3.6.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/buchsuitethemebuild-package_1.1.0_1787153899793_0.5656492850253614","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@buchsuite/buchsuitethemebuild-package","version":"1.1.1","description":"Shared build steps for the buchsuite OXID themes: deploy to source, template cache, email CSS, font preload generation.","license":"(MIT OR Apache-2.0)","author":{"name":"buchsuite.de: Mario Lorenz"},"repository":{"type":"git","url":"git+https://bitbucket.org/buchsuite/buchsuitethemebuild-package.git"},"keywords":["buchsuite","npm","oxid","theme","build","font-preload"],"publishConfig":{"access":"public"},"type":"module","main":"./src/index.js","exports":{".":"./src/index.js","./package.json":"./package.json","./context":"./src/theme-context.js","./copy-to-source":"./src/copy-to-source.js","./clean-cache":"./src/clean-cache.js","./watch-and-copy":"./src/watch-and-copy.js","./email-css":"./src/email-css.js","./font-preload":"./src/font-preload.js"},"bin":{"theme-build":"bin/theme-build.js"},"engines":{"node":">=20"},"dependencies":{"chokidar":"^3.6.0","cssnano":"^7.0.6","postcss":"^8.5.1","sass":"^1.83.4"},"gitHead":"c2b0a8eb856605a65ea6193f152fa911ac6d9d49","_id":"@buchsuite/buchsuitethemebuild-package@1.1.1","bugs":{"url":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package/issues"},"homepage":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package#readme","_nodeVersion":"24.12.0","_npmVersion":"11.16.0","dist":{"integrity":"sha512-1PMbaLxInZ/uABKMKCOpK1oWvx26o9mE9aLj+iPvx8ClTCX8W0LzFQx2D/ogOm8NlhhKqo4VRO+hyKej/Y/eBg==","shasum":"49d093e3457b41fb0f247f62cd54a78ceb181894","tarball":"https://registry.npmjs.org/@buchsuite/buchsuitethemebuild-package/-/buchsuitethemebuild-package-1.1.1.tgz","fileCount":10,"unpackedSize":38308,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIEMuJLhWwh32BYJLkKCIlk3I1dp1GPPRed2xQ6mDW7SjAiACr6c+k18Hr6Tl14H49N26q6f9tmq5gaey8RvAe3GlnQ=="}]},"_npmUser":{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"},"directories":{},"maintainers":[{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/buchsuitethemebuild-package_1.1.1_1787154524338_0.9881731590915692"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-19T12:13:30.023Z","modified":"2026-08-19T15:48:44.763Z","1.0.0":"2026-08-19T12:13:30.359Z","1.0.1":"2026-08-19T12:20:31.986Z","1.1.0":"2026-08-19T15:38:19.955Z","1.1.1":"2026-08-19T15:48:44.533Z"},"bugs":{"url":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package/issues"},"author":{"name":"buchsuite.de: Mario Lorenz"},"license":"(MIT OR Apache-2.0)","homepage":"https://bitbucket.org/buchsuite/buchsuitethemebuild-package#readme","keywords":["buchsuite","npm","oxid","theme","build","font-preload"],"repository":{"type":"git","url":"git+https://bitbucket.org/buchsuite/buchsuitethemebuild-package.git"},"description":"Shared build steps for the buchsuite OXID themes: deploy to source, template cache, email CSS, font preload generation.","maintainers":[{"name":"buchsuite","email":"mario_lorenz@the-real-world.de"}],"readme":"# @buchsuite/buchsuitethemebuild-package\n\nShared build steps for the buchsuite OXID themes. Each theme keeps its own intent — which fonts,\nwhich variables, which templates — and calls these tasks instead of carrying a copy of them.\n\nThe steps were identical across themes before this package existed: `copy-to-source.js` and\n`clean-cache.js` were byte-for-byte the same in gerstenberg-theme and artemis-theme, differing\nonly in line endings. That is the problem this package removes.\n\n## Install\n\n```bash\nnpm install @buchsuite/buchsuitethemebuild-package\n```\n\n## Use\n\n```json\n{\n  \"scripts\": {\n    \"build\": \"vite build --mode production && npm run build:preload && npm run build:email\",\n    \"build:preload\": \"theme-build font-preload\",\n    \"build:email\": \"theme-build email-css\",\n    \"build:copy\": \"npm run build && npm run copy && npm run clean:cache\",\n    \"copy\": \"theme-build copy\",\n    \"watch\": \"vite build --watch --mode development\",\n    \"watch:copy\": \"theme-build watch\",\n    \"dev\": \"npm run watch & npm run watch:copy\",\n    \"clean:cache\": \"theme-build clean-cache\"\n  },\n  \"config\": {\n    \"theme\": \"gerstenberg\",\n    \"pathToShopSource\": \"./../../../source/\"\n  },\n  \"homepage\": \"https://www.example.com/\"\n}\n```\n\nTasks run from the theme root, which is where npm scripts run by default. Everything else is\nderived from the theme's `package.json`:\n\n| field | used by | meaning |\n|---|---|---|\n| `config.theme` | all | theme name; drives `out/<theme>/src/` and `Application/views/<theme>/` |\n| `config.pathToShopSource` | all | relative path to the shop's `source/` |\n| `homepage` | `email-css` | shop base URL, for rewriting relative asset paths to absolute ones |\n\n## Tasks\n\n| task | what it does |\n|---|---|\n| `theme-build copy` | copies `out/`, `de/`, `en/`, `tpl/` into the shop. Merges, never deletes — clear the target first after renaming outputs |\n| `theme-build clean-cache` | clears `tmp/template_cache`; a deployed template change stays invisible without it |\n| `theme-build watch` | watches `tpl/`, `de/`, `en/` and copies on change (`out/` is Vite's job in watch mode) |\n| `theme-build email-css` | compiles `build/scss/style-email.scss` with dart-sass, rewrites `../fonts` to absolute URLs, minifies with cssnano, writes `tpl/email/html/email.min.css` |\n| `theme-build font-preload` | reads `build/font-preload.config.js`, verifies it against the compiled stylesheet, writes `tpl/layout/_font-preload.html.twig` |\n\nEach task is also importable, for themes that need to compose them:\n\n```js\nimport { copyToSource, buildFontPreload, themeContext } from '@buchsuite/buchsuitethemebuild-package';\n```\n\n## `font-preload`\n\nThe theme declares which faces the first paint needs. Entries name a **face**, never a file: the\nwoff2 files come from npm packages, so a version bump can rename them while the face stays the\nsame.\n\n```js\n// build/font-preload.config.js\nexport default {\n    iconFamilies: ['my-iconset', 'Font Awesome 6 Free'],\n    preload: [\n        {\n            family: 'Yanone Kaffeesatz',\n            weight: 400,\n            style: 'normal',\n            covers: 'A',\n            reason: 'h1–h6; the latin subset carries the ASCII glyphs',\n        },\n    ],\n};\n```\n\n- `covers` picks between subset faces of one family by naming a character the face must carry\n  (matched against its `unicode-range`). Omit it for families with a single face, and for icon\n  fonts, whose glyphs live in the private use area.\n- `iconFamilies` are checked for `font-display: block` across the whole stylesheet, preloaded or\n  not — so FontAwesome stays covered even when it is not in `preload`.\n- `reason` ends up as a comment in the generated fragment. Keep the list short: every entry\n  competes with the stylesheet and the scripts for bandwidth, so measure before adding one.\n\nInclude the fragment in the layout, **before** the stylesheet — that is the whole point, since\notherwise the font request only starts once the CSS has been downloaded, parsed and applied:\n\n```twig\n{% block base_preload_fonts %}\n    {% include \"layout/_font-preload.html.twig\" ignore missing %}\n{% endblock %}\n```\n\n`ignore missing` keeps a theme deployed without a build rendering instead of throwing; the\nmissing preload is caught by the build, an exception there would not be.\n\n### What it verifies\n\nErrors fail the build, warnings only report. An unusable preload is worse than none — it costs a\nrequest and the browser warns about it — while a missing one is invisible.\n\n- the face is still declared in the stylesheet (catches a renamed or dropped font)\n- exactly one face matches; ambiguity must be resolved with `covers`\n- the face has a woff2 source and is same-origin\n- the file the stylesheet references exists on disk\n- the emitted URL resolves to the same path the stylesheet requests, so the file is not fetched\n  twice\n- one preload per file, even when several faces share it\n- `unicode-range` values the browser will drop as invalid\n- faces that shadow each other (same family/weight/style, no effective `unicode-range`)\n- icon families on anything but `font-display: block`\n- a preloaded face with **no metric-matched fallback** — a preload shortens the swap, it does not\n  stop the layout shifting when the font arrives; icon fonts are exempt, nothing can stand in for\n  them\n- a woff2 **larger than 40 KiB**, which usually means it is not subset to the scripts in use\n- **more than 100 KiB preloaded in total**, where the preload starts costing more than it saves\n\n### A different output format\n\n`options.render` takes a function from resolved entries to file content, if a theme needs\nsomething other than OXID Twig link tags:\n\n```js\nimport { buildFontPreload } from '@buchsuite/buchsuitethemebuild-package';\nimport config from '../build/font-preload.config.js';\n\nbuildFontPreload(config, {\n    render: (entries) => entries.map((e) => `<link rel=\"preload\" href=\"/${e.resourcePath}\">`).join('\\n'),\n});\n```\n\n## Not in this package\n\n- **Font fallback metrics** (`size-adjust`, `ascent-override`). The values are per theme and have\n  to be measured; `visual-compare/scripts/inspect-font-metrics.mjs` does that and checks the\n  declared values for drift. The preload build does warn when a preloaded face has none, so the\n  step is hard to forget — but it cannot compute the values for you.\n- **The Zurb Ink variable bridge.** Which theme variable maps onto which Ink variable differs per\n  theme — Bootstrap 4 and 5 do not share names — so the mapping stays in the theme's\n  `style-email.scss`. Only the compile step is shared.\n- **Measurement tooling.** `visual-compare` is already central across projects; duplicating it\n  here would buy nothing.\n","readmeFilename":"README.md"}