From b47f286dc93ca7715c9f22748c2a2aa44a8c6b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Mon, 30 Mar 2020 12:01:08 +0800 Subject: [PATCH 01/14] fix(test): get css module name --- babel.config.js | 12 +++++++++++ package.json | 2 +- src/__tests__/get-css-module-name.js | 32 ++++++++++++++++++++++++++++ src/runtime/get-css-module-name.js | 8 ++++--- 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 babel.config.js create mode 100644 src/__tests__/get-css-module-name.js diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..11cadc4 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,12 @@ +module.exports = function (api) { + // Cache the returned value forever and don't call this function again. + if (api) api.cache(true); + + return { + presets: [ + ['@babel/preset-env', { + 'loose': true, + }], + ] + }; +}; diff --git a/package.json b/package.json index c653a44..5b899a2 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "devDependencies": { "@alifd/next": "^1.19.18", "babel-eslint": "^10.1.0", - "babel-jest": "^25.1.0", + "babel-jest": "^25.2.4", "css-loader": "^3.4.2", "eslint": "^6.8.0", "eslint-config-rax": "^0.0.3", diff --git a/src/__tests__/get-css-module-name.js b/src/__tests__/get-css-module-name.js new file mode 100644 index 0000000..ed685d0 --- /dev/null +++ b/src/__tests__/get-css-module-name.js @@ -0,0 +1,32 @@ +import getCSSModuleName from '../runtime/get-css-module-name'; + +describe('GetCSSModuleName', () => { + const MAPPING = { + container: 'foo', + strong: 'bar', + }; + + it('should transform local name', () => { + const actual = getCSSModuleName(MAPPING, 'strong'); + + expect(actual).toEqual('bar'); + }); + + it('should transform multi', () => { + const actual = getCSSModuleName(MAPPING, 'strong container'); + + expect(actual).toEqual('bar foo'); + }); + + it('should transform global', () => { + const actual = getCSSModuleName(MAPPING, ':strong :container'); + + expect(actual).toEqual('strong container'); + }); + + it('should not transform not match', () => { + const actual = getCSSModuleName(MAPPING, 'sss ddd'); + + expect(actual).toEqual('sss ddd'); + }); +}); diff --git a/src/runtime/get-css-module-name.js b/src/runtime/get-css-module-name.js index c20d4a1..e3a5e63 100644 --- a/src/runtime/get-css-module-name.js +++ b/src/runtime/get-css-module-name.js @@ -1,4 +1,5 @@ const CLASS_NAME_SPLITER = /\s/; +const hasOwn = {}.hasOwnProperty; /** * Support syntax of `:module`, which means global css scope. @@ -11,10 +12,11 @@ export default function getCSSModuleName(moduleMapping, className) { .split(CLASS_NAME_SPLITER) .map(local => { if (local[0] === ':') { - const module = moduleMapping[local.slice(1)]; - return module ? module : local; + return local.slice(1); } else { - return local; + return hasOwn.call(moduleMapping, local) + ? moduleMapping[local] + : local; } }) .join(' '); From e89b926151d2a40cc989c013e0f4215fea3ca503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Mon, 30 Mar 2020 13:34:56 +0800 Subject: [PATCH 02/14] feat: script and style should be conditional --- src/__tests__/{parts.rml => basic.rml} | 0 src/__tests__/parts.js | 4 ++-- src/parts.js | 1 + src/rml-loader.js | 15 +++++++++------ src/style-loader.js | 3 +++ 5 files changed, 15 insertions(+), 8 deletions(-) rename src/__tests__/{parts.rml => basic.rml} (100%) diff --git a/src/__tests__/parts.rml b/src/__tests__/basic.rml similarity index 100% rename from src/__tests__/parts.rml rename to src/__tests__/basic.rml diff --git a/src/__tests__/parts.js b/src/__tests__/parts.js index 7b569d1..30a614d 100644 --- a/src/__tests__/parts.js +++ b/src/__tests__/parts.js @@ -6,8 +6,8 @@ const { readFileSync } = require('fs'); const { join } = require('path'); describe('parts', () => { - it('should parse rml', () => { - const rml = readFileSync(join(__dirname, './parts.rml'), 'utf-8'); + it('should parse basic rml', () => { + const rml = readFileSync(join(__dirname, './basic.rml'), 'utf-8'); const parts = parseSFCParts(rml); const script = selectPart(parts, 'script'); expect(script).toMatchSnapshot(); diff --git a/src/parts.js b/src/parts.js index a32b232..f214602 100644 --- a/src/parts.js +++ b/src/parts.js @@ -120,6 +120,7 @@ function parseSFCParts(html) { function preCompileParts(html, key) { const parts = parseSFCParts(html); partsStorage.set(key, parts); + return parts; } exports.getResourcePart = getResourcePart; diff --git a/src/rml-loader.js b/src/rml-loader.js index 796022e..cfc3450 100644 --- a/src/rml-loader.js +++ b/src/rml-loader.js @@ -17,21 +17,24 @@ module.exports = function RMLLoader(rawContent) { const { resourcePath } = context; const { renderer } = options; - preCompileParts(rawContent, resourcePath); + const parts = preCompileParts(rawContent, resourcePath); const loadScriptRequest = stringifyRequest(`${paths.partLoader}?part=script!${resourcePath}`); const loadTemplateRequest = stringifyRequest(`${paths.templateLoader}?renderer=${renderer}!${paths.partLoader}?part=template!${resourcePath}`); const loadStyleRequest = stringifyRequest(`${paths.styleLoader}!${resourcePath}`); - const code = ` -import createData from ${loadScriptRequest}; + let loadData; + if (parts['script']) { + loadData = `import createData from ${loadScriptRequest};`; + } + + const code = `${loadData} import render from ${loadTemplateRequest}; import * as style from ${loadStyleRequest}; - export default function AnonymousRMLModule(props) { - return render(createData(props), style); + return render(${loadData ? 'createData(props)' : 'null'}, style); } - `; +`; return code.trim() + '\n'; }; diff --git a/src/style-loader.js b/src/style-loader.js index a115d4a..a348f91 100644 --- a/src/style-loader.js +++ b/src/style-loader.js @@ -8,6 +8,9 @@ module.exports = function styleLoader(styleContent) { const stringifyRequest = r => loaderUtils.stringifyRequest(this, r); const style = getResourcePart(resourcePath, 'style'); + // No style tag exists. + if (!style) return ''; + // Use webpack's RuleSet utility to normalize user rules const compiler = this._compiler; const rawRules = compiler.options.module.rules; From ef7faab7048a571683eb466d1632d75188dd04ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Mon, 30 Mar 2020 13:35:40 +0800 Subject: [PATCH 03/14] test: clean snapshot --- src/__tests__/__snapshots__/parts.js.snap | 8 ++++---- src/rml-loader.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/__tests__/__snapshots__/parts.js.snap b/src/__tests__/__snapshots__/parts.js.snap index b4ec93f..5011b58 100644 --- a/src/__tests__/__snapshots__/parts.js.snap +++ b/src/__tests__/__snapshots__/parts.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`parts should parse rml 1`] = ` +exports[`parts should parse basic rml 1`] = ` Object { "attrs": Object {}, "content": "import { useState, useCallback } from 'react'; @@ -22,7 +22,7 @@ Object { } `; -exports[`parts should parse rml 2`] = ` +exports[`parts should parse basic rml 2`] = ` Object { "attrs": Object {}, "content": Array [ @@ -43,7 +43,7 @@ Object { } `; -exports[`parts should parse rml 3`] = ` +exports[`parts should parse basic rml 3`] = ` Object { "attrs": Object {}, "content": ".foo { @@ -53,7 +53,7 @@ Object { } `; -exports[`parts should parse rml 4`] = ` +exports[`parts should parse basic rml 4`] = ` Array [ Object { "Button": "Button", diff --git a/src/rml-loader.js b/src/rml-loader.js index cfc3450..6d4a8ad 100644 --- a/src/rml-loader.js +++ b/src/rml-loader.js @@ -24,7 +24,7 @@ module.exports = function RMLLoader(rawContent) { const loadStyleRequest = stringifyRequest(`${paths.styleLoader}!${resourcePath}`); let loadData; - if (parts['script']) { + if (parts.script) { loadData = `import createData from ${loadScriptRequest};`; } From 8bff7c5c6e9caf7a0e70042723fd570ff8634039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Wed, 1 Apr 2020 11:33:46 +0800 Subject: [PATCH 04/14] 0.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b899a2..ecf3ba0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@reactml/loader", - "version": "0.1.1", + "version": "0.1.2", "description": "Webpack loader for react markup language.", "main": "src/rml-loader.js", "scripts": { From 09b4d66b6abca4bbca63db0107076440b827c3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Wed, 1 Apr 2020 11:37:45 +0800 Subject: [PATCH 05/14] chore: make babel.config.js not effect test --- src/__tests__/babel-plugin-with-props.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/__tests__/babel-plugin-with-props.js b/src/__tests__/babel-plugin-with-props.js index 565c6e4..af486e3 100644 --- a/src/__tests__/babel-plugin-with-props.js +++ b/src/__tests__/babel-plugin-with-props.js @@ -30,6 +30,7 @@ describe('babel-plugin-with-props', () => { const expected = spec[1]; const actual = transformSync(input, { compact: true, + configFile: false, plugins: [[plugin, {}]], parserOpts: { plugins: ['jsx'] From 823125b2d57c00accd991c6c50fe291822b03909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Wed, 1 Apr 2020 15:04:54 +0800 Subject: [PATCH 06/14] feat: support inline style --- src/babel.config.js | 5 ++++- src/rml-loader.js | 5 +++-- src/template-loader.js | 10 +++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/babel.config.js b/src/babel.config.js index 3d432d7..5e9695e 100644 --- a/src/babel.config.js +++ b/src/babel.config.js @@ -88,7 +88,10 @@ module.exports = (userOptions) => { if (styleSheet) { babelConfigList.push({ plugins: [ - [require.resolve('babel-plugin-transform-jsx-stylesheet'), { retainClassName: true }], + [ + require.resolve('babel-plugin-transform-jsx-stylesheet'), + { retainClassName: true, injectedStyleName: styleSheet } + ], ], }); } diff --git a/src/rml-loader.js b/src/rml-loader.js index 6d4a8ad..c3a808c 100644 --- a/src/rml-loader.js +++ b/src/rml-loader.js @@ -4,6 +4,7 @@ const paths = require('./paths'); const defaultOptions = { renderer: 'react', // Can be replaced with preact/rax/... + inlineStyle: false, // Style should be inlined, default to false. }; /** @@ -15,12 +16,12 @@ module.exports = function RMLLoader(rawContent) { const options = Object.assign({}, defaultOptions, loaderUtils.getOptions(context)); const stringifyRequest = r => loaderUtils.stringifyRequest(context, r); const { resourcePath } = context; - const { renderer } = options; + const { renderer, inlineStyle } = options; const parts = preCompileParts(rawContent, resourcePath); const loadScriptRequest = stringifyRequest(`${paths.partLoader}?part=script!${resourcePath}`); - const loadTemplateRequest = stringifyRequest(`${paths.templateLoader}?renderer=${renderer}!${paths.partLoader}?part=template!${resourcePath}`); + const loadTemplateRequest = stringifyRequest(`${paths.templateLoader}?renderer=${renderer}&inlineStyle=${inlineStyle}!${paths.partLoader}?part=template!${resourcePath}`); const loadStyleRequest = stringifyRequest(`${paths.styleLoader}!${resourcePath}`); let loadData; diff --git a/src/template-loader.js b/src/template-loader.js index 4e78649..92e45d2 100644 --- a/src/template-loader.js +++ b/src/template-loader.js @@ -11,10 +11,10 @@ const GET_CSS_MODULE_NAME = '__get_css_module_name__'; * @param templates * @return {string} */ -module.exports = function(templates) { +module.exports = function (templates) { const { resourcePath } = this; const stringifyRequest = r => loaderUtils.stringifyRequest(this, r); - const { renderer } = Object.assign({}, loaderUtils.getOptions(this)); + const { renderer, inlineStyle } = Object.assign({}, loaderUtils.getOptions(this)); if (!Array.isArray(templates)) { templates = [templates]; } @@ -30,7 +30,7 @@ module.exports = function(templates) { const getCSSModuleNameRuntimeRequest = stringifyRequest(getCSSModuleNameRuntime); extraImports += `\nimport ${GET_CSS_MODULE_NAME} from ${getCSSModuleNameRuntimeRequest};`; } - const jsx = generateJSX(templates, scopeIds, enableCSSModules); + const jsx = generateJSX(templates, scopeIds, enableCSSModules, inlineStyle); return ` import { createElement } from '${renderer}';${imports}${extraImports} @@ -79,7 +79,7 @@ function compile(template, compileOptions, babelConfig) { return babel.transformSync(template, finalTransformOptions); } -function generateJSX(templates, scopeIds, enableCSSModules) { +function generateJSX(templates, scopeIds, enableCSSModules, inlineStyle) { const whiteList = ['createElement', STYLE_IDENTIFIER].concat(scopeIds); if (enableCSSModules) { whiteList.push(GET_CSS_MODULE_NAME); @@ -103,7 +103,7 @@ function generateJSX(templates, scopeIds, enableCSSModules) { ]); } const babelConfig = getBabelConfig({ - styleSheet: true, + styleSheet: inlineStyle ? STYLE_IDENTIFIER : false, override: babelConfigOverride, }); From 4c5b3036b6d3fb4524d54e95fb8534040fabbf3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Wed, 1 Apr 2020 15:12:07 +0800 Subject: [PATCH 07/14] fix: lint pass --- src/template-loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/template-loader.js b/src/template-loader.js index 92e45d2..8a30575 100644 --- a/src/template-loader.js +++ b/src/template-loader.js @@ -11,7 +11,7 @@ const GET_CSS_MODULE_NAME = '__get_css_module_name__'; * @param templates * @return {string} */ -module.exports = function (templates) { +module.exports = function(templates) { const { resourcePath } = this; const stringifyRequest = r => loaderUtils.stringifyRequest(this, r); const { renderer, inlineStyle } = Object.assign({}, loaderUtils.getOptions(this)); From 62a5fe6a02e035b535d5c4ac2e4f140e13f2a58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Thu, 2 Apr 2020 11:32:58 +0800 Subject: [PATCH 08/14] fix: function declaration id should not be replaced --- example/component.rml | 4 ++-- src/__tests__/babel-plugin-with-props.js | 4 ++++ src/babel-plugin-with-props.js | 28 ++++++++++++++++-------- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/example/component.rml b/example/component.rml index 3711f43..413b1cd 100644 --- a/example/component.rml +++ b/example/component.rml @@ -76,11 +76,11 @@ 计算 - {/* */} +