@newlogic-digital/core 3.1.1 → 4.0.0-next.10

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/index.js CHANGED
@@ -6,10 +6,10 @@ import latte from '@vituum/vite-plugin-latte'
6
6
  import juice from '@vituum/vite-plugin-juice'
7
7
  import send from '@vituum/vite-plugin-send'
8
8
  import { getPackageInfo, merge } from 'vituum/utils/common.js'
9
- import twigOptions from './src/twig.js'
10
9
  import browserslistToEsbuild from 'browserslist-to-esbuild'
11
10
  import browserslist from 'browserslist'
12
11
  import { Features as LightningCssFeatures, browserslistToTargets } from 'lightningcss'
12
+ import process from 'node:process'
13
13
 
14
14
  const { name } = getPackageInfo(import.meta.url)
15
15
 
@@ -17,62 +17,61 @@ const { name } = getPackageInfo(import.meta.url)
17
17
  * @type {import('@newlogic-digital/core/types').PluginUserConfig}
18
18
  */
19
19
  const defaultOptions = {
20
- mode: null,
21
- cert: 'localhost',
22
- format: ['latte'],
23
- manualChunks: {},
24
- input: {
25
- assets: [
26
- './src/styles/*.{css,pcss,scss,sass,less,styl,stylus}',
27
- './src/scripts/*.{js,ts,mjs}'
28
- ],
29
- pages: [
30
- './src/pages/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
31
- '!./src/pages/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json',
32
- '!./src/pages/email/**/*'
33
- ],
34
- emails: [
35
- './src/pages/email/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
36
- './src/styles/emails/*.{css,pcss,scss,sass,less,styl,stylus}',
37
- '!./src/pages/email/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json'
38
- ]
20
+ mode: null,
21
+ cert: 'localhost',
22
+ format: ['latte'],
23
+ codeSplitting: {},
24
+ input: {
25
+ assets: [
26
+ './src/styles/*.{css,pcss,scss,sass,less,styl,stylus}',
27
+ './src/scripts/*.{js,ts,mjs}',
28
+ ],
29
+ pages: [
30
+ './src/pages/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
31
+ '!./src/pages/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json',
32
+ '!./src/pages/email/**/*',
33
+ ],
34
+ emails: [
35
+ './src/pages/email/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
36
+ './src/styles/emails/*.{css,pcss,scss,sass,less,styl,stylus}',
37
+ '!./src/pages/email/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json',
38
+ ],
39
+ },
40
+ vituum: {
41
+ imports: {
42
+ paths: ['./src/styles/*/**', '!./src/styles/emails/*', './src/scripts/*/**'],
39
43
  },
40
- vituum: {
41
- imports: {
42
- paths: ['./src/styles/*/**', '!./src/styles/emails/*', './src/scripts/*/**']
43
- }
44
+ },
45
+ juice: {
46
+ paths: ['src/pages/email'],
47
+ postcss: {
48
+ globalData: {
49
+ files: ['./src/styles/emails/theme/config.css'],
50
+ },
44
51
  },
45
- juice: {
46
- paths: ['src/pages/email'],
47
- postcss: {
48
- globalData: {
49
- files: ['./src/styles/emails/theme/config.css']
50
- }
51
- }
52
+ },
53
+ css: {
54
+ transformer: 'postcss',
55
+ lightningcss: {},
56
+ },
57
+ tailwindcss: {},
58
+ send: {},
59
+ latte: {
60
+ globals: {
61
+ srcPath: resolve(process.cwd(), 'src'),
62
+ templatesPath: resolve(process.cwd(), 'src/templates'),
63
+ template: './src/templates/layouts/default.latte',
52
64
  },
53
- css: {
54
- transformer: 'postcss',
55
- lightningcss: {}
65
+ functions: {
66
+ pages: () => {
67
+ return fs.readdirSync(resolve(process.cwd(), 'src/pages')).filter(file => fs.statSync(resolve(process.cwd(), 'src/pages/' + file)).isFile())
68
+ },
56
69
  },
57
- tailwindcss: {},
58
- send: {},
59
- latte: {
60
- globals: {
61
- srcPath: resolve(process.cwd(), 'src'),
62
- templatesPath: resolve(process.cwd(), 'src/templates'),
63
- template: './src/templates/layouts/default.latte'
64
- },
65
- functions: {
66
- pages: () => {
67
- return fs.readdirSync(resolve(process.cwd(), 'src/pages')).filter(file => fs.statSync(resolve(process.cwd(), 'src/pages/' + file)).isFile())
68
- }
69
- },
70
- filters: {
71
- json: resolve(process.cwd(), 'node_modules/@newlogic-digital/core/latte/JsonFilter.js'),
72
- code: 'node_modules/@newlogic-digital/core/latte/CodeFilter.php'
73
- }
70
+ filters: {
71
+ json: resolve(process.cwd(), 'node_modules/@newlogic-digital/core/latte/JsonFilter.js'),
72
+ code: 'node_modules/@newlogic-digital/core/latte/CodeFilter.php',
74
73
  },
75
- twig: twigOptions
74
+ },
76
75
  }
77
76
 
78
77
  /**
@@ -80,145 +79,162 @@ const defaultOptions = {
80
79
  * @returns [import('vite').Plugin]
81
80
  */
82
81
  const plugin = async (options = {}) => {
83
- options = merge(defaultOptions, options)
84
-
85
- const templatesPlugins = []
86
- const tailwindcssPlugin = []
82
+ options = merge(defaultOptions, options)
87
83
 
88
- if (options.format.includes('twig')) {
89
- const twig = (await import('@vituum/vite-plugin-twig')).default
84
+ const templatesPlugins = []
85
+ const tailwindcssPlugin = []
90
86
 
91
- templatesPlugins.push(twig(options.twig))
92
- }
93
-
94
- if (options.format.includes('latte')) {
95
- templatesPlugins.push(latte(options.latte))
96
- }
87
+ if (options.format.includes('twig')) {
88
+ const twig = (await import('@vituum/vite-plugin-twig')).default
97
89
 
98
- if (options.css.transformer === 'postcss') {
99
- const tailwindcss = (await import('@vituum/vite-plugin-tailwindcss')).default
90
+ templatesPlugins.push(twig(options.twig))
91
+ }
100
92
 
101
- tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
102
- }
93
+ if (options.format.includes('latte')) {
94
+ templatesPlugins.push(latte(options.latte))
95
+ }
103
96
 
104
- if (options.css.transformer === 'lightningcss') {
105
- if (!fs.existsSync(resolve(process.cwd(), 'src/+.css'))) {
106
- fs.writeFileSync(resolve(process.cwd(), 'src/+.css'), '@import "./styles/main.css";')
107
- }
97
+ if (options.css.transformer === 'postcss') {
98
+ const tailwindcss = (await import('@vituum/vite-plugin-tailwindcss')).default
108
99
 
109
- // @ts-ignore
110
- const tailwindcss = (await import('@tailwindcss/vite')).default
100
+ tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
101
+ }
111
102
 
112
- tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
103
+ if (options.css.transformer === 'lightningcss') {
104
+ if (!fs.existsSync(resolve(process.cwd(), 'src/+.css'))) {
105
+ fs.writeFileSync(resolve(process.cwd(), 'src/+.css'), '@import "./styles/main.css";')
113
106
  }
114
107
 
115
- const plugins = [
116
- vituum(options.vituum),
117
- ...tailwindcssPlugin,
118
- ...templatesPlugins,
119
- juice(options.juice),
120
- send(options.send)
121
- ]
122
-
123
- return [{
124
- name,
125
- enforce: 'pre',
126
- config(userConfig, userEnv) {
127
- const isHttps = userConfig?.server?.https !== false
128
- && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}.pem`))
129
- && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`))
130
-
131
- let defaultInput = [
132
- ...(options?.input?.assets ?? [])
133
- ]
134
-
135
- if (!options.mode) {
136
- options.mode = userEnv.mode
137
- }
108
+ // @ts-ignore
109
+ const tailwindcss = (await import('@tailwindcss/vite')).default
110
+
111
+ tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
112
+ }
113
+
114
+ const plugins = [
115
+ vituum(options.vituum),
116
+ ...tailwindcssPlugin,
117
+ ...templatesPlugins,
118
+ juice(options.juice),
119
+ send(options.send),
120
+ ]
121
+
122
+ return [{
123
+ name,
124
+ enforce: 'pre',
125
+ /**
126
+ * @param {import('vite').UserConfig} userConfig
127
+ * @param {import('vite').ConfigEnv} userEnv
128
+ */
129
+ config(userConfig, userEnv) {
130
+ // @ts-ignore
131
+ const isHttps = userConfig?.server?.https !== false
132
+ && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}.pem`))
133
+ && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`))
134
+
135
+ let defaultInput = [
136
+ ...(options?.input?.assets ?? []),
137
+ ]
138
+
139
+ if (!options.mode) {
140
+ options.mode = userEnv.mode
141
+ }
142
+
143
+ if (options.mode === 'development') {
144
+ defaultInput = [
145
+ ...(options?.input?.pages ?? []),
146
+ ...(options?.input?.assets ?? []),
147
+ ]
148
+ }
138
149
 
139
- if (options.mode === 'development') {
140
- defaultInput = [
141
- ...(options?.input?.pages ?? []),
142
- ...(options?.input?.assets ?? [])
143
- ]
144
- }
150
+ if (userEnv.command === 'build') {
151
+ userConfig.publicDir = userConfig.publicDir ?? false
152
+ }
145
153
 
146
- if (userEnv.command === 'build') {
147
- userConfig.publicDir = userConfig.publicDir ?? false
148
- }
154
+ const outDir = resolve(userConfig.root ?? process.cwd(), 'public')
149
155
 
150
- const outDir = resolve(userConfig.root ?? process.cwd(), 'public')
156
+ if (userConfig.build && !userConfig.build.outDir) {
157
+ userConfig.build.outDir = outDir
158
+ }
151
159
 
152
- if (userConfig.build && !userConfig.build.outDir) {
153
- userConfig.build.outDir = outDir
154
- }
160
+ userConfig.optimizeDeps = Object.assign({
161
+ entries: [],
162
+ }, userConfig.optimizeDeps ?? {})
155
163
 
156
- userConfig.optimizeDeps = Object.assign({
157
- entries: []
158
- }, userConfig.optimizeDeps ?? {})
159
-
160
- userConfig.css = Object.assign({
161
- transformer: options.css.transformer
162
- }, userConfig.css ?? {})
163
-
164
- userConfig.css.lightningcss = Object.assign({
165
- targets: browserslistToTargets(browserslist()),
166
- exclude: (options.mode !== 'emails') ? LightningCssFeatures.Nesting : 0,
167
- drafts: {
168
- customMedia: true
169
- }
170
- }, userConfig.css.lightningcss ?? {})
171
-
172
- userConfig.build = Object.assign({
173
- target: browserslistToEsbuild(),
174
- manifest: (options.mode === 'emails') ? false : 'manifest.json',
175
- emptyOutDir: false,
176
- modulePreload: false,
177
- assetsInlineLimit: 0,
178
- outDir
179
- }, userConfig.build ?? {})
180
-
181
- if (options.mode === 'emails') {
182
- userEnv.mode = 'production'
183
-
184
- defaultInput = [
185
- ...(options?.input?.emails ?? [])
186
- ]
187
-
188
- userConfig.build.rollupOptions = Object.assign({
189
- input: defaultInput,
190
- output: {
191
- assetFileNames: 'assets/email/[name].[ext]'
192
- }
193
- }, userConfig.build.rollupOptions ?? {})
194
- } else {
195
- userConfig.build.rollupOptions = Object.assign({
196
- input: defaultInput,
197
- output: {
198
- manualChunks: options.manualChunks ?? {
199
- swup: ['swup'],
200
- stimulus: ['@hotwired/stimulus'],
201
- naja: ['naja']
202
- }
203
- }
204
- }, userConfig.build.rollupOptions ?? {})
205
- }
164
+ userConfig.css = Object.assign({
165
+ transformer: options.css.transformer,
166
+ }, userConfig.css ?? {})
167
+
168
+ userConfig.css.lightningcss = Object.assign({
169
+ targets: browserslistToTargets(browserslist()),
170
+ exclude: (options.mode !== 'emails') ? LightningCssFeatures.Nesting : 0,
171
+ drafts: {
172
+ customMedia: true,
173
+ },
174
+ }, userConfig.css.lightningcss ?? {})
175
+
176
+ userConfig.build = Object.assign({
177
+ target: browserslistToEsbuild(),
178
+ manifest: (options.mode === 'emails') ? false : 'manifest.json',
179
+ emptyOutDir: false,
180
+ modulePreload: false,
181
+ assetsInlineLimit: 0,
182
+ outDir,
183
+ }, userConfig.build ?? {})
184
+
185
+ if (options.mode === 'emails') {
186
+ userEnv.mode = 'production'
187
+
188
+ defaultInput = [
189
+ ...(options?.input?.emails ?? []),
190
+ ]
206
191
 
207
- userConfig.server = Object.assign({
208
- host: true,
209
- cors: true,
210
- fsServe: {
211
- strict: false
192
+ userConfig.build.rolldownOptions = Object.assign({
193
+ input: defaultInput,
194
+ output: {
195
+ assetFileNames: 'assets/email/[name].[ext]',
196
+ },
197
+ }, userConfig.build.rolldownOptions ?? {})
198
+ }
199
+ else {
200
+ userConfig.build.rolldownOptions = Object.assign({
201
+ input: defaultInput,
202
+ output: {
203
+ codeSplitting: options.codeSplitting ?? {
204
+ groups: [
205
+ {
206
+ name: 'swup',
207
+ test: /swup/,
208
+ },
209
+ {
210
+ name: '@hotwired/stimulus',
211
+ test: /@hotwired\/stimulus/,
212
+ },
213
+ {
214
+ name: 'naja',
215
+ test: /naja/,
212
216
  },
213
- https: isHttps
214
- ? {
215
- key: fs.readFileSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`)),
216
- cert: fs.readFileSync(join(os.homedir(), `.ssh/${options.cert}.pem`))
217
- }
218
- : false
219
- }, userConfig.server ?? {})
220
- }
221
- }, ...plugins]
217
+ ],
218
+ },
219
+ },
220
+ }, userConfig.build.rolldownOptions ?? {})
221
+ }
222
+
223
+ userConfig.server = Object.assign({
224
+ host: true,
225
+ cors: true,
226
+ fsServe: {
227
+ strict: false,
228
+ },
229
+ https: isHttps
230
+ ? {
231
+ key: fs.readFileSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`)),
232
+ cert: fs.readFileSync(join(os.homedir(), `.ssh/${options.cert}.pem`)),
233
+ }
234
+ : false,
235
+ }, userConfig.server ?? {})
236
+ },
237
+ }, ...plugins]
222
238
  }
223
239
 
224
240
  export default plugin
@@ -1,7 +1,7 @@
1
1
  import parseMinifyHtml from '../src/minify.js'
2
2
 
3
3
  const json = async (input, name) => {
4
- return await parseMinifyHtml(input, name)
4
+ return await parseMinifyHtml(input, name)
5
5
  }
6
6
 
7
7
  export default json
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@newlogic-digital/core",
3
3
  "type": "module",
4
- "version": "3.1.1",
4
+ "version": "4.0.0-next.10",
5
5
  "main": "index.js",
6
6
  "author": "New Logic Studio s.r.o.",
7
7
  "description": "Set of tools that can be used to create modern web applications",
@@ -12,32 +12,25 @@
12
12
  "publish-next": "npm publish --tag next"
13
13
  },
14
14
  "dependencies": {
15
- "@tailwindcss/vite": "^4.1.4",
16
- "@vituum/vite-plugin-juice": "^1.4.0",
17
- "@vituum/vite-plugin-latte": "^1.3.0",
18
- "@vituum/vite-plugin-posthtml": "^1.1.0",
19
- "@vituum/vite-plugin-send": "^1.1.0",
20
- "browserslist": "^4.24.4",
15
+ "@minify-html/node": "^0.18.1",
16
+ "@vituum/vite-plugin-juice": "^2.0.0-next.2",
17
+ "@vituum/vite-plugin-latte": "^2.0.0-next.3",
18
+ "@vituum/vite-plugin-send": "^2.0.0-next.3",
19
+ "browserslist": "^4.28.1",
21
20
  "browserslist-to-esbuild": "^2.1.1",
22
- "fast-glob": "^3.3.3",
23
- "fs-extra": "^11.3.0",
24
- "html-minifier-terser": "^7.2.0",
25
- "lightningcss": "^1.29.3",
26
- "lodash": "^4.17.21",
27
- "picocolors": "^1.1.1",
28
- "posthtml": "^0.16.6",
29
- "posthtml-prism": "^2.0.1",
30
- "prismjs": "^1.30.0",
31
- "vituum": "^1.2.0"
21
+ "lightningcss": "^1.30.2",
22
+ "vituum": "^2.0.0-next.6"
32
23
  },
33
24
  "devDependencies": {
34
- "@types/node": "^22.15.3",
35
- "eslint": "^9.25.1",
36
- "neostandard": "^0.12.1",
37
- "typescript": "^5",
38
- "vite": "^6",
25
+ "@eslint/js": "^9.39",
26
+ "@stylistic/eslint-plugin": "^5.7",
27
+ "@types/node": "^25.0",
39
28
  "@vituum/vite-plugin-tailwindcss": "^1.2.0",
40
- "@vituum/vite-plugin-twig": "^1.1.0"
29
+ "@vituum/vite-plugin-twig": "^1.1.0",
30
+ "eslint": "^9.39.2",
31
+ "rolldown": "^1.0.0-beta.60",
32
+ "typescript": "^5",
33
+ "vite": "^8.0.0-beta.8"
41
34
  },
42
35
  "files": [
43
36
  "latte",
package/src/minify.js CHANGED
@@ -1,22 +1,22 @@
1
- import minifier from 'html-minifier-terser'
1
+ import minifyHtml from '@minify-html/node'
2
+ import { Buffer } from 'node:buffer'
2
3
 
3
4
  const parseMinifyHtml = async (input, name) => {
4
- const minify = await minifier.minify(input, {
5
- collapseWhitespace: true,
6
- collapseInlineTagWhitespace: false,
7
- minifyCSS: true,
8
- removeAttributeQuotes: true,
9
- quoteCharacter: '\'',
10
- minifyJS: true
11
- })
5
+ const minify = await minifyHtml.minify(Buffer.from(input), {
6
+ minify_css: true,
7
+ minify_js: true,
8
+ })
9
+
10
+ const minifyWithQuotes = minify.toString().replaceAll(/=(\s*)"(.*?)"/g, '=\'$2\'')
12
11
 
13
- if (name) {
14
- return JSON.stringify({
15
- [name]: minify
16
- })
17
- } else {
18
- return JSON.stringify(minify)
19
- }
12
+ if (name) {
13
+ return JSON.stringify({
14
+ [name]: minifyWithQuotes,
15
+ })
16
+ }
17
+ else {
18
+ return JSON.stringify(minifyWithQuotes)
19
+ }
20
20
  }
21
21
 
22
22
  export default parseMinifyHtml
package/src/twig.js CHANGED
@@ -1,174 +1,177 @@
1
1
  import fs from 'fs'
2
2
  import { resolve } from 'path'
3
3
  import parseMinifyHtml from './minify.js'
4
+ import process from 'node:process'
4
5
 
5
6
  const wrapPreCode = (code, lang) => {
6
- return `<pre class="language-${lang}"><code class="language-${lang}">${code}</code></pre>`
7
+ return `<pre class="language-${lang}"><code class="language-${lang}">${code}</code></pre>`
7
8
  }
8
9
 
9
10
  const stripIndent = (string) => {
10
- const indent = () => {
11
- const match = string.match(/^[ \t]*(?=\S)/gm)
11
+ const indent = () => {
12
+ const match = string.match(/^[ \t]*(?=\S)/gm)
12
13
 
13
- if (!match) {
14
- return 0
15
- }
16
-
17
- return match.reduce((r, a) => Math.min(r, a.length), Infinity)
14
+ if (!match) {
15
+ return 0
18
16
  }
19
17
 
20
- if (indent() === 0) {
21
- return string
22
- }
18
+ return match.reduce((r, a) => Math.min(r, a.length), Infinity)
19
+ }
20
+
21
+ if (indent() === 0) {
22
+ return string
23
+ }
23
24
 
24
- const regex = new RegExp(`^[ \\t]{${indent()}}`, 'gm')
25
+ const regex = new RegExp(`^[ \\t]{${indent()}}`, 'gm')
25
26
 
26
- return string.replace(regex, '')
27
+ return string.replace(regex, '')
27
28
  }
28
29
 
29
30
  export default {
30
- namespaces: {
31
- src: resolve(process.cwd(), 'src'),
32
- templates: resolve(process.cwd(), 'src/templates')
31
+ namespaces: {
32
+ src: resolve(process.cwd(), 'src'),
33
+ templates: resolve(process.cwd(), 'src/templates'),
34
+ },
35
+ functions: {
36
+ pages: () => {
37
+ return fs.readdirSync('src/views').filter(file => fs.statSync('src/views/' + file).isFile())
33
38
  },
34
- functions: {
35
- pages: () => {
36
- return fs.readdirSync('src/views').filter(file => fs.statSync('src/views/' + file).isFile())
37
- },
38
- fetch: (data) => {
39
- if (typeof data !== 'undefined') {
40
- if (data.indexOf('http') > -1) {
41
- return data
42
- } else {
43
- let slash = data.indexOf('/') + 1
44
- if (slash > 1) {
45
- slash = 0
46
- }
47
-
48
- return fs.readFileSync(process.cwd() + '/' + data.substring(slash, data.length), 'utf8').toString()
49
- }
50
- }
51
- },
52
- randomColor: () => {
53
- return '#' + Math.random().toString(16).slice(2, 8)
54
- },
55
- placeholder: (width, height) => {
56
- const colors = ['333', '444', '666', '222', '777', '888', '111']
57
- return 'https://via.placeholder.com/' + width + 'x' + height + '/' + colors[Math.floor(Math.random() * colors.length)] + '.webp'
58
- },
59
- lazy: (width, height) => {
60
- const svg = encodeURIComponent(stripIndent('<svg width="' + width + '" height="' + height + '" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + width + ' ' + height + '"></svg>'))
39
+ fetch: (data) => {
40
+ if (typeof data !== 'undefined') {
41
+ if (data.indexOf('http') > -1) {
42
+ return data
43
+ }
44
+ else {
45
+ let slash = data.indexOf('/') + 1
46
+ if (slash > 1) {
47
+ slash = 0
48
+ }
61
49
 
62
- return 'data:image/svg+xml;charset=UTF-8,' + svg
63
- },
64
- ratio: (width, height) => {
65
- return (height / width) * 100
50
+ return fs.readFileSync(process.cwd() + '/' + data.substring(slash, data.length), 'utf8').toString()
66
51
  }
52
+ }
67
53
  },
68
- filters: {
69
- asset: (url) => {
70
- return url
71
- },
72
- rem: (value) => {
73
- return `${value / 16}rem`
74
- },
75
- encode64: (path) => {
76
- const svg = encodeURIComponent(stripIndent(path))
54
+ randomColor: () => {
55
+ return '#' + Math.random().toString(16).slice(2, 8)
56
+ },
57
+ placeholder: (width, height) => {
58
+ const colors = ['333', '444', '666', '222', '777', '888', '111']
59
+ return 'https://via.placeholder.com/' + width + 'x' + height + '/' + colors[Math.floor(Math.random() * colors.length)] + '.webp'
60
+ },
61
+ lazy: (width, height) => {
62
+ const svg = encodeURIComponent(stripIndent('<svg width="' + width + '" height="' + height + '" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + width + ' ' + height + '"></svg>'))
77
63
 
78
- return 'data:image/svg+xml;charset=UTF-8,' + svg
64
+ return 'data:image/svg+xml;charset=UTF-8,' + svg
65
+ },
66
+ ratio: (width, height) => {
67
+ return (height / width) * 100
68
+ },
69
+ },
70
+ filters: {
71
+ asset: (url) => {
72
+ return url
73
+ },
74
+ rem: (value) => {
75
+ return `${value / 16}rem`
76
+ },
77
+ encode64: (path) => {
78
+ const svg = encodeURIComponent(stripIndent(path))
79
+
80
+ return 'data:image/svg+xml;charset=UTF-8,' + svg
81
+ },
82
+ exists: (path) => {
83
+ if (path.indexOf('/') === 0) {
84
+ path = path.slice(1)
85
+ }
86
+
87
+ return fs.existsSync(resolve(process.cwd(), path))
88
+ },
89
+ tel: (value) => {
90
+ return value.replace(/\s+/g, '').replace('(', '').replace(')', '')
91
+ },
92
+ },
93
+ extensions: [
94
+ (Twig) => {
95
+ Twig.exports.extendTag({
96
+ type: 'json',
97
+ regex: /^json\s+(.+)$|^json$/,
98
+ next: ['endjson'],
99
+ open: true,
100
+ compile: function (token) {
101
+ const expression = token.match[1] ?? '\'_null\''
102
+
103
+ token.stack = Reflect.apply(Twig.expression.compile, this, [{
104
+ type: Twig.expression.type.expression,
105
+ value: expression,
106
+ }]).stack
107
+
108
+ delete token.match
109
+ return token
79
110
  },
80
- exists: (path) => {
81
- if (path.indexOf('/') === 0) {
82
- path = path.slice(1)
111
+ parse: async function (token, context, chain) {
112
+ const name = Reflect.apply(Twig.expression.parse, this, [token.stack, context])
113
+ const output = this.parse(token.output, context)
114
+
115
+ if (name === '_null') {
116
+ return {
117
+ chain,
118
+ output: await parseMinifyHtml(output),
83
119
  }
84
-
85
- return fs.existsSync(resolve(process.cwd(), path))
120
+ }
121
+ else {
122
+ return {
123
+ chain,
124
+ output: await parseMinifyHtml(output, name),
125
+ }
126
+ }
86
127
  },
87
- tel: (value) => {
88
- return value.replace(/\s+/g, '').replace('(', '').replace(')', '')
89
- }
128
+ })
129
+ Twig.exports.extendTag({
130
+ type: 'endjson',
131
+ regex: /^endjson$/,
132
+ next: [],
133
+ open: false,
134
+ })
90
135
  },
91
- extensions: [
92
- (Twig) => {
93
- Twig.exports.extendTag({
94
- type: 'json',
95
- regex: /^json\s+(.+)$|^json$/,
96
- next: ['endjson'],
97
- open: true,
98
- compile: function (token) {
99
- const expression = token.match[1] ?? '\'_null\''
100
-
101
- token.stack = Reflect.apply(Twig.expression.compile, this, [{
102
- type: Twig.expression.type.expression,
103
- value: expression
104
- }]).stack
105
-
106
- delete token.match
107
- return token
108
- },
109
- parse: async function (token, context, chain) {
110
- const name = Reflect.apply(Twig.expression.parse, this, [token.stack, context])
111
- const output = this.parse(token.output, context)
112
-
113
- if (name === '_null') {
114
- return {
115
- chain,
116
- output: await parseMinifyHtml(output)
117
- }
118
- } else {
119
- return {
120
- chain,
121
- output: await parseMinifyHtml(output, name)
122
- }
123
- }
124
- }
125
- })
126
- Twig.exports.extendTag({
127
- type: 'endjson',
128
- regex: /^endjson$/,
129
- next: [],
130
- open: false
131
- })
136
+ (Twig) => {
137
+ Twig.exports.extendTag({
138
+ type: 'code',
139
+ regex: /^code\s+(.+)$/,
140
+ next: ['endcode'], // match the type of the end tag
141
+ open: true,
142
+ compile: function (token) {
143
+ const expression = token.match[1]
144
+
145
+ token.stack = Reflect.apply(Twig.expression.compile, this, [{
146
+ type: Twig.expression.type.expression,
147
+ value: expression,
148
+ }]).stack
149
+
150
+ delete token.match
151
+ return token
132
152
  },
133
- (Twig) => {
134
- Twig.exports.extendTag({
135
- type: 'code',
136
- regex: /^code\s+(.+)$/,
137
- next: ['endcode'], // match the type of the end tag
138
- open: true,
139
- compile: function (token) {
140
- const expression = token.match[1]
141
-
142
- token.stack = Reflect.apply(Twig.expression.compile, this, [{
143
- type: Twig.expression.type.expression,
144
- value: expression
145
- }]).stack
146
-
147
- delete token.match
148
- return token
149
- },
150
- parse: function (token, context, chain) {
151
- let type = Reflect.apply(Twig.expression.parse, this, [token.stack, context])
152
- const output = this.parse(token.output, context)
153
- let mirror = false
154
-
155
- if (type.includes(':mirror')) {
156
- mirror = true
157
- type = type.replace(':mirror', '')
158
- }
159
-
160
- return {
161
- chain,
162
- output: `${mirror ? output : ''}${wrapPreCode(output, type)}`
163
- }
164
- }
165
- })
166
- Twig.exports.extendTag({
167
- type: 'endcode',
168
- regex: /^endcode$/,
169
- next: [],
170
- open: false
171
- })
172
- }
173
- ]
153
+ parse: function (token, context, chain) {
154
+ let type = Reflect.apply(Twig.expression.parse, this, [token.stack, context])
155
+ const output = this.parse(token.output, context)
156
+ let mirror = false
157
+
158
+ if (type.includes(':mirror')) {
159
+ mirror = true
160
+ type = type.replace(':mirror', '')
161
+ }
162
+
163
+ return {
164
+ chain,
165
+ output: `${mirror ? output : ''}${wrapPreCode(output, type)}`,
166
+ }
167
+ },
168
+ })
169
+ Twig.exports.extendTag({
170
+ type: 'endcode',
171
+ regex: /^endcode$/,
172
+ next: [],
173
+ open: false,
174
+ })
175
+ },
176
+ ],
174
177
  }
package/types/index.d.ts CHANGED
@@ -9,13 +9,12 @@ export interface PluginUserConfig {
9
9
  format?: string[]
10
10
  input?: Input
11
11
  cert?: string
12
- manualChunks?: import('rollup').ManualChunksOption
12
+ codeSplitting?: import('rolldown').OutputOptions['codeSplitting']
13
13
  vituum?: import('vituum').UserConfig,
14
14
  css?: import('vite').CSSOptions
15
- posthtml?: import('@vituum/vite-plugin-posthtml/types').PluginUserConfig
16
- juice?: import('@vituum/vite-plugin-juice/types').PluginUserConfig
17
- send?: import('@vituum/vite-plugin-send/types').PluginUserConfig
18
- tailwindcss?: import('@vituum/vite-plugin-tailwindcss/types').PluginUserConfig
19
- latte?: import('@vituum/vite-plugin-latte/types').PluginUserConfig
20
- twig?: import('@vituum/vite-plugin-twig/types').PluginUserConfig
15
+ juice?: import('@vituum/vite-plugin-juice').PluginUserConfig
16
+ send?: import('@vituum/vite-plugin-send').PluginUserConfig
17
+ tailwindcss?: import('@vituum/vite-plugin-tailwindcss').PluginUserConfig
18
+ latte?: import('@vituum/vite-plugin-latte').PluginUserConfig
19
+ twig?: import('@vituum/vite-plugin-twig').PluginUserConfig
21
20
  }
package/src/prism.js DELETED
@@ -1,90 +0,0 @@
1
- import Prism from 'prismjs'
2
- import { render } from 'posthtml-render'
3
- import loadLanguages from 'prismjs/components/index.js'
4
- import NormalizeWhitespace from 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace.js'
5
-
6
- const Normalize = new NormalizeWhitespace({
7
- 'remove-trailing': true,
8
- 'remove-indent': true,
9
- 'left-trim': true,
10
- 'right-trim': true
11
- })
12
-
13
- const createPrismPlugin = (options) => {
14
- return (tree) => {
15
- const highlightCodeTags = node => tree.match.call(node, { tag: 'code' }, highlightNode)
16
-
17
- if (options.inline) {
18
- highlightCodeTags(tree)
19
- } else {
20
- tree.match({ tag: 'pre' }, highlightCodeTags)
21
- }
22
- }
23
- }
24
-
25
- const highlightNode = (node) => {
26
- const attrs = node.attrs || {}
27
- const classList = `${attrs.class || ''}`.trimStart()
28
-
29
- if ('prism-ignore' in attrs) {
30
- delete node.attrs['prism-ignore']
31
-
32
- return node
33
- }
34
-
35
- if (classList.includes('prism-ignore')) {
36
- node.attrs.class = node.attrs.class.replace('prism-ignore', '').trim()
37
-
38
- return node
39
- }
40
-
41
- const lang = getExplicitLanguage(classList)
42
-
43
- if (lang && !classList.includes(`language-${lang}`)) {
44
- attrs.class = `${classList || ''} language-${lang}`.trimStart()
45
- }
46
-
47
- node.attrs = attrs
48
-
49
- if (node.content) {
50
- const html = (node.content[0].tag && !node.content[0].content) ? `<${node.content[0].tag}>` : render(node.content)
51
-
52
- node.content = mapStringOrNode(html, lang)
53
- }
54
-
55
- return node
56
- }
57
-
58
- const mapStringOrNode = (stringOrNode, lang = null) => {
59
- if (typeof stringOrNode === 'string') {
60
- if (lang) {
61
- if (!Object.keys(Prism.languages).includes(lang)) {
62
- loadLanguages.silent = true
63
- loadLanguages([lang])
64
- }
65
-
66
- return Prism.highlight(Normalize.normalize(stringOrNode), Prism.languages[lang], lang)
67
- }
68
-
69
- return Prism.highlight(Normalize.normalize(stringOrNode), Prism.languages.markup, 'markup')
70
- }
71
-
72
- highlightNode(stringOrNode)
73
-
74
- return stringOrNode
75
- }
76
-
77
- const getExplicitLanguage = (classList) => {
78
- const matches = classList.match(/(?:lang|language)-(\w*)/)
79
-
80
- return matches === null ? null : matches[1]
81
- }
82
-
83
- const plugin = (options) => {
84
- options = options || {}
85
- options.inline = options.inline || false
86
-
87
- return tree => createPrismPlugin(options)(tree)
88
- }
89
-
90
- export default plugin