Skip to content

Commit 57e3c01

Browse files
author
Callin Mullaney
committed
feat: refine Emulsify Core config templates
1 parent 48ac9b1 commit 57e3c01

14 files changed

Lines changed: 344 additions & 139 deletions

.github/scripts/release-check.cjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,18 +607,22 @@ function runStaticChecks() {
607607
});
608608

609609
runStaticCheck('Starterkit generation', () => {
610-
for (const requiredIgnore of ['/project.emulsify.json', '/whisk.info.emulsify.yml', '/whisk.starterkit.yml']) {
610+
for (const requiredIgnore of ['/whisk.info.emulsify.yml', '/whisk.starterkit.yml']) {
611611
ensure(whiskStarterkit.includes(requiredIgnore), `whisk.starterkit.yml should ignore ${requiredIgnore}.`);
612612
}
613+
ensure(!whiskStarterkit.includes('/project.emulsify.json'), 'whisk.starterkit.yml should copy project.emulsify.json into generated themes.');
613614
for (const requiredNoEdit of ['/config/emulsify-core/**', '/screenshot.png']) {
614615
ensure(yamlTopLevelListContains(whiskStarterkit, 'no_edit', requiredNoEdit), `whisk.starterkit.yml should not edit ${requiredNoEdit}.`);
615616
}
616617
ensure(yamlTopLevelListContains(whiskStarterkit, 'no_rename', '/config/emulsify-core/**'), 'whisk.starterkit.yml should not rename Emulsify Core config files.');
617618
ensure(whiskStarterkit.includes(`core_version_requirement: '${coreConstraint}'`), 'whisk.starterkit.yml should align generated theme core compatibility with composer.json.');
618619
ensure(/^\s*hidden:\s+null\s*$/m.test(whiskStarterkit), 'whisk.starterkit.yml should expose hidden: null in the starterkit info overrides.');
619-
for (const starterOnlyFile of ['project.emulsify.json', 'whisk.starterkit.yml', 'whisk.info.emulsify.yml']) {
620+
for (const starterOnlyFile of ['whisk.starterkit.yml', 'whisk.info.emulsify.yml']) {
620621
ensure(starterkitSmoke.includes(starterOnlyFile), `starterkit-smoke.sh should assert ${starterOnlyFile} is not retained.`);
621622
}
623+
ensure(starterkitSmoke.includes('assert_existing_file "project.emulsify.json"'), 'starterkit-smoke.sh should require project.emulsify.json in generated themes.');
624+
ensure(starterkitSmoke.includes('"platform": "drupal"'), 'starterkit-smoke.sh should assert the generated Emulsify project uses the Drupal platform adapter.');
625+
ensure(starterkitSmoke.includes('"singleDirectoryComponents": true'), 'starterkit-smoke.sh should assert generated theme SDC behavior.');
622626
ensure(starterkitSmoke.includes('npm run build'), 'starterkit-smoke.sh should verify the generated theme Vite-based build workflow.');
623627
ensure(starterkitSmoke.includes('EMULSIFY_STARTERKIT_STORYBOOK_BUILD'), 'starterkit-smoke.sh should expose release-only Storybook build coverage.');
624628
ensure(starterkitSmoke.includes('generated-theme-info.yml'), 'starterkit-smoke.sh should copy generated theme info into smoke artifacts.');

.github/scripts/starterkit-smoke.sh

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ assert_missing_file() {
5959
fi
6060
}
6161

62+
assert_existing_file() {
63+
local relative_path="$1"
64+
65+
if [ ! -f "${generated_theme_dir}/${relative_path}" ]; then
66+
fail "Starterkit output should include ${relative_path}."
67+
fi
68+
}
69+
6270
assert_missing_glob() {
6371
local glob_pattern="$1"
6472

@@ -87,14 +95,26 @@ if grep -Eq '^hidden:[[:space:]]*true[[:space:]]*$' "$generated_theme_info"; the
8795
fail "Generated theme should not remain hidden."
8896
fi
8997

90-
assert_missing_file "project.emulsify.json"
98+
assert_existing_file "project.emulsify.json"
9199
assert_missing_file "whisk.starterkit.yml"
92100
assert_missing_file "whisk.info.emulsify.yml"
93101
assert_missing_file "${generated_theme}.starterkit.yml"
94102
assert_missing_file "${generated_theme}.info.emulsify.yml"
95103
assert_missing_glob "*.starterkit.yml"
96104
assert_missing_glob "*.info.emulsify.yml"
97105

106+
if ! grep -q '"platform": "drupal"' "${generated_theme_dir}/project.emulsify.json"; then
107+
fail "Generated theme project.emulsify.json must preserve the Drupal platform adapter."
108+
fi
109+
110+
if ! grep -q '"singleDirectoryComponents": true' "${generated_theme_dir}/project.emulsify.json"; then
111+
fail "Generated theme project.emulsify.json must preserve SDC behavior."
112+
fi
113+
114+
if ! grep -q "\"machineName\": \"${generated_theme}\"" "${generated_theme_dir}/project.emulsify.json"; then
115+
fail "Generated theme project.emulsify.json must use the generated theme machine name."
116+
fi
117+
98118
(
99119
cd "$fixture_dir"
100120
./vendor/bin/drush theme:enable "$generated_theme" -y

whisk/config/emulsify-core/a11y.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,15 @@ module.exports = {
44
// should be ignored. These codes and descriptions allow for those
55
// errors to be targeted specifically.
66
ignore: {
7+
// Example:
8+
// codes: ['WCAG2AA.Principle1.Guideline1_4.1_4_3.G18.Fail'],
79
codes: [],
10+
// Example:
11+
// descriptions: ['This color pair is supplied by third-party content.'],
812
descriptions: [],
913
},
1014
// List of storybook component IDs defined and used in this project.
15+
// Example:
16+
// components: ['components-button--default', 'components-card--default'],
1117
components: [],
1218
};
Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
import { defineConfig } from "eslint/config";
2-
import {default as emulsifyCoreConfig} from "../../node_modules/@emulsify/core/config/eslint.config.js";
1+
import { defineConfig } from 'eslint/config';
2+
import emulsifyCoreConfig from '../../node_modules/@emulsify/core/config/eslint.config.js';
33

4-
export default defineConfig(
5-
6-
// apply an array config to a subset of files
7-
{
8-
files: ["../../src/**/*.js"],
9-
extends: [emulsifyCoreConfig]
10-
},
11-
12-
// your modifications
13-
{
14-
rules: {
15-
"no-unused-vars": "warn"
16-
}
17-
}
18-
);
4+
// Extend Emulsify Core's shared flat ESLint config by adding project-specific
5+
// config objects after the spread below.
6+
//
7+
// Example:
8+
// {
9+
// files: ['src/**/*.js', 'components/**/*.js'],
10+
// rules: {
11+
// 'no-unused-vars': 'warn',
12+
// },
13+
// },
14+
export default defineConfig([...emulsifyCoreConfig]);
Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,68 @@
1-
// Pass an empty configOverrides by default.
1+
// This file is loaded by Emulsify Core's shared Storybook main config.
2+
//
3+
// Keep the default export as an object. Emulsify Core shallow-merges this object
4+
// into its default Storybook config. Addons are handled specially: project
5+
// addons are appended to Emulsify Core's defaults unless replaceAddons is true.
6+
//
7+
// This file is for Node-side Storybook configuration, such as:
8+
// - addons
9+
// - static asset directories
10+
// - final Storybook config patches
11+
//
12+
// Browser-side story parameters belong in preview.js.
13+
// Storybook manager branding belongs in theme.js.
14+
15+
// Pass empty config overrides by default so generated themes inherit Emulsify
16+
// Core's stories, framework, Vite builder, Twig handling, and default addons.
217
const configOverrides = {};
318

4-
// Uncomment the following section to override the default Emulsify Core configuration.
5-
// Doing so is a complete override so no configuration from Emulsify Core's main.js will be inherited.
6-
// See https://storybook.js.org/docs/7/configure for details.
19+
// Example: add a project-specific addon and static directory.
20+
//
21+
// Install the addon in the generated theme first:
22+
// npm install --save-dev @storybook/addon-viewport
23+
//
24+
// const configOverrides = {
25+
// addons: ['@storybook/addon-viewport'],
26+
// staticDirs: ['public'],
27+
// };
28+
29+
// Example: customize an Emulsify Core default addon without duplicating it.
30+
//
731
// const configOverrides = {
8-
// stories: [
9-
// '../../../../components/**/*.stories.@(js|jsx|ts|tsx)',
10-
// ],
1132
// addons: [
12-
// '../../../@storybook/addon-a11y',
13-
// '../../../@storybook/addon-links',
14-
// '../../../@storybook/addon-essentials',
15-
// '../../../@storybook/addon-themes'
33+
// {
34+
// name: '@storybook/addon-a11y',
35+
// options: {
36+
// manual: true,
37+
// },
38+
// },
1639
// ],
17-
// core: {
18-
// builder: 'vite',
19-
// },
20-
// framework: {
21-
// name: '@storybook/react-vite',
22-
// options: {},
23-
// },
24-
// docs: {
25-
// autodocs: true,
26-
// },
2740
// };
2841

29-
export default configOverrides;
42+
// Example: replace the full addon list instead of appending to Core defaults.
43+
// Use this only when the project intentionally opts out of Emulsify defaults.
44+
//
45+
// export const replaceAddons = true;
46+
//
47+
// const configOverrides = {
48+
// addons: ['@storybook/addon-viewport'],
49+
// };
50+
51+
// Example: patch the final Storybook config after Emulsify Core applies the
52+
// default export above. The env object is the normalized project.emulsify.json
53+
// model resolved by Emulsify Core.
54+
//
55+
// export function extendConfig(config, { env }) {
56+
// return {
57+
// ...config,
58+
// staticDirs:
59+
// env.platform === 'drupal'
60+
// ? [...(config.staticDirs || []), 'storybook-static-assets']
61+
// : config.staticDirs,
62+
// };
63+
// }
64+
65+
// Avoid redefining stories, framework, core.builder, or viteFinal unless the
66+
// project is intentionally replacing Emulsify Core's Storybook integration.
67+
68+
export default configOverrides;
Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,39 @@
1-
<!-- Add scripts or css files to render for the entire storybook instance outside the preview window. -->
1+
<!--
2+
This file is appended to Storybook's manager document <head>.
3+
4+
Use it for Storybook UI chrome only: sidebar, toolbar, addon panels, manager
5+
fonts, analytics for the documentation UI, or CSS variables consumed by
6+
theme.js. Markup here does not run inside the story preview iframe.
7+
-->
8+
9+
<!-- Example: load a manager-only font used by theme.js. -->
10+
<!--
11+
<link rel="preconnect" href="https://fonts.example.com" />
12+
<link
13+
rel="stylesheet"
14+
href="https://fonts.example.com/css2?family=Example+Sans:wght@400;600;700&display=swap"
15+
/>
16+
-->
17+
18+
<!-- Example: make small Storybook chrome adjustments. -->
19+
<!--
20+
<style>
21+
:root {
22+
--project-storybook-focus: #FCB817;
23+
}
24+
25+
.sidebar-container a:focus-visible {
26+
outline: 2px solid var(--project-storybook-focus);
27+
outline-offset: 2px;
28+
}
29+
</style>
30+
-->
31+
32+
<!-- Example: add a manager-only script. Avoid scripts that stories depend on. -->
33+
<!--
34+
<script>
35+
window.projectStorybookManager = {
36+
environment: 'local',
37+
};
38+
</script>
39+
-->
Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,37 @@
1-
<!-- Add scripts or css files to render for every stories.js file within the preview window. -->
1+
<!--
2+
This file is appended to Storybook's preview iframe <head>.
3+
4+
Use it for browser assets that rendered stories need: fonts, meta tags,
5+
third-party scripts, or CSS expected by Twig/React components. Storybook UI
6+
chrome belongs in manager-head.html instead.
7+
-->
8+
9+
<!-- Example: add viewport or rendering metadata for stories. -->
10+
<!--
11+
<meta name="theme-color" content="#00405B" />
12+
-->
13+
14+
<!-- Example: load a font used by project components. -->
15+
<!--
16+
<link rel="preconnect" href="https://fonts.example.com" />
17+
<link
18+
rel="stylesheet"
19+
href="https://fonts.example.com/css2?family=Example+Serif:wght@400;700&display=swap"
20+
/>
21+
-->
22+
23+
<!-- Example: expose small preview-only CSS variables to every story. -->
24+
<!--
25+
<style>
26+
:root {
27+
--project-color-primary: #00405B;
28+
--project-color-accent: #FCB817;
29+
}
30+
</style>
31+
-->
32+
33+
<!-- Example: load a script required by rendered components. Prefer npm imports
34+
from preview.js when the script is bundled with the project. -->
35+
<!--
36+
<script src="https://cdn.example.com/component-runtime.js" defer></script>
37+
-->
Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
1-
// export project specific parameters as config overrides.
1+
// This file is loaded in Storybook's browser preview iframe through Vite.
2+
//
3+
// Use it for Storybook preview parameters and browser-side imports that stories
4+
// need, such as global CSS. Emulsify Core keeps its default a11y parameters and
5+
// merges this project's parameter overrides into them.
6+
//
27
// See https://storybook.js.org/docs/writing-stories/parameters#story-parameters.
3-
const overrideParams = {};
48

5-
export default overrideParams;
9+
// Example: load project CSS into every story.
10+
//
11+
// import '../../../src/global/storybook.css';
12+
13+
// Example: override selected Storybook parameters.
14+
//
15+
// export const parameters = {
16+
// layout: 'fullscreen',
17+
// backgrounds: {
18+
// default: 'light',
19+
// values: [
20+
// { name: 'light', value: '#ffffff' },
21+
// { name: 'dark', value: '#00202E' },
22+
// ],
23+
// },
24+
// controls: {
25+
// expanded: true,
26+
// matchers: {
27+
// color: /(background|color)$/i,
28+
// date: /Date$/i,
29+
// },
30+
// },
31+
// a11y: {
32+
// config: {
33+
// detailedReport: true,
34+
// },
35+
// },
36+
// };
37+
38+
export const parameters = {};
39+
40+
export default parameters;

0 commit comments

Comments
 (0)