dsh 0.2.0-rc.2: in-container update (experimental channel), path-agnostic compose, upstream patches adapted to 0.1.x/0.2.x
This commit is contained in:
commit
e6dcef9bf5
302 files changed
+75178
No files matched your search
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
|
||||
function replaceOnce(source, pattern, replacement, label) {
|
||||
const next = source.replace(pattern, replacement)
|
||||
if (next === source) throw new Error(`client source is missing ${label}`)
|
||||
return next
|
||||
}
|
||||
|
||||
function cssModule(source, namespace) {
|
||||
const names = [...new Set([...source.matchAll(/\.([A-Za-z_][A-Za-z0-9_-]*)/g)].map(match => match[1]))].sort()
|
||||
const classes = Object.fromEntries(names.map(name => [name, `${namespace}_${name}`]))
|
||||
let css = source
|
||||
for (const name of names.sort((left, right) => right.length - left.length)) {
|
||||
css = css.replace(new RegExp(`\\.${name}(?=[^A-Za-z0-9_-]|$)`, 'g'), `.${classes[name]}`)
|
||||
}
|
||||
return { classes, css }
|
||||
}
|
||||
|
||||
export async function buildSystemPluginClient({ sourcePath, stylePath, pluginId }) {
|
||||
let source = await readFile(sourcePath, 'utf8')
|
||||
const namespace = pluginId === '@dsh-docker/platform-management'
|
||||
? 'dshPlatform'
|
||||
: `dsh${pluginId.split('/').at(-1).split('-').map(part => part[0].toUpperCase() + part.slice(1)).join('')}`
|
||||
const style = cssModule(await readFile(stylePath, 'utf8'), namespace)
|
||||
source = replaceOnce(
|
||||
source,
|
||||
/^import React, \{ useCallback, useEffect, useRef, useState \} from 'react'\n/m,
|
||||
"const React = require('react')\nconst { useCallback, useEffect, useRef, useState } = React\n",
|
||||
'the React import',
|
||||
)
|
||||
source = replaceOnce(source, /^import css from '.\/style\.module\.css'\n/m, '', 'the CSS Module import')
|
||||
source = replaceOnce(source, 'export const inject =', 'const inject =', 'the inject export')
|
||||
source = replaceOnce(source, 'export function apply(ctx)', 'function apply(ctx)', 'the apply export')
|
||||
|
||||
const styleId = `${pluginId}/style.module.css`
|
||||
return [
|
||||
`window.__ModuleLoader__.load({ id: ${JSON.stringify(pluginId)}, factory: (require) => {`,
|
||||
'var module = { exports: {} }; var exports = module.exports;',
|
||||
`const css = Object.freeze(${JSON.stringify(style.classes)});`,
|
||||
`const styleId = ${JSON.stringify(styleId)};`,
|
||||
'if (typeof document !== \'undefined\' && ![...document.querySelectorAll(\'style[data-plugin-css]\')].some(tag => tag.dataset.pluginCss === styleId)) {',
|
||||
' const tag = document.createElement(\'style\');',
|
||||
` tag.dataset.plugin = ${JSON.stringify(pluginId)};`,
|
||||
' tag.dataset.pluginCss = styleId;',
|
||||
` tag.textContent = ${JSON.stringify(style.css)};`,
|
||||
' document.head.appendChild(tag);',
|
||||
'}',
|
||||
source.trim(),
|
||||
'exports.inject = inject;',
|
||||
'exports.apply = apply;',
|
||||
'return module.exports; } });',
|
||||
'',
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
||||
if (process.argv.length !== 6) {
|
||||
console.error('usage: build-system-plugin-client.mjs <plugin-id> <source.js> <style.css> <output.js>')
|
||||
process.exit(64)
|
||||
}
|
||||
const [, , pluginId, sourcePath, stylePath, outputPath] = process.argv
|
||||
await writeFile(outputPath, await buildSystemPluginClient({ sourcePath, stylePath, pluginId }))
|
||||
}
|
||||
Reference in new issue
Block a user