Skip to content

Commit

Permalink
feat: remove elf global and replace with eventListener (#511)
Browse files Browse the repository at this point in the history
* feat: add event based theming option to theme compiler

* feat(core): remove elf global and replace with eventListener

* fix(core): using registration instead of styles

* fix(theme-compiler): fix pass variable to generateLessOptions

* chore(core): add ignore eslint

* test(core): add test case for registry event

* refactor(core): rearrange code

* feat(create-efx): add registration to using core by listener

Co-authored-by: Sarin Udompanish <[email protected]>
  • Loading branch information
Theeraphat-Sorasetsakul and Sarin Udompanish authored Nov 7, 2022
1 parent d0d83a9 commit d94c087
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 26 deletions.
29 changes: 27 additions & 2 deletions packages/core/__test__/elf.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, fixture } from '@refinitiv-ui/test-helpers';
import { expect, fixture, oneEvent } from '@refinitiv-ui/test-helpers';
import { customElement } from './../lib/decorators/custom-element';
import { LitElement } from '../lib/index.js';

import { CustomStyleRegistry } from '../lib/registries/CustomStyleRegistry.js';
class BasicElementTest extends LitElement {

}
Expand Down Expand Up @@ -36,3 +36,28 @@ describe('Test ELF', () => {
expect(warnMessage).to.equal('Please use an ELF element type, instead of LitElement', 'Wrong warning message is used');
});
});

describe('Test ELF', () => {
it('Test registry event call: ef.customStyles.define', async () => {
const mockElementName = 'test-element';
const mockCssString = ':host{}';
window.dispatchEvent(new CustomEvent('ef.customStyles.define', {
detail: {
name: mockElementName,
styles: mockCssString
}
}));
expect(CustomStyleRegistry.get(mockElementName)).to.equal(mockCssString);
});
it('Test registry event call: ef.nativeStyles.define', async () => {
const mockElementName = 'test-element';
const mockCssString = ':host{}';
window.dispatchEvent(new CustomEvent('ef.nativeStyles.define', {
detail: {
name: mockElementName,
styles: mockCssString
}
}));
expect(CustomStyleRegistry.get(mockElementName)).to.equal(mockCssString);
});
});
17 changes: 11 additions & 6 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */

export {
html,
svg,
Expand Down Expand Up @@ -74,10 +77,12 @@ import { CustomStyleRegistry } from './registries/CustomStyleRegistry.js';
import { NativeStyleRegistry } from './registries/NativeStyleRegistry.js';
import { global } from './utils/global.js';

global.elf = global.Elf = global.ELF = {
customStyles: CustomStyleRegistry,
nativeStyles: NativeStyleRegistry,
version: 'PUBLISH_VERSION'
};
global.addEventListener('ef.customStyles.define', (event) => {
const { name, styles } = (event as CustomEvent).detail;
CustomStyleRegistry.define(name, styles);
});

Object.freeze(global.elf);
global.addEventListener('ef.nativeStyles.define', (event) => {
const { name, styles } = (event as CustomEvent).detail;
NativeStyleRegistry.define(name, styles);
});
2 changes: 1 addition & 1 deletion packages/create-efx/template/package.json.template
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"start": "vite --open --base=/demo/",
"build": "npm run build:themes && tsc --sourceMap --declarationMap",
"build:themes": "npm run build:theme-halo",
"build:theme-halo": "cd themes/halo && theme-compiler light --variant light && theme-compiler dark --variant dark",
"build:theme-halo": "cd themes/halo && theme-compiler light --variant light --registration=event && theme-compiler dark --variant dark --registration=event",
"prepare": "npm run build:themes",
"lint": "eslint src",
"lint:fix": "eslint src --fix",
Expand Down
4 changes: 2 additions & 2 deletions packages/elemental-theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"!.*"
],
"scripts": {
"build:light": "theme-compiler light --variant=light",
"build:dark": "theme-compiler dark --variant=dark",
"build:light": "theme-compiler light --variant=light --registration=event",
"build:dark": "theme-compiler dark --variant=dark --registration=event",
"build": "npm run build:light && npm run build:dark",
"build:prod": "npm run build",
"watch": "watch \"npm run build\" src --wait=10",
Expand Down
4 changes: 2 additions & 2 deletions packages/halo-theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"!.*"
],
"scripts": {
"build:dark": "theme-compiler dark --variant=dark",
"build:light": "theme-compiler light --variant=light",
"build:dark": "theme-compiler dark --variant=dark --registration=event",
"build:light": "theme-compiler light --variant=light --registration=event",
"build": "npm run build:dark && npm run build:light",
"build:prod": "npm run build",
"watch": "watch \"npm run build\" src --wait=10",
Expand Down
6 changes: 3 additions & 3 deletions packages/solar-theme/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"!.*"
],
"scripts": {
"build:charcoal": "theme-compiler charcoal --variant=charcoal",
"build:pearl": "theme-compiler pearl --variant=pearl",
"build:charcoal": "theme-compiler charcoal --variant=charcoal --registration=event",
"build:pearl": "theme-compiler pearl --variant=pearl --registration=event",
"build": "npm run build:charcoal && npm run build:pearl",
"build:prod": "npm run build",
"watch": "watch \"npm run build\" src --wait=10",
Expand All @@ -32,4 +32,4 @@
"publishConfig": {
"access": "public"
}
}
}
46 changes: 40 additions & 6 deletions packages/theme-compiler/src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,34 @@ const autoprefixer = require('postcss')().use(require('autoprefixer'));
const clean = new (require('clean-css'))({ returnPromise: true, level: '2' });
const path = require('path');

const wrap = (name, style) => `elf.${name.indexOf('-') > 0 ? 'custom'
: 'native'}Styles.define('${name}', '${style.replace(/'/g, '\\\'')}');\n`;
/**
* Return injector code in form of string
* @param {string} name element's path
* @param {string} style element's path
* @param {string} isEvent condition if need to be event method
* @returns {string} injector code
*/
const wrap = (name, style, isEvent) => {
const eventName = name.indexOf('-') > 0 ? 'custom' : 'native';
if(isEvent) {
return `dispatchEvent(new CustomEvent('ef.${eventName}Styles.define', { detail: { name: '${name}', styles: '${style.replace(/'/g, '\\\'')}' }}));\n`;
}
return `elf.${eventName}Styles.define('${name}', '${style.replace(/'/g, '\\\'')}');\n`;
}

const cleanCSS = css => autoprefixer.process(css, { from: false })
.then(o => clean.minify(o.css)).then(o => o.styles);

const wrapHostSelectors = css => Promise
.resolve(css.replace(/(:host)([.:[#][^\s,{]+)/g, '$1($2)'));

/**
* Return less option template
* @param {string} entrypoint source map output
* @param {string} filename source of the element styles
* @param {string} variables variables that override the less file
* @returns {string} injector code
*/
const generateLessOptions = (entrypoint, filename, variables) => ({
filename: entrypoint,
math: 2,
Expand All @@ -41,13 +60,21 @@ const generateLessOptions = (entrypoint, filename, variables) => ({
]
});

const generateJsInfo = (name, css, dependencies) => {
/**
* Return generated info for injector string
* @param {string} name element name
* @param {string} css element style
* @param {string} dependencies list of elements
* @param {string} variables option variables that include using event condition
* @returns {object} injector code
*/
const generateJsInfo = (name, css, dependencies, variables) => {
let importString = 'import \'./imports/native-elements.js\';\n';
importString += dependencies.filter(name => name.indexOf('-') !== -1)
.map(dep => `import './${dep}.js';`).join('\n') + '\n';
return {
importString,
injectorString: wrap(name, css.replace(/([^\\])\\([^\\])/g, '$1\\\\$2'))
injectorString: wrap(name, css.replace(/([^\\])\\([^\\])/g, '$1\\\\$2'), variables.registration === 'event')
};
};

Expand All @@ -59,13 +86,20 @@ const getElementNameFromLess = (filename) => {
return path.basename(filename).replace(/\.less$/, '');
};

const generateOutput = (filename, output) => {
/**
* Return object that use for parser
* @param {string} filename element source
* @param {string} output less file source
* @param {string} variables option variables that include using event condition
* @returns {object}
*/
const generateOutput = (filename, output, variables) => {
return cleanCSS(output.css).then(wrapHostSelectors).then(css => {
let name = path.basename(filename).replace(/\.less$/, '');
let dependencies = output.imports
.filter(filename => prefix.test(filename))
.map(filename => filename.replace(dependencyPattern, ''));
let styleInfo = generateJsInfo(name, css, dependencies);
let styleInfo = generateJsInfo(name, css, dependencies, variables);
return {
name,
dependencies,
Expand Down
7 changes: 4 additions & 3 deletions packages/theme-compiler/src/themeParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const parse = (entrypoint, variables) => {
let options = helpers.generateLessOptions(entrypoint, entrypoint, variables);
return fs.readFile(entrypoint, 'utf8').then(lessInput => {
return less.render(lessInput, options).then(() => {
helpers.getElementFiles().forEach(filename => renderElement(filename, lessInput));
helpers.getElementFiles().forEach(filename => renderElement(filename, lessInput, variables));
return Promise.all(tempCollection)
.then(resolvedCollection => {
let result = sortCollection(resolvedCollection);
Expand All @@ -65,9 +65,10 @@ const parse = (entrypoint, variables) => {
*
* @param {String} filename Source of the element styles
* @param {String} lessInput Less input from the entrypoint
* @param {Object} variables Variables to modify in the less input
* @returns {Promise} Promise
*/
const renderElement = (filename, lessInput) => {
const renderElement = (filename, lessInput, variables) => {
// Obtain elementName
const elemName = helpers.getElementNameFromLess(filename);

Expand All @@ -76,7 +77,7 @@ const parse = (entrypoint, variables) => {

let options = helpers.generateLessOptions(entrypoint, filename, variables);
let promise = less.render(lessInput, options)
.then(output => helpers.generateOutput(filename, output));
.then(output => helpers.generateOutput(filename, output, variables));
tempCollection.push(promise);
return promise;
};
Expand Down
2 changes: 1 addition & 1 deletion scripts/release/theme-extractor.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ const handler = async () => {
// Reads theme entrypoint content
const sourceContent = fs.readFileSync(possibleThemeEntrypoint).toString();
const componentThemeDefinition = sourceContent.substring(
sourceContent.indexOf('elf.customStyles.define')
sourceContent.indexOf(`dispatchEvent(new CustomEvent('ef.customStyles.define'`)
);

// Skip if the file already contain the same component definition
Expand Down

0 comments on commit d94c087

Please sign in to comment.