Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
0680440
feat: remove storybook-html in favor of storybook-react v9.x
Jun 10, 2025
3d3518f
feat: install vite and dependencies
cienvaras Jun 29, 2025
4040960
feat: update storybook configuration
cienvaras Jun 30, 2025
60dbdcc
feat: remove all webpack specific plugins but leave the config files …
Sep 10, 2025
ab7efbd
feat: port file compilation logic from webpack and split up config
Sep 11, 2025
b255a4d
chore: version bump
Sep 11, 2025
4b167b5
feat: enable vite watching and refactor the entry array being passed …
Sep 12, 2025
89cd952
chore: remove eslint-disable flag
Sep 12, 2025
fdcb146
feat: configure compilation logic for JS/CSS file locations
Sep 15, 2025
602bd8a
feat: copy srcmaps to compiled folders
Sep 15, 2025
eb6b2bc
feat: copy srcmaps to compiled folders
Sep 15, 2025
918ef9d
feat: jsdoc standards for entries.js
Sep 15, 2025
4c25bb6
chore: cleanup unused packages
Sep 15, 2025
e6c6983
chore: prettier format changes
Sep 15, 2025
beb3b1f
Merge pull request #208 from emulsify-ds/feat-split-plugin-entries-en…
callinmullaney Sep 15, 2025
c62331d
fix: vite integration issues fix
cienvaras Sep 29, 2025
ec62bdb
chore: dependency updates
Oct 1, 2025
fc6316a
feat: ensure static assets are copied over with compiled assets
Oct 2, 2025
a7509d5
chore: eslint fixes for entries
Oct 2, 2025
e3ea68b
chore: eslint fixes for environment
Oct 2, 2025
858d2fb
chore: eslint fixes for plugins
Oct 2, 2025
7fb24e3
chore: eslint fixes for plugins
Oct 2, 2025
40d4a84
feat: add sass glob importer support
Oct 2, 2025
91cb110
feat: account for structureImplementations when compiling files for l…
Oct 3, 2025
ff75a72
feat: account for structureImplementations when compiling files for l…
Oct 3, 2025
8945833
chore: lint fixes
Oct 3, 2025
dcf8a68
chore: lint fixes
Oct 3, 2025
e07bb85
feat: change legacy reference to structure overrides
Oct 3, 2025
592ae21
feat: move svgsprite plugin to baseplugins
Oct 3, 2025
b3ebff0
chore: restore legacy emulsify compiling structure
Oct 3, 2025
0aa365d
feat: allow for plugin and vite.config extension per project
Oct 3, 2025
89ef589
feat: better code commenting for vite.config.js
Oct 3, 2025
2bbd0ae
Merge pull request #220 from emulsify-ds/emulsify-537
callinmullaney Oct 3, 2025
7a8bf21
chore: remove webpack references
Oct 28, 2025
2f67c22
feat: add twig polyfils for storybook configuration
Oct 29, 2025
9f79d9f
feat: preverve dir structure when assets are copied to dist
Dec 1, 2025
18c58fe
feat: add relativizr plugin for url() processed in scss
Dec 1, 2025
ca579a4
fix: patch broken svg attributes that contain a colon
Dec 1, 2025
6e10130
chore: remove console log
Dec 1, 2025
9ff70e5
feat: properly merge vite config so non-js files are loaded properly …
Dec 2, 2025
4e5a515
chore: update storybook to v10
cienvaras Dec 9, 2025
3fd6727
chore: refine code comments for central storybook config
Apr 2, 2026
e839921
fix: include react in list of vite optimized dependencies
cienvaras May 20, 2026
95303b7
fix: errors in twig-resolver.js when running storybook
cienvaras May 20, 2026
8bf596b
feat: use platform-neutral Twig renderer
May 23, 2026
cf518ef
fix: preserve Storybook Twig rendering
May 23, 2026
3d34eb5
test: cover platform-neutral Twig plugins
May 23, 2026
08f2a58
docs: describe platform-agnostic Twig rendering
May 23, 2026
7756477
chore: remove retired twig extension packages
May 23, 2026
bc9d3f6
feat: add native twig extension registry
May 23, 2026
fab683d
docs: add jsdoc comments for native extensions
May 23, 2026
ad1808b
Merge pull request #245 from emulsify-ds/codex/native-twig-extensions
callinmullaney May 23, 2026
6c53f2f
docs: standardize code comments
May 23, 2026
0ff39d7
chore: enforce node 24 script floor
May 23, 2026
8a35611
feat: normalize Vite project structure
May 24, 2026
2b213cb
feat: support mixed Storybook renderers
May 24, 2026
73abe8c
ci: add release readiness fixtures
May 24, 2026
f2d419c
feat: add Twig switch tags
May 24, 2026
b6fed1b
ci: add develop version bump workflow
May 25, 2026
0ff4e9f
refactor: move Storybook Twig runtime helpers
May 25, 2026
c12271a
docs: split README into docs directory
May 25, 2026
09540bb
docs: refine documentation tone
May 25, 2026
25d72c5
docs: remove stale twig extensions reference
May 25, 2026
710c5e0
perf: reuse Vite source file discovery
May 25, 2026
5a1a224
test: add release fixture matrix coverage
May 25, 2026
7615a52
docs: clarify release readiness guidance
May 25, 2026
11da997
feat: support project Storybook addon overrides
May 25, 2026
cd4961b
chore: move release fixtures under github
May 25, 2026
ee72ae2
chore: merge develop into 4.x
May 25, 2026
e9ac605
chore: clean up prerelease docs and branding
May 25, 2026
39906d5
ci: avoid duplicate release readiness runs
May 25, 2026
76c7ce7
feat: support legacy Twig story rendering
May 25, 2026
4736e9f
feat: add project readiness audit
May 25, 2026
b5ccd4b
fix: improve audit source scoping and asset checks
May 26, 2026
e03c2aa
fix: reduce install audit noise
May 26, 2026
50a754b
fix: add named YAML metadata exports
May 26, 2026
811513d
fix: prevent twig template cache collisions
May 26, 2026
0dc66be
fix: render legacy twig story markup
May 26, 2026
4631c8f
refactor(vite): consolidate path and fs utilities
May 26, 2026
5e5c527
fix(storybook): dedupe react runtime for twig stories
May 26, 2026
51b2312
refactor(vite): split plugins.js into per-plugin modules (internal)
May 26, 2026
e6f6ba5
feat(vite): replace Twig glob placeholder injection with virtual module
May 26, 2026
459f148
fix(vite): make mirrorComponentsToRoot race-safe via writeBundle + at…
May 26, 2026
6e895ca
chore(vite): remove dead patterns parameter from buildInputs
May 26, 2026
1cd889d
fix: use public Vite extension config path
May 26, 2026
c9852d8
test(vite): assert Vituum plugin shape after patching
May 26, 2026
9214d1a
docs(react): mark defineReactExtension as reserved API
May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 0 additions & 45 deletions .all-contributorsrc

This file was deleted.

58 changes: 31 additions & 27 deletions .cli/init.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
#!/usr/bin/env node

/**
* @file Initializes a generated Emulsify project from project.emulsify.json.
*/

const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');

/**
* Returns a boolean indicating whether or not the given object is a literal object.
* Determine whether a value is a plain object.
*
* @param {any} obj object who's type will be checked.
* @returns {boolean} boolean indicating whether or not the given obj is a literal object.
* @param {*} obj - Value to inspect.
* @returns {boolean} TRUE when the value is a plain object.
*/
const isObjectLiteral = (obj) =>
obj != null && obj.constructor.name === 'Object';

/**
* Attempts to require the project.emulsify.json file.
* Load project.emulsify.json from the generated project config directory.
*
* @returns parsed project.emulsify.json file.
* @returns {Object} Parsed project.emulsify.json file.
* @throws {Error} When the config cannot be loaded.
*/
const getEmulsifyConfig = () => {
try {
Expand All @@ -31,9 +36,11 @@ const getEmulsifyConfig = () => {
};

/**
* Throws if the given emulsify config file is invalid.
* Validate the minimal project configuration required for initialization.
*
* @param {*} config emulsify project config, as loaded from a project.emulsify.json file.
* @param {*} config - Emulsify project config loaded from project.emulsify.json.
* @returns {void}
* @throws {Error} When required config values are missing or invalid.
*/
const validateEmulsifyConfig = (config) => {
const prefix = 'Invalid project.emulsify.json config file';
Expand Down Expand Up @@ -68,36 +75,34 @@ const validateEmulsifyConfig = (config) => {
};

/**
* Takes an array of objects describing the origin and destination of a given file,
* then moves each specified file according to it's to/from properties.
* Move generated starter files to their project-specific names.
*
* @param {Array<{ to: string, from: string }>} files array of objects depicting the origin and destination of a given file.
* @returns void.
* @param {Array<{ to: string, from: string }>} files - Files to move.
* @returns {Array<void>} Rename results.
*/
const renameFiles = (files) =>
files.map(({ from, to }) =>
fs.renameSync(path.join(__dirname, from), path.join(__dirname, to)),
);

/**
* Takes a machineName, and returns a fn that, when called with a str,
* replaces all instances of `emulsify` with the given machineName.
* Create a replacer that swaps the starter machine name for the project name.
*
* @param {string} machineName string that should replace emulsify.
* @returns {function} fn that when called with a str, replaces all instances of `emulsify` with the given machineName.
* @param {string} machineName - Machine name that should replace `emulsify`.
* @returns {Function} String replacer.
*/
const strReplaceEmulsify = (machineName) => (str) =>
str.replace(/emulsify/g, machineName);

/**
* Loads a yml file at filePath, applies the functor to the contents of the file, and writes it.
* Load a YAML file, transform its parsed contents, and write it back.
*
* @param {string} filePath path to the file that should be loaded, modified, and re-saved.
* @param {fn} functor fn that should return the new contents of the file, to be saved.
* @returns void.
* @param {string} filePath - File to load, modify, and save.
* @param {Function} functor - Function that returns the replacement YAML data.
* @returns {void}
*/
const applyToYmlFile = (filePath, functor) => {
if (!filePath || typeof filePath !== `string`) {
if (!filePath || typeof filePath !== 'string') {
throw new Error(
`Cannot modify a file without knowing how to access it: ${filePath}`,
);
Expand All @@ -111,18 +116,17 @@ const applyToYmlFile = (filePath, functor) => {
};

const main = () => {
// Load up config file, throw if none exists.
// Load the project config before mutating any generated files.
const config = getEmulsifyConfig();

// Validate config file, throw if it is missing
//properties or is otherwise malformed.
// Fail fast when required project metadata is missing or malformed.
validateEmulsifyConfig(config);

const {
project: { machineName, name },
project: { machineName },
} = config;

// Move all files to their correct location.
// Rename starter files from the generic prefix to the project machine name.
renameFiles([
{
from: '../emulsify.info.yml',
Expand All @@ -142,7 +146,7 @@ const main = () => {
},
]);

// Update info.yml file.
// Update info.yml values that Drupal reads from the generated theme.
applyToYmlFile(
path.join(__dirname, `../${machineName}.info.yml`),
(info) => ({
Expand All @@ -152,7 +156,7 @@ const main = () => {
}),
);

// Update breakpoint.yml file.
// Update breakpoint keys to match the renamed theme machine name.
applyToYmlFile(
path.join(__dirname, `../${machineName}.breakpoints.yml`),
(breakpoints) => {
Expand Down
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Unix-style newlines with a newline ending every file
# Keep editor defaults aligned with Prettier and repository formatting.
[*]
indent_style = space
indent_size = 2
Expand Down
8 changes: 7 additions & 1 deletion .github/ISSUE_TEMPLATE/BUG_REPORT_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
### Describe the bug

_A clear and concise description of what the bug is._

### Steps to reproduce the bug

Steps to reproduce the behavior:

1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

### Expected behavior

A clear and concise description of what you expected to happen.

### Suggested solution or approach:

_(optional) Describe a solution or approach to your request that may help with implementation._

### Additional context
_(optional) Add any other context or screenshots about the feature request here._

_(optional) Add any other context or screenshots about the feature request here._
8 changes: 6 additions & 2 deletions .github/ISSUE_TEMPLATE/FEATURE_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
### Emulsify Core Version:

- [1.0.0](https://github.com/emulsify-ds/emulsify-core/releases)):

### Description of the feature request:
_Please give as much information as possible_

_Please give as much information as possible_

### Suggested solution or approach:

_(optional) Describe a solution or approach to your request that may help with implementation._

### Additional context:
_(optional) Add any other context or screenshots about the feature request here._

_(optional) Add any other context or screenshots about the feature request here._
9 changes: 7 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
**This PR does the following:**

- Adds functionality bullet item
- Fixes this or that bullet item

### Related Issue(s)

- [Title of the issue](https://github.com/emulsify-ds/emulsify-core/issues/1)

### Notes:

- (optional) Document any intentionally unfinished parts or known issues within this PR

### Functional Testing:

- [ ] Document steps that allow someone to fully test your code changes. Include screenshot and links when appropriate.

### Security

_Security checks that should be reviewed_

### Accessibility
_Should this be checked for this feature?_

_Should this be checked for this feature?_
4 changes: 3 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Keeps npm dependency metadata current for the package root.
version: 2
updates:
- package-ecosystem: npm
directory: "/"
directory: '/'
# Weekly updates reduce churn while keeping dependencies maintained.
schedule:
interval: weekly
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"project": {
"platform": "drupal",
"name": "drupal-sdc-src-components",
"machineName": "drupal_sdc_src_components",
"singleDirectoryComponents": true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>{{ content }}</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
drupal-sdc-asset
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: Card
props:
type: object
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import template from './card.twig';

export default template({
heading: 'Drupal SDC card',
content: 'Rendered from a Twig include.',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.card {
color: #135e96;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% set attrs = {
class: bem('card', ['featured']),
'data-fixture': 'drupal-sdc'
} %}
<article {{ add_attributes(attrs) }}>
<h2>{{ heading }}</h2>
{% include './_content.twig' %}
</article>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = [
{
name: 'generic-fixture-vite-extension',
generateBundle() {
this.emitFile({
type: 'asset',
fileName: 'extension-marker.txt',
source: 'config/emulsify-core/vite/plugins.js loaded\n',
});
},
},
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"project": {
"platform": "generic",
"name": "generic-src-components",
"machineName": "generic_src_components"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const fixture = 'generic base';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.base {
color: #2f6f4e;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<p>{{ content }}</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
generic-src-asset
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import template from './card.twig';

export const html = template({
heading: 'Generic Twig card',
content: 'Compiled with generic platform behavior.',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.card {
color: #4f5f9f;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% set attrs = {
class: bem('card', ['generic']),
'data-fixture': 'generic-src'
} %}
<article {{ add_attributes(attrs) }}>
<h2>{{ heading }}</h2>
{% include './_content.twig' %}
</article>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"project": {
"platform": "generic",
"name": "large-twig-storybook",
"machineName": "large_twig_storybook"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { renderTwig } from '@emulsify/core/storybook';
import template from './gallery.twig';

export default {
title: 'Fixtures/Large Twig Storybook',
};

export const Default = {
render: renderTwig(template),
args: {
heading: 'Large Twig fixture',
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<section class="large-gallery">
<h2>{{ heading }}</h2>
{{ include('@components/item-001/item-001.twig', {
label: 'Included via normalized namespace',
variant: 'featured'
}) }}
<pre data-source-check>{{ source('@components/item-002/item-002.twig') }}</pre>
</section>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
legacy-components-asset
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import template from './banner.twig';

export default template({
heading: 'Legacy banner',
});
Loading
Loading