@newlogic-digital/core 4.0.0-next.1 → 4.0.0-next.2

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
@@ -10,6 +10,7 @@ import twigOptions from './src/twig.js'
10
10
  import browserslistToEsbuild from 'browserslist-to-esbuild'
11
11
  import browserslist from 'browserslist'
12
12
  import { Features as LightningCssFeatures, browserslistToTargets } from 'lightningcss'
13
+ import process from 'node:process'
13
14
 
14
15
  const { name } = getPackageInfo(import.meta.url)
15
16
 
@@ -17,62 +18,62 @@ const { name } = getPackageInfo(import.meta.url)
17
18
  * @type {import('@newlogic-digital/core/types').PluginUserConfig}
18
19
  */
19
20
  const defaultOptions = {
20
- mode: null,
21
- cert: 'localhost',
22
- format: ['latte'],
23
- advancedChunks: {},
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
- ]
21
+ mode: null,
22
+ cert: 'localhost',
23
+ format: ['latte'],
24
+ advancedChunks: {},
25
+ input: {
26
+ assets: [
27
+ './src/styles/*.{css,pcss,scss,sass,less,styl,stylus}',
28
+ './src/scripts/*.{js,ts,mjs}',
29
+ ],
30
+ pages: [
31
+ './src/pages/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
32
+ '!./src/pages/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json',
33
+ '!./src/pages/email/**/*',
34
+ ],
35
+ emails: [
36
+ './src/pages/email/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
37
+ './src/styles/emails/*.{css,pcss,scss,sass,less,styl,stylus}',
38
+ '!./src/pages/email/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json',
39
+ ],
40
+ },
41
+ vituum: {
42
+ imports: {
43
+ paths: ['./src/styles/*/**', '!./src/styles/emails/*', './src/scripts/*/**'],
39
44
  },
40
- vituum: {
41
- imports: {
42
- paths: ['./src/styles/*/**', '!./src/styles/emails/*', './src/scripts/*/**']
43
- }
45
+ },
46
+ juice: {
47
+ paths: ['src/pages/email'],
48
+ postcss: {
49
+ globalData: {
50
+ files: ['./src/styles/emails/theme/config.css'],
51
+ },
44
52
  },
45
- juice: {
46
- paths: ['src/pages/email'],
47
- postcss: {
48
- globalData: {
49
- files: ['./src/styles/emails/theme/config.css']
50
- }
51
- }
53
+ },
54
+ css: {
55
+ transformer: 'postcss',
56
+ lightningcss: {},
57
+ },
58
+ tailwindcss: {},
59
+ send: {},
60
+ latte: {
61
+ globals: {
62
+ srcPath: resolve(process.cwd(), 'src'),
63
+ templatesPath: resolve(process.cwd(), 'src/templates'),
64
+ template: './src/templates/layouts/default.latte',
52
65
  },
53
- css: {
54
- transformer: 'postcss',
55
- lightningcss: {}
66
+ functions: {
67
+ pages: () => {
68
+ return fs.readdirSync(resolve(process.cwd(), 'src/pages')).filter(file => fs.statSync(resolve(process.cwd(), 'src/pages/' + file)).isFile())
69
+ },
56
70
  },
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
- }
71
+ filters: {
72
+ json: resolve(process.cwd(), 'node_modules/@newlogic-digital/core/latte/JsonFilter.js'),
73
+ code: 'node_modules/@newlogic-digital/core/latte/CodeFilter.php',
74
74
  },
75
- twig: twigOptions
75
+ },
76
+ twig: twigOptions,
76
77
  }
77
78
 
78
79
  /**
@@ -80,161 +81,162 @@ const defaultOptions = {
80
81
  * @returns [import('vite').Plugin]
81
82
  */
82
83
  const plugin = async (options = {}) => {
83
- options = merge(defaultOptions, options)
84
+ options = merge(defaultOptions, options)
84
85
 
85
- const templatesPlugins = []
86
- const tailwindcssPlugin = []
86
+ const templatesPlugins = []
87
+ const tailwindcssPlugin = []
87
88
 
88
- if (options.format.includes('twig')) {
89
- const twig = (await import('@vituum/vite-plugin-twig')).default
89
+ if (options.format.includes('twig')) {
90
+ const twig = (await import('@vituum/vite-plugin-twig')).default
90
91
 
91
- templatesPlugins.push(twig(options.twig))
92
- }
92
+ templatesPlugins.push(twig(options.twig))
93
+ }
93
94
 
94
- if (options.format.includes('latte')) {
95
- templatesPlugins.push(latte(options.latte))
96
- }
95
+ if (options.format.includes('latte')) {
96
+ templatesPlugins.push(latte(options.latte))
97
+ }
98
+
99
+ if (options.css.transformer === 'postcss') {
100
+ const tailwindcss = (await import('@vituum/vite-plugin-tailwindcss')).default
97
101
 
98
- if (options.css.transformer === 'postcss') {
99
- const tailwindcss = (await import('@vituum/vite-plugin-tailwindcss')).default
102
+ tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
103
+ }
100
104
 
101
- tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
105
+ if (options.css.transformer === 'lightningcss') {
106
+ if (!fs.existsSync(resolve(process.cwd(), 'src/+.css'))) {
107
+ fs.writeFileSync(resolve(process.cwd(), 'src/+.css'), '@import "./styles/main.css";')
102
108
  }
103
109
 
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
- }
110
+ // @ts-ignore
111
+ const tailwindcss = (await import('@tailwindcss/vite')).default
108
112
 
109
- // @ts-ignore
110
- // const tailwindcss = (await import('@tailwindcss/vite')).default
111
- //
112
- // tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
113
- }
113
+ tailwindcssPlugin.push(tailwindcss(options.tailwindcss))
114
+ }
114
115
 
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
- /**
116
+ const plugins = [
117
+ vituum(options.vituum),
118
+ ...tailwindcssPlugin,
119
+ ...templatesPlugins,
120
+ juice(options.juice),
121
+ send(options.send),
122
+ ]
123
+
124
+ return [{
125
+ name,
126
+ enforce: 'pre',
127
+ /**
127
128
  * @param {import('vite').UserConfig} userConfig
128
129
  * @param {import('vite').ConfigEnv} userEnv
129
130
  */
130
- config(userConfig, userEnv) {
131
- // @ts-ignore
132
- const isHttps = userConfig?.server?.https !== false
133
- && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}.pem`))
134
- && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`))
135
-
136
- let defaultInput = [
137
- ...(options?.input?.assets ?? [])
138
- ]
139
-
140
- if (!options.mode) {
141
- options.mode = userEnv.mode
142
- }
131
+ config(userConfig, userEnv) {
132
+ // @ts-ignore
133
+ const isHttps = userConfig?.server?.https !== false
134
+ && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}.pem`))
135
+ && fs.existsSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`))
136
+
137
+ let defaultInput = [
138
+ ...(options?.input?.assets ?? []),
139
+ ]
140
+
141
+ if (!options.mode) {
142
+ options.mode = userEnv.mode
143
+ }
144
+
145
+ if (options.mode === 'development') {
146
+ defaultInput = [
147
+ ...(options?.input?.pages ?? []),
148
+ ...(options?.input?.assets ?? []),
149
+ ]
150
+ }
143
151
 
144
- if (options.mode === 'development') {
145
- defaultInput = [
146
- ...(options?.input?.pages ?? []),
147
- ...(options?.input?.assets ?? [])
148
- ]
149
- }
152
+ if (userEnv.command === 'build') {
153
+ userConfig.publicDir = userConfig.publicDir ?? false
154
+ }
150
155
 
151
- if (userEnv.command === 'build') {
152
- userConfig.publicDir = userConfig.publicDir ?? false
153
- }
156
+ const outDir = resolve(userConfig.root ?? process.cwd(), 'public')
154
157
 
155
- const outDir = resolve(userConfig.root ?? process.cwd(), 'public')
158
+ if (userConfig.build && !userConfig.build.outDir) {
159
+ userConfig.build.outDir = outDir
160
+ }
156
161
 
157
- if (userConfig.build && !userConfig.build.outDir) {
158
- userConfig.build.outDir = outDir
159
- }
162
+ userConfig.optimizeDeps = Object.assign({
163
+ entries: [],
164
+ }, userConfig.optimizeDeps ?? {})
160
165
 
161
- userConfig.optimizeDeps = Object.assign({
162
- entries: []
163
- }, userConfig.optimizeDeps ?? {})
164
-
165
- userConfig.css = Object.assign({
166
- transformer: options.css.transformer
167
- }, userConfig.css ?? {})
168
-
169
- userConfig.css.lightningcss = Object.assign({
170
- targets: browserslistToTargets(browserslist()),
171
- exclude: (options.mode !== 'emails') ? LightningCssFeatures.Nesting : 0,
172
- drafts: {
173
- customMedia: true
174
- }
175
- }, userConfig.css.lightningcss ?? {})
176
-
177
- userConfig.build = Object.assign({
178
- target: browserslistToEsbuild(),
179
- manifest: (options.mode === 'emails') ? false : 'manifest.json',
180
- emptyOutDir: false,
181
- modulePreload: false,
182
- assetsInlineLimit: 0,
183
- outDir
184
- }, userConfig.build ?? {})
185
-
186
- if (options.mode === 'emails') {
187
- userEnv.mode = 'production'
188
-
189
- defaultInput = [
190
- ...(options?.input?.emails ?? [])
191
- ]
192
-
193
- userConfig.build.rolldownOptions = Object.assign({
194
- input: defaultInput,
195
- output: {
196
- assetFileNames: 'assets/email/[name].[ext]'
197
- }
198
- }, userConfig.build.rolldownOptions ?? {})
199
- } else {
200
- userConfig.build.rolldownOptions = Object.assign({
201
- input: defaultInput,
202
- output: {
203
- advancedChunks: options.advancedChunks ?? {
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/
216
- }
217
- ]
218
- }
219
- }
220
- }, userConfig.build.rolldownOptions ?? {})
221
- }
166
+ userConfig.css = Object.assign({
167
+ transformer: options.css.transformer,
168
+ }, userConfig.css ?? {})
169
+
170
+ userConfig.css.lightningcss = Object.assign({
171
+ targets: browserslistToTargets(browserslist()),
172
+ exclude: (options.mode !== 'emails') ? LightningCssFeatures.Nesting : 0,
173
+ drafts: {
174
+ customMedia: true,
175
+ },
176
+ }, userConfig.css.lightningcss ?? {})
177
+
178
+ userConfig.build = Object.assign({
179
+ target: browserslistToEsbuild(),
180
+ manifest: (options.mode === 'emails') ? false : 'manifest.json',
181
+ emptyOutDir: false,
182
+ modulePreload: false,
183
+ assetsInlineLimit: 0,
184
+ outDir,
185
+ }, userConfig.build ?? {})
186
+
187
+ if (options.mode === 'emails') {
188
+ userEnv.mode = 'production'
189
+
190
+ defaultInput = [
191
+ ...(options?.input?.emails ?? []),
192
+ ]
222
193
 
223
- userConfig.server = Object.assign({
224
- host: true,
225
- cors: true,
226
- fsServe: {
227
- strict: false
194
+ userConfig.build.rolldownOptions = Object.assign({
195
+ input: defaultInput,
196
+ output: {
197
+ assetFileNames: 'assets/email/[name].[ext]',
198
+ },
199
+ }, userConfig.build.rolldownOptions ?? {})
200
+ }
201
+ else {
202
+ userConfig.build.rolldownOptions = Object.assign({
203
+ input: defaultInput,
204
+ output: {
205
+ advancedChunks: options.advancedChunks ?? {
206
+ groups: [
207
+ {
208
+ name: 'swup',
209
+ test: /swup/,
210
+ },
211
+ {
212
+ name: '@hotwired/stimulus',
213
+ test: /@hotwired\/stimulus/,
214
+ },
215
+ {
216
+ name: 'naja',
217
+ test: /naja/,
228
218
  },
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]
219
+ ],
220
+ },
221
+ },
222
+ }, userConfig.build.rolldownOptions ?? {})
223
+ }
224
+
225
+ userConfig.server = Object.assign({
226
+ host: true,
227
+ cors: true,
228
+ fsServe: {
229
+ strict: false,
230
+ },
231
+ https: isHttps
232
+ ? {
233
+ key: fs.readFileSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`)),
234
+ cert: fs.readFileSync(join(os.homedir(), `.ssh/${options.cert}.pem`)),
235
+ }
236
+ : false,
237
+ }, userConfig.server ?? {})
238
+ },
239
+ }, ...plugins]
238
240
  }
239
241
 
240
242
  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": "4.0.0-next.1",
4
+ "version": "4.0.0-next.2",
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",
@@ -14,22 +14,15 @@
14
14
  "dependencies": {
15
15
  "@vituum/vite-plugin-juice": "^2.0.0-next.1",
16
16
  "@vituum/vite-plugin-latte": "^2.0.0-next.2",
17
- "@vituum/vite-plugin-posthtml": "^2.0.0-next.1",
18
17
  "@vituum/vite-plugin-send": "^2.0.0-next.1",
19
18
  "browserslist": "^4.28.1",
20
19
  "browserslist-to-esbuild": "^2.1.1",
21
- "fast-glob": "^3.3.3",
22
- "fs-extra": "^11.3.2",
23
- "html-minifier-terser": "^7.2.0",
24
20
  "lightningcss": "^1.30.2",
25
- "lodash": "^4.17.21",
26
- "picocolors": "^1.1.1",
27
- "posthtml": "^0.16.7",
28
- "posthtml-prism": "^2.0.1",
29
- "prismjs": "^1.30.0",
30
- "vituum": "^2.0.0-next.3"
21
+ "vituum": "^2.0.0-next.5"
31
22
  },
32
23
  "devDependencies": {
24
+ "@eslint/js": "^9.39",
25
+ "@stylistic/eslint-plugin": "^5.6",
33
26
  "@types/node": "^25.0.3",
34
27
  "eslint": "^9.39.2",
35
28
  "rolldown": "^1.0.0-beta.55",
package/src/minify.js CHANGED
@@ -1,22 +1,23 @@
1
1
  import minifier from 'html-minifier-terser'
2
2
 
3
3
  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
- })
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
+ })
12
12
 
13
- if (name) {
14
- return JSON.stringify({
15
- [name]: minify
16
- })
17
- } else {
18
- return JSON.stringify(minify)
19
- }
13
+ if (name) {
14
+ return JSON.stringify({
15
+ [name]: minify,
16
+ })
17
+ }
18
+ else {
19
+ return JSON.stringify(minify)
20
+ }
20
21
  }
21
22
 
22
23
  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/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