-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: new generateStylableJSModuleSource api (#2660)
- Loading branch information
Showing
11 changed files
with
202 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,7 @@ | ||
/**@deprecated */ | ||
export { createModuleSource, generateModuleSource } from './module-source'; | ||
|
||
export { Options, stylableModuleFactory } from './module-factory'; | ||
export { generateDTSContent } from './generate-dts'; | ||
export { generateDTSSourceMap } from './generate-dts-sourcemaps'; | ||
export { generateStylableJSModuleSource } from './stylable-js-module-source'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,46 @@ | ||
import { Stylable, StylableConfig } from '@stylable/core'; | ||
import { generateModuleSource } from './module-source'; | ||
import { generateStylableJSModuleSource } from './stylable-js-module-source'; | ||
|
||
export interface Options { | ||
injectCSS: boolean; | ||
staticImports: string[]; | ||
runtimePath: string; | ||
runtimeStylesheetId: 'module' | 'namespace'; | ||
injectCSS: boolean; | ||
moduleType: 'esm' | 'cjs'; | ||
runtimeId: string; | ||
/**@deprecated not in use */ | ||
renderableOnly: boolean; | ||
staticImports: string[]; | ||
} | ||
|
||
export function stylableModuleFactory( | ||
stylableOptions: StylableConfig, | ||
{ | ||
runtimePath = '@stylable/runtime', | ||
runtimePath, | ||
runtimeStylesheetId = 'module', | ||
injectCSS = true, | ||
renderableOnly = false, | ||
staticImports = [], | ||
moduleType = 'cjs', | ||
runtimeId = '0', | ||
}: Partial<Options> = {} | ||
) { | ||
const stylable = new Stylable(stylableOptions); | ||
return function stylableToModule(source: string, path: string) { | ||
const meta = stylable.analyze(path, source); | ||
const res = stylable.transform(meta); | ||
return generateModuleSource( | ||
res, | ||
runtimeStylesheetId === 'module' ? 'module.id' : res.meta.namespace, | ||
[ | ||
...staticImports.map((request) => `import ${JSON.stringify(request)}`), | ||
`const runtime = require(${JSON.stringify(runtimePath)})`, | ||
], | ||
`runtime.$`, | ||
`runtime.create`, | ||
`runtime.createRenderable`, | ||
injectCSS ? JSON.stringify(res.meta.targetAst!.toString()) : '""', | ||
'-1', // ToDo: calc depth for node as well | ||
'module.exports', | ||
'' /* afterModule */, | ||
renderableOnly | ||
const { meta, exports } = stylable.transform(stylable.analyze(path, source)); | ||
return generateStylableJSModuleSource( | ||
{ | ||
moduleType: moduleType, | ||
imports: staticImports.map((from) => ({ from })), | ||
jsExports: exports, | ||
namespace: meta.namespace, | ||
runtimeRequest: runtimePath, | ||
varType: 'var', | ||
}, | ||
{ | ||
id: runtimeStylesheetId === 'module' ? undefined : meta.namespace, | ||
css: injectCSS ? meta.targetAst!.toString() : '', | ||
depth: -1, | ||
runtimeId, | ||
} | ||
); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import type { StylableExports } from '@stylable/core/dist/index-internal'; | ||
|
||
interface InjectCSSOptions { | ||
/** | ||
* omitting the id will fallback to module.id/import.meta.url | ||
*/ | ||
id?: string | undefined; | ||
/** | ||
* css string to inject | ||
*/ | ||
css: string; | ||
/** | ||
* calculated style depth | ||
*/ | ||
depth: number | string; | ||
/** | ||
* use code to get the depth | ||
*/ | ||
depthCode?: string; | ||
/** | ||
* reconciliation will happen only for style with the same runtimeId | ||
*/ | ||
runtimeId: string; | ||
} | ||
|
||
interface ModuleOptions { | ||
/** | ||
* module namespace | ||
*/ | ||
namespace: string; | ||
/** | ||
* static imports for the module | ||
*/ | ||
imports?: Array<{ from: string }>; | ||
/** | ||
* Stylable transforms exports | ||
*/ | ||
jsExports: StylableExports | { [K in keyof StylableExports]: string }; | ||
/** | ||
* the request of the module runtime api e.g @stylable/runtime | ||
*/ | ||
runtimeRequest?: string; | ||
/** | ||
* target module format | ||
*/ | ||
moduleType: 'esm' | 'cjs'; | ||
/** | ||
* es3 compat mode | ||
*/ | ||
varType?: 'const' | 'var'; | ||
/** | ||
* inject code immediately after imports | ||
*/ | ||
header?: string; | ||
/** | ||
* inject code after the entire module code | ||
*/ | ||
footer?: string; | ||
} | ||
|
||
export function generateStylableJSModuleSource( | ||
moduleOptions: ModuleOptions, | ||
injectOptions?: InjectCSSOptions | ||
) { | ||
const { | ||
namespace, | ||
imports = [], | ||
jsExports, | ||
moduleType, | ||
runtimeRequest, | ||
varType = 'const', | ||
header = '', | ||
footer = '', | ||
} = moduleOptions; | ||
|
||
const { classes, keyframes, layers, stVars, vars } = jsExports; | ||
const exportKind = moduleType === 'esm' ? `export ${varType} ` : 'module.exports.'; | ||
return ` | ||
${imports.map(moduleRequest(moduleType)).join('\n')} | ||
${runtimeImport(moduleType, runtimeRequest, injectOptions)} | ||
${header} | ||
${varType} _namespace_ = ${JSON.stringify(namespace)}; | ||
${varType} _style_ = /*#__PURE__*/ classesRuntime.bind(null, _namespace_); | ||
${exportKind}cssStates = /*#__PURE__*/ statesRuntime.bind(null, _namespace_); | ||
${exportKind}style = /*#__PURE__*/ _style_; | ||
${exportKind}st = /*#__PURE__*/ _style_; | ||
${exportKind}namespace = _namespace_; | ||
${exportKind}classes = ${JSON.stringify(classes)}; | ||
${exportKind}keyframes = ${JSON.stringify(keyframes)}; | ||
${exportKind}layers = ${JSON.stringify(layers)}; | ||
${exportKind}stVars = ${JSON.stringify(stVars)}; | ||
${exportKind}vars = ${JSON.stringify(vars)}; | ||
${runtimeExecuteInject(moduleType, injectOptions)} | ||
${footer} | ||
`; | ||
} | ||
|
||
function moduleRequest(moduleType: 'esm' | 'cjs') { | ||
return (moduleRequest: { from: string }) => { | ||
const request = JSON.stringify(moduleRequest.from); | ||
return moduleType === 'esm' ? `import ${request};` : `require(${request});`; | ||
}; | ||
} | ||
|
||
function runtimeImport( | ||
moduleType: 'esm' | 'cjs', | ||
runtimeRequest: string | undefined, | ||
injectOptions: InjectCSSOptions | undefined | ||
) { | ||
const importInjectCSS = injectOptions?.css ? `, injectCSS` : ''; | ||
const request = JSON.stringify( | ||
runtimeRequest ?? | ||
// TODO: we use direct requests here since we don't know how this will be resolved | ||
(moduleType === 'esm' | ||
? '@stylable/runtime/esm/runtime' | ||
: '@stylable/runtime/dist/runtime') | ||
); | ||
return moduleType === 'esm' | ||
? `import { classesRuntime, statesRuntime${importInjectCSS} } from ${request};` | ||
: `const { classesRuntime, statesRuntime${importInjectCSS} } = require(${request});`; | ||
} | ||
|
||
function runtimeExecuteInject( | ||
moduleType: 'esm' | 'cjs', | ||
injectOptions: InjectCSSOptions | undefined | ||
) { | ||
if (!injectOptions?.css) { | ||
return ''; | ||
} | ||
const { id, css, depthCode, depth, runtimeId } = injectOptions; | ||
|
||
let out = 'injectCSS('; | ||
out += id ? JSON.stringify(id) : moduleType === 'esm' ? 'import.meta.url' : 'module.id'; | ||
out += ', '; | ||
out += JSON.stringify(css); | ||
out += ', '; | ||
out += depthCode || JSON.stringify(depth) || '-1'; | ||
out += ', '; | ||
out += JSON.stringify(runtimeId); | ||
out += ');'; | ||
return out; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,4 +44,5 @@ export function injectStyles(host: Host) { | |
} | ||
} | ||
host.sti = stylableRuntime; | ||
return host; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters