@lls/vitescripts 1.0.0-128c53cdd

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # viteScripts
2
+
3
+ lls vite plugins
4
+
5
+ Purpose is to factorize vite plugin scripts
6
+
7
+ ## deploy
8
+
9
+ ```
10
+ npm version patch
11
+ git push && git push origin $(git describe --tags --abbrev=0)
12
+ npm publish
13
+ ```
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@lls/vitescripts",
3
+ "version": "1.0.0-128c53cdd",
4
+ "description": "lls vite plugins",
5
+ "main": "src/index.mjs",
6
+ "files": [
7
+ "src/"
8
+ ],
9
+ "dependencies": {
10
+ "lightningcss": "1.22.1",
11
+ "esbuild-plugin-lightningcss-modules": "0.1.1",
12
+ "browserslist": "4.22.1"
13
+ },
14
+ "type": "module",
15
+ "author": "",
16
+ "license": "ISC",
17
+ "devDependencies": {
18
+ "@lls/eslint-config-lls": "1.1.12",
19
+ "@lls/lls-kit": "23.0.0",
20
+ "nano-staged": "0.8.0",
21
+ "vitest": "0.34.6"
22
+ },
23
+ "nano-staged": {
24
+ "*.{js,jsx,mjs,tsx,ts}": "CONF_ENV=test pnpm vitest related --run"
25
+ },
26
+ "scripts": {
27
+ "test": "CONF_ENV=test pnpm vitest run",
28
+ "precommit": "pnpm nano-staged"
29
+ }
30
+ }
@@ -0,0 +1,43 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import llsCssModuleMacroPlugin from './llsCssModuleMacroPlugin.mjs'
4
+ import { cssModules } from 'esbuild-plugin-lightningcss-modules'
5
+
6
+ export default ({ prefix = '', llsCssModuleMacroPluginArg }) => {
7
+ const esbuildCssModule = cssModules({
8
+ targets: { chrome: 80 << 16 },
9
+ drafts: { nesting: true },
10
+ cssModulesPattern: `${prefix ? prefix + '-' : ''}[hash]-[local]`
11
+ })
12
+ const tmpDir = path.join(process.cwd(), 'tmp_esbuild')
13
+ return [
14
+ {
15
+ name: 'lls-cssmodule',
16
+ async setup (build) {
17
+ await fs.promises.mkdir(tmpDir, { recursive: true })
18
+ const llsCssModuleMacroPluginInstance = await llsCssModuleMacroPlugin(llsCssModuleMacroPluginArg)
19
+
20
+ // need to add the generated files to esbuild pipeline
21
+ build.onResolve({ filter: /tmp_esbuild/ }, async args => {
22
+ return { path: args.path }
23
+ })
24
+ build.onLoad({ filter: /module\.css$/ }, async args => {
25
+ if (args.path.startsWith(tmpDir)) return
26
+
27
+ const contents = await fs.promises.readFile(args.path, 'utf8').then(str => llsCssModuleMacroPluginInstance.transform(str, args.path))
28
+ const id = args.path.replace(process.cwd(), '').replace(/\//g, '_')
29
+ const out = path.join(tmpDir, id)
30
+ await fs.promises.writeFile(out, contents)
31
+ return {
32
+ contents: `export { default } from '${out}'`,
33
+ loader: 'js'
34
+ }
35
+ })
36
+ build.onEnd(async () => {
37
+ await fs.promises.rm(tmpDir, { recursive: true })
38
+ })
39
+ }
40
+ },
41
+ esbuildCssModule
42
+ ]
43
+ }
package/src/index.mjs ADDED
@@ -0,0 +1,11 @@
1
+ export { default as llsAssetsPlugin } from './llsAssetsPlugin.mjs'
2
+ export { default as llsLinariaImportsPlugin } from './llsLinariaImportsPlugin.mjs'
3
+ export { default as llsCssSsrCollectPlugin } from './llsCssSsrCollectPlugin.mjs'
4
+ export { default as llsRequirePlugin } from './llsRequirePlugin.mjs'
5
+ export { default as llsSideRefreshMetaPlugin } from './llsSideRefreshMetaPlugin.mjs'
6
+ export { default as llsVitestMockPlugin } from './llsVitestMockPlugin.mjs'
7
+ export { default as llsLadlePlugin } from './llsLadlePlugin.mjs'
8
+ export { default as llsCssModuleMacroPlugin } from './llsCssModuleMacroPlugin.mjs'
9
+ export { default as postBuildAutoprefixerPlugin } from './postBuildAutoprefixerPlugin.mjs'
10
+ export { default as esbuildCssModulePlugin } from './esbuildCssModulePlugin.mjs'
11
+ export { default as postBuildTsTypesPlugin } from './postBuildTsTypes.mjs'
@@ -0,0 +1,74 @@
1
+ import fs from 'fs'
2
+ import { promisify } from 'util'
3
+ import { exec } from 'node:child_process'
4
+ import path from 'path'
5
+ const execP = promisify(exec)
6
+
7
+ // https://github.com/vitejs/vite/pull/8574
8
+ /**
9
+ * Plugin that will copy assets from given repos to public dir of launched project
10
+ * @param {*} llsRepos array containing names of the repos
11
+ * @param {*} publicDir public dir to copy assets to
12
+ * @returns config() method that copies assets
13
+ * transform() method that replaces assets path to be resolved
14
+ */
15
+ const llsAssetsPlugin = (llsRepos, publicDir = 'ladleassets', { stripRoot = true } = {}) => {
16
+ const publicAssetDir = path.join(publicDir, 'assets')
17
+ const fileExists = (s) => new Promise(resolve => fs.access(s, e => resolve(!e)))
18
+ const srcRoot = process.cwd() + '/src'
19
+ const storyRoot = process.cwd() + '/stories'
20
+ return {
21
+ name: 'lls:copyassets',
22
+ async config () {
23
+ await execP(`mkdir -p ${publicAssetDir}`)
24
+ const pnpmNameToPath = await execP('pnpm ls -r @lls/lls-drawer --json'/*'pnpm ls -r -d 0 --json'*/)
25
+ .then(({ stdout }) => JSON.parse(stdout))
26
+ .then(json => {
27
+ let drawer = null
28
+ const back = json.map(({ name, path, dependencies }) => {
29
+ if (dependencies?.['@lls/lls-drawer']?.path) {
30
+ drawer = ['@lls/lls-drawer', dependencies?.['@lls/lls-drawer']?.path + '/lib/assets/*']
31
+ }
32
+ return [name, path + '/lib/assets/*']
33
+ })
34
+ return back.concat(drawer ? [drawer] : [])
35
+ })
36
+ .then(Object.fromEntries)
37
+ .catch(e => {})
38
+ const repoArgs = await Promise.all(llsRepos.map(async repo => {
39
+ if (!repo.startsWith('@')) return repo
40
+ const pnpmPath = pnpmNameToPath[repo]
41
+ if (pnpmPath) return pnpmPath
42
+
43
+ const aPath = 'lib/assets/*'
44
+ const prefix = await fileExists(`${process.cwd()}/node_modules/${repo}`)
45
+ ? `${process.cwd()}/node_modules/${repo}`
46
+ : `${process.cwd()}/node_modules/.pnpm/${repo}`
47
+ return path.join(prefix, aPath)
48
+ }))
49
+ repoArgs.push('static/assets/*')
50
+ for (const repo of repoArgs) {
51
+ await execP(`cp -rf ${repo} ${publicAssetDir}`)
52
+ }
53
+ },
54
+ ...(stripRoot && {
55
+ transform (src, id) {
56
+ if (
57
+ llsRepos.some(repo => id.includes(repo)) ||
58
+ id.startsWith(srcRoot) ||
59
+ id.startsWith(storyRoot)
60
+ ) {
61
+ // workaround because we don't use /assets (maybe we should ?)
62
+ // specs orders than relative path in css is current container
63
+ // so use relative path instead of / being the "fqdn"
64
+ return {
65
+ code: src.replace(/(= |url\(|Worker\()(['"])\/assets/g, '$1$2assets'),
66
+ map: null
67
+ }
68
+ }
69
+ }
70
+ })
71
+ }
72
+ }
73
+
74
+ export default llsAssetsPlugin
@@ -0,0 +1,140 @@
1
+ import { transform as lightTransform } from 'lightningcss'
2
+ import { makeSideRefreshThemeInterceptor } from './llsSideRefreshMetaPlugin.mjs'
3
+
4
+ const llsCssModuleMacroPlugin = async ({ themeIsFreeMode, themeIsDarkMode, themeIsNotDarkMode, sideRefreshActiveModules = [] }) => {
5
+ const keepProperties = [
6
+ 'Supporting',
7
+ 'Button1',
8
+ 'Button2',
9
+ 'Body1',
10
+ 'Body2',
11
+ 'Body3',
12
+ 'RippleEffect',
13
+ 'Heading1',
14
+ 'Heading2',
15
+ 'Heading3',
16
+ 'Heading4',
17
+ 'ThemeCss',
18
+ 'FontFamily'
19
+ ]
20
+ const kitBag = await import('@lls/lls-kit')
21
+ .then(m => m.default || m)
22
+ .then(obj => Object.fromEntries(keepProperties.map(property => [property, obj[property]])))
23
+
24
+ const cssMacroTheme = {
25
+ themeIsFreeMode,
26
+ themeIsDarkMode,
27
+ themeIsNotDarkMode,
28
+ dark: themeIsDarkMode,
29
+ free: themeIsFreeMode,
30
+ light: themeIsNotDarkMode
31
+ }
32
+ const replaceKitBag = (__, cap) => kitBag[cap]
33
+
34
+ const interceptSideRefreshTheme = await makeSideRefreshThemeInterceptor(sideRefreshActiveModules)
35
+ // replaces dark from @llsTheme(dark) with proper css macro
36
+ const replaceTheme = (cap, id) => {
37
+ // try to resolve proper macro from siderefreshed directory
38
+ // otherwise defaults to standard resolving
39
+ return interceptSideRefreshTheme(cap, id, (cap) => {
40
+ const back = cssMacroTheme[cap]
41
+ if (!back) {
42
+ throw new Error('llsCssModuleMacroPlugin::missing definition for ' + cap)
43
+ }
44
+ return back
45
+ })
46
+ }
47
+ const replaceGetFluidSize = (__, cap) => {
48
+ const args = {
49
+ minViewport: 320, // BREAKPOINT_XXS
50
+ maxViewport: 1280, // BREAKPOINT_MD
51
+ minSize: undefined,
52
+ maxSize: undefined
53
+ }
54
+ for (const a of cap.matchAll(/(?<prop>maxSize|minSize|minViewport|maxViewport)\s*:\s*(?<value>.+?)(?=[,]|\s|$)/g)) {
55
+ args[a.groups.prop] = a.groups.value
56
+ }
57
+ const { maxSize, minSize, minViewport, maxViewport } = args
58
+ return `min(${maxSize}px, max(${minSize}px, calc(${minSize}px + (${maxSize} - ${minSize}) * ((100vw - ${minViewport}px) / (${maxViewport} - ${minViewport})))))`
59
+ }
60
+
61
+ // lightningcss helpers
62
+ const token = (type) => ({ type: 'token', value: { type } })
63
+ const delim = (operator) => ({ type: 'token', value: { type: 'delim', value: operator } })
64
+ const length = (value, unit) => ({ type: 'length', value: { value, unit } })
65
+ const func = (name, args) => ({ type: 'function', value: { name, arguments: args } })
66
+ const num = value => ({ type: 'token', value: { type: 'number', value } })
67
+ return {
68
+ enforce: 'pre',
69
+ transform (src, id) {
70
+ if (!/module\.css(\?.*)?$/.test(id)) {
71
+ return undefined
72
+ }
73
+ const back = src
74
+ .replace(/@cx\((Body[123]|Heading[1234]|Button[12]|Supporting|RippleEffect|FontFamily)\)/g, replaceKitBag)
75
+ .replace(/\${(Body[123]|Heading[1234]|Button[12]|Supporting|RippleEffect|FontFamily)}/g, replaceKitBag)
76
+ .replace(/\${(themeIsFreeMode|themeIsDarkMode|themeIsNotDarkMode)}/g, (__, cap) => replaceTheme(cap, id))
77
+ .replace(/@llsTheme\((dark|light|free)\)/g, (__, cap) => replaceTheme(cap, id))
78
+
79
+ .replace(/\${getFluidSize\({(.*?)}\)}/gs, replaceGetFluidSize)
80
+ .replace(/\${getTruePx\((.*?)\)}?/g, 'calc(var(--size-index, 1) * $1 * 1px)')
81
+
82
+ const { code } = lightTransform({
83
+ code: Buffer.from(back),
84
+ visitor: {
85
+ Function: {
86
+ getTruePx ({ arguments: [value] }) {
87
+ return {
88
+ type: 'function',
89
+ value: {
90
+ name: 'calc',
91
+ arguments: [
92
+ value.type !== 'token' && token('parenthesis-block'),
93
+ value,
94
+ value.type !== 'token' && token('close-parenthesis'),
95
+ delim('*'),
96
+ { type: 'var', value: { name: { ident: '--size-index', from: null }, fallback: [{ type: 'token', value: { type: 'number', value: 1 } }] } },
97
+ delim('*'),
98
+ length(1, 'px')
99
+ ].filter(Boolean)
100
+ }
101
+ }
102
+ },
103
+ getFluidSize ({ arguments: [minSize, comma1, maxSize, comma2, iMinViewport, comma3, iMaxViewport] }) {
104
+ const minViewport = (typeof (iMinViewport) === 'undefined' || iMinViewport.value?.type === 'comma') ? length(320, 'px') : iMinViewport
105
+ const max = iMinViewport?.value?.type === 'comma' ? comma3 : iMaxViewport
106
+ const maxViewport = typeof (max) === 'undefined' ? length(1280, 'px') : max
107
+ return func('min', [
108
+ maxSize,
109
+ token('comma'),
110
+ func('max', [
111
+ minSize,
112
+ token('comma'),
113
+ func('calc', [
114
+ minSize,
115
+ delim('+'),
116
+ num(maxSize?.value?.value - minSize?.value?.value),
117
+ delim('*'),
118
+ token('parenthesis-block'),
119
+ token('parenthesis-block'),
120
+ length(100, 'vw'),
121
+ delim('-'),
122
+ minViewport,
123
+ token('close-parenthesis'),
124
+ delim('/'),
125
+ num(maxViewport?.value?.value - minViewport?.value.value),
126
+ token('close-parenthesis')
127
+ ])
128
+ ])
129
+ ])
130
+ }
131
+ }
132
+ }
133
+ })
134
+
135
+ return code.toString()
136
+ }
137
+ }
138
+ }
139
+
140
+ export default llsCssModuleMacroPlugin
@@ -0,0 +1,25 @@
1
+ /**
2
+ * flushStyles() method that generates and return <style> tag with refreshed style
3
+ */
4
+ import { transform } from 'lightningcss'
5
+ const llsCssSsrCollectPlugin = () => {
6
+ const cssIds = new Map()
7
+ return {
8
+ name: 'lls:llsCssSsrCollectPlugin',
9
+ transform (src, id) {
10
+ if (/module\.css$/.test(id)) {
11
+ cssIds.set(id, src)
12
+ }
13
+ },
14
+ flushStyles () {
15
+ const css = [...cssIds.values()].join('\n')
16
+
17
+ // when hmr, id changes but not css-selector so we get two rules with the same css-selector
18
+ // we dedupe the rules so old rule is now stripped.
19
+ const { code } = transform({ code: Buffer.from(css) })
20
+ return `<style id="cssmodule-ssr-collect-plugin">${code.toString()}</style>`
21
+ }
22
+ }
23
+ }
24
+
25
+ export default llsCssSsrCollectPlugin
@@ -0,0 +1,16 @@
1
+ const llsLadlePlugin = (sbFolder) => ({
2
+ name: 'lls:llsLadlePlugin',
3
+ config (config, { command }) {
4
+ const ladleCiEnv = /prod|tag|master|v\d/.test(process.env.LADLE_DEST) ? 'prod' : 'dev'
5
+ return {
6
+ base: command === 'serve' ? '/' : `https://build.lelivrescolaire.fr/storybook/${sbFolder}-${ladleCiEnv}/`,
7
+ // base: command === 'serve' ? '/' : 'http://localhost:5000/ladledist/',
8
+
9
+ build: {
10
+ minify: false
11
+ }
12
+ }
13
+ }
14
+ })
15
+
16
+ export default llsLadlePlugin
@@ -0,0 +1,19 @@
1
+ const llsLinariaImports = ({ client } = {}) => {
2
+ return {
3
+ name: 'lls:linaria-imports',
4
+ load (id) {
5
+ console.log('llsLinariaImports plugin is deprecated, remove usage. Already handled by llsSideRefreshMetaPlugin')
6
+ if (client) return
7
+ if (id.endsWith('@lls/viewer/lib/assets/viewer.css')) { return '' }
8
+ if (id.endsWith('@lls/superkit/lib/assets/superkit.css')) { return '' }
9
+ if (id.endsWith('@lls/lls-kit/lib/assets/lls-kit.css') || id.endsWith('@lls/lls-kit/lib/assets/lls-kit-fonts.css')) {
10
+ return ''
11
+ }
12
+ if (id.endsWith('@lls/lls-drawer/lib/assets/lls-drawer.css')) { return '' }
13
+ if (id.endsWith('@lls/lls-code/lib/assets/lls-code.css')) { return '' }
14
+ if (id.endsWith('@lls/core/lib/assets/core.css')) { return '' }
15
+ }
16
+ }
17
+ }
18
+
19
+ export default llsLinariaImports
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Plugin that collects styles from linaria cache to inject it in the page.
3
+ * @returns config() method that instantiates linariaPlugin
4
+ * resolveId() method that filters files to be added to css set
5
+ * flushStyles() method that generates and return <style> tag with refreshed style
6
+ */
7
+ import { transform } from 'lightningcss'
8
+ const llsLinariaSsrCollectPlugin = () => {
9
+ const cssIds = new Set()
10
+ let linariaPlugin
11
+ return {
12
+ name: 'lls:llsLinariaSsrCollect',
13
+ /* we enforce pre because if vite-plugin-linaria resolves id, vite4 won't call us. Since we do not resolve, we can be put before */
14
+ enforce: 'pre',
15
+ config (config) {
16
+ linariaPlugin = config.plugins.find(plugin => plugin.name === 'linaria')
17
+ },
18
+ async resolveId (id, from) {
19
+ if (id.includes('@linaria-cache')) { cssIds.add(id) }
20
+ },
21
+ flushStyles () {
22
+ const css = [...cssIds].map(linariaPlugin.load).join('\n')
23
+
24
+ // when hmr, id changes but not css-selector so we get two rules with the same css-selector
25
+ // we dedupe the rules so old rule is now stripped.
26
+ const { code } = transform({ code: Buffer.from(css) })
27
+ return `<style id="linaria-ssr-collect-plugin">${code.toString()}</style>`
28
+ }
29
+ }
30
+ }
31
+
32
+ export default llsLinariaSsrCollectPlugin
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Plugin using vite-plugin-require-transform, used to transform require syntax to import
3
+ * Needed when we use viewer in sideRefresh
4
+ * @returns the plugin with its transform method
5
+ */
6
+ const llsSsrRequirePlugin = async () => {
7
+ const VitePluginRequireTransform = await import('vite-plugin-require-transform').then(m => m.default)
8
+ // Lazy loaded viewer modules that are using require syntax
9
+ const fileRegex = /(?:(Audio|Playlist|Recorder|Python|Video|QuestionRich|CodemirrorEditor|useLazyModule)\.jsx$|@lls_lls-code)/
10
+ const back = VitePluginRequireTransform({ fileRegex })
11
+ return {
12
+ name: 'lls:require',
13
+ transform: async function (code, id) {
14
+ const { transform } = await back
15
+ if (fileRegex.test(id)) {
16
+ code = code.replace(/interop\(require\(['"][^'"]+\.browser['"]\)\)/, '() => null')
17
+ }
18
+ return {
19
+ ...await transform.apply(this, [code, id]),
20
+ map: null
21
+ }
22
+ }
23
+ }
24
+ }
25
+
26
+ export default llsSsrRequirePlugin
@@ -0,0 +1,149 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+
4
+ // sideRefreshActiveModules is of the form ['viewer', 'superkit', ...] with 'viewer' if repo launched
5
+ // WITH_VIEWER=1 npm start
6
+ export const makeSideRefreshThemeInterceptor = async (sideRefreshActiveModules) => {
7
+ const parentDir = path.basename(path.dirname(process.cwd()))
8
+ const sideRefreshThemes = {}
9
+ if (sideRefreshActiveModules.length) {
10
+ const cssThemeMap = {
11
+ viewer: '@lls/viewer/lib/css-bare.mjs',
12
+ // kit: no themes for kit
13
+ superkit: '@lls/superkit/lib/css-bare.mjs',
14
+ core: '@lls/core/lib/css-bare.mjs',
15
+ audio: '@lls/lls-audio/lib/css-bare.mjs',
16
+ code: '@lls/lls-code/lib/css-bare.mjs'
17
+ }
18
+ await Promise.all(sideRefreshActiveModules.map(sideRefreshName => {
19
+ if (!cssThemeMap[sideRefreshName]) {
20
+ throw new Error('invalid side refresh name' + sideRefreshName)
21
+ }
22
+ return import(cssThemeMap[sideRefreshName]).then(m => {
23
+ const mod = m.default || m
24
+ sideRefreshThemes[`${sideRefreshName}_dark`] = mod.themeIsDarkMode
25
+ sideRefreshThemes[`${sideRefreshName}_free`] = mod.themeIsFreeMode
26
+ sideRefreshThemes[`${sideRefreshName}_light`] = mod.themeIsNotDarkMode
27
+ })
28
+ }))
29
+ }
30
+ const folderRegex = new RegExp(Object.keys(sideRefreshThemes).map(capName => parentDir + '/' + capName.split('_')[0]).join('|'))
31
+ return (cap, id, next) => {
32
+ const match = id.match(folderRegex)?.[0]
33
+ cap = match ? `${match.split('/')[1]}_${cap}` : cap
34
+ return match && sideRefreshThemes[cap] ? sideRefreshThemes[cap] : next(cap)
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Side refresh plugin for LLS clients
40
+ * @param {*} param specifies which dependency is beign sideRefreshed
41
+ * @returns a plugin to pass to vite and aliases for sideRefreshed packages
42
+ */
43
+ const llsSideRefreshMetaPlugin = ({ audio: iAudio, viewer: iViewer, superkit: iSuperkit, kit: iKit, utils: iUtils, core: iCore, code: iCode }, { client, publicDir = 'ladleassets' } = {}) => {
44
+ const pwd = process.cwd()
45
+ let activeModules = []
46
+ if ([iViewer, iSuperkit, iKit, iUtils, iCore, iCode, iAudio].some(x => x)) {
47
+ activeModules = [
48
+ iViewer && 'viewer',
49
+ iSuperkit && 'superkit',
50
+ iKit && 'kit',
51
+ iUtils && 'utils',
52
+ iCore && 'core',
53
+ iCode && 'code',
54
+ iAudio && 'audio'
55
+ ].filter(Boolean)
56
+ // eslint-disable-next-line no-console
57
+ console.log('sideResfresh: ', activeModules)
58
+ }
59
+
60
+ const makeResolver = (dirname, aliasImport) => {
61
+ const projectPath = path.resolve(pwd, '../', dirname)
62
+ const projectDir = path.join(projectPath, 'src/')
63
+ const projectDirs = fs.readdirSync(projectDir).map(x => x.replace(/\.[jt]sx?$/, ''))
64
+ return {
65
+ async resolve (id, from) {
66
+ if (projectDirs.some(dir => id.startsWith(dir))) {
67
+ try {
68
+ const resolution = await this.resolve(projectDir + id, from, { skipSelf: true })
69
+ return resolution.id
70
+ } catch (e) {
71
+ }
72
+ }
73
+ },
74
+ alias: {
75
+ // kit has no public/assets folder, and should fallback to next case (/lib)
76
+ ...(dirname === 'lls-kit'
77
+ ? {}
78
+ : { ['@lls/' + dirname + '/lib/assets']: path.join(projectPath, 'static/assets') }
79
+ ),
80
+ // handle multiple cases : @lls/superkit/lib, @lls/superkit, @superkit, or alias import
81
+ ['@lls/' + dirname + '/lib']: path.join(projectPath, 'src'),
82
+ ['@lls/' + dirname]: path.join(projectPath, 'src/index'),
83
+ ['@' + dirname]: path.join(projectPath, 'src'),
84
+ [aliasImport || '@' + dirname]: path.join(projectPath, 'src')
85
+ },
86
+ shouldResolve (from) {
87
+ return from.includes(dirname)
88
+ }
89
+ }
90
+ }
91
+ const makeNoopResolver = () => ({
92
+ shouldResolve: () => false,
93
+ alias: {}
94
+ })
95
+ const viewer = (iViewer && makeResolver('viewer')) || makeNoopResolver()
96
+ const superkit = (iSuperkit && makeResolver('superkit')) || makeNoopResolver()
97
+ const kit = (iKit && makeResolver('lls-kit', '@kit')) || makeNoopResolver()
98
+ const utils = (iUtils && makeResolver('utils', 'commons')) || makeNoopResolver()
99
+ const core = (iCore && makeResolver('core', '@core')) || makeNoopResolver()
100
+ const code = (iCode && makeResolver('lls-code', '@code')) || makeNoopResolver()
101
+ const audio = (iAudio && makeResolver('lls-audio', '@audio')) || makeNoopResolver()
102
+
103
+ const VIRTUAL_ID = 'sideRefresh/node_modules' // specify node_modules to bypass linaria plugin parsing css file... (cant tweak exclude regex)
104
+ const key = basename => path.join(pwd, publicDir, 'assets', basename)
105
+ const loads = new Map(['core.css', 'viewer.css', 'superkit.css', 'lls-kit.css', 'lls-kit-fonts.css', 'lls-audio.css', 'lls-code.css', 'lls-audio.css'].map(basename => {
106
+ let promise = ''
107
+ const getPromise = () => {
108
+ if (client && !pwd.includes(basename.replace('.css', ''))) {
109
+ promise = fs.promises.readFile(key(basename), 'utf8')
110
+ }
111
+ return promise
112
+ }
113
+ return [VIRTUAL_ID + key(basename), getPromise]
114
+ }))
115
+ const plugin = () => ({
116
+ name: 'lls:sideRefresh',
117
+ async resolveId (id, from) {
118
+ const basename = path.basename(id)
119
+ if (['core.css', 'viewer.css', 'superkit.css', 'lls-kit.css', 'lls-kit-fonts.css', 'lls-audio.css', 'lls-code.css', 'lls-audio.css'].includes(basename)) {
120
+ return VIRTUAL_ID + key(basename)
121
+ }
122
+ if (viewer.shouldResolve(from)) { return viewer.resolve.call(this, id, from) }
123
+ if (superkit.shouldResolve(from)) { return superkit.resolve.call(this, id, from) }
124
+ if (kit.shouldResolve(from)) { return kit.resolve.call(this, id, from) }
125
+ if (utils.shouldResolve(from)) { return utils.resolve.call(this, id, from) }
126
+ if (core.shouldResolve(from)) { return core.resolve.call(this, id, from) }
127
+ if (code.shouldResolve(from)) { return code.resolve.call(this, id, from) }
128
+ if (audio.shouldResolve(from)) { return audio.resolve.call(this, id, from) }
129
+ },
130
+
131
+ async load (id) {
132
+ if (loads.has(id)) {
133
+ return loads.get(id)()
134
+ }
135
+ }
136
+ })
137
+ const alias = {
138
+ ...viewer.alias,
139
+ ...superkit.alias,
140
+ ...kit.alias,
141
+ ...utils.alias,
142
+ ...core.alias,
143
+ ...code.alias,
144
+ ...audio.alias
145
+ }
146
+ return { plugin, alias, activeModules }
147
+ }
148
+
149
+ export default llsSideRefreshMetaPlugin
@@ -0,0 +1,14 @@
1
+ const llsVitestMock = () => ({
2
+ name: 'lls:vitestmock',
3
+ transform (code, id) {
4
+ if (id.endsWith('@lls/viewer/lib/index.js')) {
5
+ return code
6
+ .replace(/require\("(@lls\/lls-audio|@lls\/lls-code|@yorab\/react-paint)"\)/g, (__, cap) => {
7
+ if (cap === '@lls/lls-audio') return '{__esModule: true, default: () => null, Recorder: () => null}'
8
+ return '{__esModule: true, default: () => null}'
9
+ })
10
+ }
11
+ }
12
+ })
13
+
14
+ export default llsVitestMock
@@ -0,0 +1,15 @@
1
+ import fs from 'fs'
2
+
3
+ const esbuildAutoprefixerPlugin = async ({ from, to, lightningcssOptions: { minify = false } = {} }) => {
4
+ const [{ transform, browserslistToTargets }, browserslist] = await Promise.all([import('lightningcss'), import('browserslist').then(m => m.default)])
5
+ const contents = await fs.promises.readFile(from).then(async buf => {
6
+ const { code } = transform({
7
+ code: buf,
8
+ targets: browserslistToTargets(browserslist('cover 99.5%')),
9
+ minify
10
+ })
11
+ return code.toString()
12
+ })
13
+ return fs.promises.writeFile(to, contents)
14
+ }
15
+ export default esbuildAutoprefixerPlugin
@@ -0,0 +1,36 @@
1
+ import fs from 'node:fs/promises'
2
+ import path from 'path'
3
+ import { exec } from 'child_process'
4
+ import util from 'util'
5
+ const execp = util.promisify(exec)
6
+
7
+ const getDirectoryFileNames = async directory => {
8
+ const fileNames = []
9
+ const filesInDirectory = await fs.readdir(directory)
10
+ for (const fileName of filesInDirectory) {
11
+ const absolute = path.join(directory, fileName)
12
+ if ((await fs.stat(absolute)).isDirectory()) {
13
+ fileNames.push(...await getDirectoryFileNames(absolute))
14
+ } else {
15
+ fileNames.push(absolute)
16
+ }
17
+ }
18
+ return fileNames
19
+ }
20
+
21
+ const postBuildTstypes = async ({ rootAliases = [] }) => {
22
+ try {
23
+ await fs.access('./builttypes', fs.constants.F_OK)
24
+ } catch (e) {
25
+ return
26
+ }
27
+ const fileNames = await getDirectoryFileNames('./builttypes')
28
+ const rootAliasRegex = new RegExp(rootAliases.map(x => x + '/').join('|') || 'nevermatching/', 'g')
29
+ for (const fileName of fileNames) {
30
+ await fs.readFile(fileName, 'utf8').then(
31
+ str => str.replaceAll(rootAliasRegex, `${path.relative(fileName, 'builttypes').slice(1)}/`) // builttypes/index.ts will be resolved to '..' so we always remove the first dot
32
+ ).then(outStr => fs.writeFile(fileName, outStr))
33
+ }
34
+ await execp('cp -r builttypes/. lib')
35
+ }
36
+ export default postBuildTstypes