Skip to content

Instantly share code, notes, and snippets.

@esr360
Created December 7, 2019 03:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save esr360/04b88700412599143b5b8a3274e9afd9 to your computer and use it in GitHub Desktop.
Save esr360/04b88700412599143b5b8a3274e9afd9 to your computer and use it in GitHub Desktop.
require('@babel/register')();
require('jsdom-global')();
const Sass = require('node-sass');
const fs = require('fs');
const mkdirp = require('mkdirp');
const getDirName = require('path').dirname;
window.matchMedia = window.matchMedia || function() {
return {
matches : false,
addListener : function() {},
removeListener: function() {}
}
}
const deepextend = require('deep-extend');
const MODULES = {};
const MODULES_PARENT_DIR = '/modules';
const MODULE_CONFIG_FILENAME = 'config';
const MODULE_STYLES_FILENAME = 'styles';
module.exports = function(source) {
const THEME = this.query.theme;
const FILEPATH = this.resourcePath;
const FILENAME = FILEPATH.replace(/^.*[\\\/]/, '');
let MODULE;
try {
MODULE = require(FILEPATH).default || {};
} catch(error) {
MODULE = {};
}
if (typeof MODULE === 'function') {
let NAMESPACE;
if (MODULE.defaultProps && MODULE.defaultProps.name) {
NAMESPACE = MODULE.defaultProps.name;
}
else if (this.context.endsWith('/modules')) {
NAMESPACE = MODULE.name;
}
if (NAMESPACE) {
if (typeof MODULE.config === 'function') {
MODULE.config = MODULE.config(THEME);
}
Object.assign(MODULE, {
config: deepextend(MODULE.config, THEME.modules && evalConfig(THEME.modules[NAMESPACE], THEME))
});
if (MODULE.styles) {
const STYLES = MODULE.styles({
theme: THEME,
config: MODULE.config,
state: {}
});
let TEMPLATE = `
@import '../../Cell/Cell/dist/cell';
@include module(${NAMESPACE}) {
//@Content
}
`;
const CSS = writeCSS(STYLES, TEMPLATE);
console.log(STYLES);
const COMPILED_CSS = Sass.renderSync({
data: CSS,
outputStyle: 'expanded'
});
mkdirp(getDirName(`dist/css/${NAMESPACE}.css`), () => {
fs.writeFile(`dist/css/${NAMESPACE}.css`, COMPILED_CSS.css, (err) => {
if (err) throw err;
});
});
}
}
}
return source;
}
/**
*/
function writeCSS(STYLES, CSS) {
if (STYLES instanceof Array) {
STYLES.forEach(STYLE => CSS = writeCSS(STYLE, CSS));
return CSS;
}
Object.entries(STYLES).forEach(style => {
const key = style[0]; let value = style[1];
if (typeof value === 'object') {
CSS = CSS.replace(`//@Content`, `@include component(${key}, (${transformJStoSass(value)}));//@Content`);
}
else if (typeof value === 'function') {
const _CSS = transformJStoSass(value({ state: {}, context: {} }));
CSS = CSS.replace(`//@Content`, `@include component(${key}, (${_CSS}));//@Content`);
}
else {
CSS = CSS.replace(`//@Content`, `${key}: ${value};//@Content`);
}
});
return CSS;
}
/**
* Evaluate module config properties
*/
function evalConfig(config, theme) {
if (!config) {
return;
}
Object.entries(config).forEach(([key, value]) => {
if (typeof value === 'object') {
return evalConfig(value, theme);
}
else {
return (typeof value === 'function') ? config[key] = value(theme) : false;
}
});
return config;
}
/**
* @param {*} url
*/
export function isValidFile(url) {
return (/\.(js)(on(5)?|s)?$/.test(url));
}
/**
* @param {*} json
*/
export function transformJStoSass(json) {
return Object.keys(json).filter(key => isValidKey(key)).filter(key => json[key] !== '#').map(key => {
return `${key}: ${parseValue(json[key])},`
}).join('\n');
}
/**
* @param {*} key
*/
export function isValidKey(key) {
return /^[^$@:].*/.test(key);
}
/**
* @param {*} value
*/
export function parseValue(value) {
if (typeof value === 'function') {
return '"[function]"'
}
if (value instanceof Array) {
return parseList(value);
}
else if (typeof value === 'object') {
return parseMap(value);
}
else if (valueShouldBeStringified(value)) {
return `"${value}"`;
}
else {
return value;
}
}
/**
* @param {*} list
*/
export function parseList(list) {
return `(${list.map(value => parseValue(value)).join(',')})`;
}
/**
* @param {*} map
*/
export function parseMap(map) {
const keys = Object.keys(map).map(key => {
try {
sass.renderSync({
data: `$foo: (${key}: 'value');`
});
return key;
}
catch(error) {
return `"${key}"`;
}
});
return `(${keys.filter(key => isValidKey(key)).map(key => {
return `${key}: ${parseValue(map[key.replace(/"/g,"")])}`;
}).join(',')})`;
}
/**
* @param {*} value
*/
export function valueShouldBeStringified(value) {
try {
Sass.renderSync({
data: `$foo: (key: ${value});`
});
return false;
}
catch(error) {
return true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment