@newlogic-digital/core 2.0.0-alpha.6 → 2.0.0-alpha.8
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 +50 -10
 - package/package.json +6 -3
 - package/src/minify.js +22 -0
 - package/src/twig.js +174 -0
 
    
        package/index.js
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            import fs from 'fs'
         
     | 
| 
       2 
     | 
    
         
            -
            import os from 'os'
         
     | 
| 
       3 
     | 
    
         
            -
            import { dirname, resolve, join } from 'path'
         
     | 
| 
      
 1 
     | 
    
         
            +
            import fs from 'node:fs'
         
     | 
| 
      
 2 
     | 
    
         
            +
            import os from 'node:os'
         
     | 
| 
      
 3 
     | 
    
         
            +
            import { dirname, resolve, join, relative } from 'node:path'
         
     | 
| 
       4 
4 
     | 
    
         
             
            import postHtml from 'posthtml'
         
     | 
| 
       5 
5 
     | 
    
         
             
            import vituum from 'vituum'
         
     | 
| 
       6 
6 
     | 
    
         
             
            import posthtml from '@vituum/vite-plugin-posthtml'
         
     | 
| 
         @@ -13,6 +13,9 @@ import { getPackageInfo, merge } from 'vituum/utils/common.js' 
     | 
|
| 
       13 
13 
     | 
    
         
             
            import parseMinifyHtml from './src/minify.js'
         
     | 
| 
       14 
14 
     | 
    
         
             
            import highlight from './src/prism.js'
         
     | 
| 
       15 
15 
     | 
    
         
             
            import twigOptions from './src/twig.js'
         
     | 
| 
      
 16 
     | 
    
         
            +
            import FastGlob from 'fast-glob'
         
     | 
| 
      
 17 
     | 
    
         
            +
            import fse from 'fs-extra'
         
     | 
| 
      
 18 
     | 
    
         
            +
            import pc from 'picocolors'
         
     | 
| 
       16 
19 
     | 
    
         | 
| 
       17 
20 
     | 
    
         
             
            const { name } = getPackageInfo(import.meta.url)
         
     | 
| 
       18 
21 
     | 
    
         | 
| 
         @@ -41,6 +44,7 @@ const posthtmlPrism = { 
     | 
|
| 
       41 
44 
     | 
    
         
             
             * @type {import('@newlogic-digital/core/types').PluginUserConfig}
         
     | 
| 
       42 
45 
     | 
    
         
             
             */
         
     | 
| 
       43 
46 
     | 
    
         
             
            const defaultOptions = {
         
     | 
| 
      
 47 
     | 
    
         
            +
                mode: null,
         
     | 
| 
       44 
48 
     | 
    
         
             
                cert: 'localhost',
         
     | 
| 
       45 
49 
     | 
    
         
             
                emails: {
         
     | 
| 
       46 
50 
     | 
    
         
             
                    outputDir: resolve(process.cwd(), 'public/email'),
         
     | 
| 
         @@ -106,11 +110,38 @@ const plugin = (options = {}) => { 
     | 
|
| 
       106 
110 
     | 
    
         
             
                return [{
         
     | 
| 
       107 
111 
     | 
    
         
             
                    name,
         
     | 
| 
       108 
112 
     | 
    
         
             
                    enforce: 'pre',
         
     | 
| 
       109 
     | 
    
         
            -
                    config (userConfig) {
         
     | 
| 
      
 113 
     | 
    
         
            +
                    config (userConfig, userEnv) {
         
     | 
| 
       110 
114 
     | 
    
         
             
                        const isHttps = userConfig?.server?.https !== false &&
         
     | 
| 
       111 
115 
     | 
    
         
             
                            fs.existsSync(join(os.homedir(), `.ssh/${options.cert}.pem`)) &&
         
     | 
| 
       112 
116 
     | 
    
         
             
                            fs.existsSync(join(os.homedir(), `.ssh/${options.cert}-key.pem`))
         
     | 
| 
       113 
117 
     | 
    
         | 
| 
      
 118 
     | 
    
         
            +
                        let defaultInput = [
         
     | 
| 
      
 119 
     | 
    
         
            +
                            './src/styles/*.{css,pcss,scss,sass,less,styl,stylus}',
         
     | 
| 
      
 120 
     | 
    
         
            +
                            './src/scripts/*.{js,ts,mjs}',
         
     | 
| 
      
 121 
     | 
    
         
            +
                            './src/views/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
         
     | 
| 
      
 122 
     | 
    
         
            +
                            '!./src/views/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json'
         
     | 
| 
      
 123 
     | 
    
         
            +
                        ]
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
                        if (!options.mode) {
         
     | 
| 
      
 126 
     | 
    
         
            +
                            options.mode = userEnv.mode
         
     | 
| 
      
 127 
     | 
    
         
            +
                        }
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                        if (userEnv.mode === 'headless') {
         
     | 
| 
      
 130 
     | 
    
         
            +
                            userEnv.mode = 'production'
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                            defaultInput = [
         
     | 
| 
      
 133 
     | 
    
         
            +
                                './src/styles/*.{css,pcss,scss,sass,less,styl,stylus}',
         
     | 
| 
      
 134 
     | 
    
         
            +
                                './src/scripts/*.{js,ts,mjs}'
         
     | 
| 
      
 135 
     | 
    
         
            +
                            ]
         
     | 
| 
      
 136 
     | 
    
         
            +
                        } else if (userEnv.mode === 'emails') {
         
     | 
| 
      
 137 
     | 
    
         
            +
                            userEnv.mode = 'production'
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                            defaultInput = [
         
     | 
| 
      
 140 
     | 
    
         
            +
                                './src/views/email/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
         
     | 
| 
      
 141 
     | 
    
         
            +
                                '!./src/views/email/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json'
         
     | 
| 
      
 142 
     | 
    
         
            +
                            ]
         
     | 
| 
      
 143 
     | 
    
         
            +
                        }
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
       114 
145 
     | 
    
         
             
                        userConfig.build = Object.assign({
         
     | 
| 
       115 
146 
     | 
    
         
             
                            manifest: true,
         
     | 
| 
       116 
147 
     | 
    
         
             
                            emptyOutDir: false,
         
     | 
| 
         @@ -118,12 +149,7 @@ const plugin = (options = {}) => { 
     | 
|
| 
       118 
149 
     | 
    
         
             
                            assetsInlineLimit: 0,
         
     | 
| 
       119 
150 
     | 
    
         
             
                            outDir: resolve(userConfig.root ?? process.cwd(), 'public'),
         
     | 
| 
       120 
151 
     | 
    
         
             
                            rollupOptions: {
         
     | 
| 
       121 
     | 
    
         
            -
                                input:  
     | 
| 
       122 
     | 
    
         
            -
                                    './src/styles/*.{css,pcss,scss,sass,less,styl,stylus}',
         
     | 
| 
       123 
     | 
    
         
            -
                                    './src/scripts/*.{js,ts,mjs}',
         
     | 
| 
       124 
     | 
    
         
            -
                                    './src/views/**/*.{json,latte,twig,liquid,njk,hbs,pug,html}',
         
     | 
| 
       125 
     | 
    
         
            -
                                    '!./src/views/**/*.{latte,twig,liquid,njk,hbs,pug,html}.json'
         
     | 
| 
       126 
     | 
    
         
            -
                                ]
         
     | 
| 
      
 152 
     | 
    
         
            +
                                input: defaultInput
         
     | 
| 
       127 
153 
     | 
    
         
             
                            }
         
     | 
| 
       128 
154 
     | 
    
         
             
                        }, userConfig.build ?? {})
         
     | 
| 
       129 
155 
     | 
    
         | 
| 
         @@ -139,6 +165,20 @@ const plugin = (options = {}) => { 
     | 
|
| 
       139 
165 
     | 
    
         
             
                                }
         
     | 
| 
       140 
166 
     | 
    
         
             
                                : false
         
     | 
| 
       141 
167 
     | 
    
         
             
                        }, userConfig.server ?? {})
         
     | 
| 
      
 168 
     | 
    
         
            +
                    },
         
     | 
| 
      
 169 
     | 
    
         
            +
                    writeBundle: async () => {
         
     | 
| 
      
 170 
     | 
    
         
            +
                        if (options.mode === 'emails') {
         
     | 
| 
      
 171 
     | 
    
         
            +
                            const emails = FastGlob.sync(`${resolve(process.cwd(), options.emails.outputDir)}/**`).filter(entry => !entry.endsWith('test.html'))
         
     | 
| 
      
 172 
     | 
    
         
            +
                            const emailsProd = emails.map(path => {
         
     | 
| 
      
 173 
     | 
    
         
            +
                                return path.replace(resolve(process.cwd(), options.emails.outputDir), resolve(process.cwd(), options.emails.appDir)).replace('.html', '.latte')
         
     | 
| 
      
 174 
     | 
    
         
            +
                            })
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                            await Promise.all(emails.map((file, i) =>
         
     | 
| 
      
 177 
     | 
    
         
            +
                                fse.move(file, emailsProd[i], { overwrite: true })
         
     | 
| 
      
 178 
     | 
    
         
            +
                            ))
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                            console.info(`${pc.cyan('@newlogic-digital/core')} ${pc.green(`all email files were moved to ${relative(process.cwd(), options.emails.appDir)}`)}`)
         
     | 
| 
      
 181 
     | 
    
         
            +
                        }
         
     | 
| 
       142 
182 
     | 
    
         
             
                    }
         
     | 
| 
       143 
183 
     | 
    
         
             
                }, ...plugins]
         
     | 
| 
       144 
184 
     | 
    
         
             
            }
         
     | 
    
        package/package.json
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            {
         
     | 
| 
       2 
2 
     | 
    
         
             
              "name": "@newlogic-digital/core",
         
     | 
| 
       3 
3 
     | 
    
         
             
              "type": "module",
         
     | 
| 
       4 
     | 
    
         
            -
              "version": "2.0.0-alpha. 
     | 
| 
      
 4 
     | 
    
         
            +
              "version": "2.0.0-alpha.8",
         
     | 
| 
       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",
         
     | 
| 
         @@ -22,7 +22,10 @@ 
     | 
|
| 
       22 
22 
     | 
    
         
             
                "posthtml-prism": "^2.0.0",
         
     | 
| 
       23 
23 
     | 
    
         
             
                "prismjs": "^1.29.0",
         
     | 
| 
       24 
24 
     | 
    
         
             
                "html-minifier-terser": "^7.2.0",
         
     | 
| 
       25 
     | 
    
         
            -
                "lodash": "^4.17.21"
         
     | 
| 
      
 25 
     | 
    
         
            +
                "lodash": "^4.17.21",
         
     | 
| 
      
 26 
     | 
    
         
            +
                "fast-glob": "^3.2.12",
         
     | 
| 
      
 27 
     | 
    
         
            +
                "fs-extra": "^11.1.1",
         
     | 
| 
      
 28 
     | 
    
         
            +
                "picocolors": "^1.0.0"
         
     | 
| 
       26 
29 
     | 
    
         
             
              },
         
     | 
| 
       27 
30 
     | 
    
         
             
              "devDependencies": {
         
     | 
| 
       28 
31 
     | 
    
         
             
                "@types/node": "^20.3.1",
         
     | 
| 
         @@ -34,7 +37,7 @@ 
     | 
|
| 
       34 
37 
     | 
    
         
             
              "files": [
         
     | 
| 
       35 
38 
     | 
    
         
             
                "latte",
         
     | 
| 
       36 
39 
     | 
    
         
             
                "index.js",
         
     | 
| 
       37 
     | 
    
         
            -
                "src 
     | 
| 
      
 40 
     | 
    
         
            +
                "src"
         
     | 
| 
       38 
41 
     | 
    
         
             
              ],
         
     | 
| 
       39 
42 
     | 
    
         
             
              "engines": {
         
     | 
| 
       40 
43 
     | 
    
         
             
                "node": ">=16.0.0",
         
     | 
    
        package/src/minify.js
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import minifier from 'html-minifier-terser'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 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 
     | 
    
         
            +
                })
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                if (name) {
         
     | 
| 
      
 14 
     | 
    
         
            +
                    return JSON.stringify({
         
     | 
| 
      
 15 
     | 
    
         
            +
                        [name]: minify
         
     | 
| 
      
 16 
     | 
    
         
            +
                    })
         
     | 
| 
      
 17 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 18 
     | 
    
         
            +
                    return JSON.stringify(minify)
         
     | 
| 
      
 19 
     | 
    
         
            +
                }
         
     | 
| 
      
 20 
     | 
    
         
            +
            }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            export default parseMinifyHtml
         
     | 
    
        package/src/twig.js
    ADDED
    
    | 
         @@ -0,0 +1,174 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            import fs from 'fs'
         
     | 
| 
      
 2 
     | 
    
         
            +
            import { resolve } from 'path'
         
     | 
| 
      
 3 
     | 
    
         
            +
            import parseMinifyHtml from './minify.js'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            const wrapPreCode = (code, lang) => {
         
     | 
| 
      
 6 
     | 
    
         
            +
                return `<pre class="language-${lang}"><code class="language-${lang}">${code}</code></pre>`
         
     | 
| 
      
 7 
     | 
    
         
            +
            }
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            const stripIndent = (string) => {
         
     | 
| 
      
 10 
     | 
    
         
            +
                const indent = () => {
         
     | 
| 
      
 11 
     | 
    
         
            +
                    const match = string.match(/^[ \t]*(?=\S)/gm)
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                    if (!match) {
         
     | 
| 
      
 14 
     | 
    
         
            +
                        return 0
         
     | 
| 
      
 15 
     | 
    
         
            +
                    }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    return match.reduce((r, a) => Math.min(r, a.length), Infinity)
         
     | 
| 
      
 18 
     | 
    
         
            +
                }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                if (indent() === 0) {
         
     | 
| 
      
 21 
     | 
    
         
            +
                    return string
         
     | 
| 
      
 22 
     | 
    
         
            +
                }
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                const regex = new RegExp(`^[ \\t]{${indent()}}`, 'gm')
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                return string.replace(regex, '')
         
     | 
| 
      
 27 
     | 
    
         
            +
            }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            export default {
         
     | 
| 
      
 30 
     | 
    
         
            +
                namespaces: {
         
     | 
| 
      
 31 
     | 
    
         
            +
                    src: resolve(process.cwd(), 'src'),
         
     | 
| 
      
 32 
     | 
    
         
            +
                    templates: resolve(process.cwd(), 'src/templates')
         
     | 
| 
      
 33 
     | 
    
         
            +
                },
         
     | 
| 
      
 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>'))
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                        return 'data:image/svg+xml;charset=UTF-8,' + svg
         
     | 
| 
      
 63 
     | 
    
         
            +
                    },
         
     | 
| 
      
 64 
     | 
    
         
            +
                    ratio: (width, height) => {
         
     | 
| 
      
 65 
     | 
    
         
            +
                        return (height / width) * 100
         
     | 
| 
      
 66 
     | 
    
         
            +
                    }
         
     | 
| 
      
 67 
     | 
    
         
            +
                },
         
     | 
| 
      
 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))
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                        return 'data:image/svg+xml;charset=UTF-8,' + svg
         
     | 
| 
      
 79 
     | 
    
         
            +
                    },
         
     | 
| 
      
 80 
     | 
    
         
            +
                    exists: (path) => {
         
     | 
| 
      
 81 
     | 
    
         
            +
                        if (path.indexOf('/') === 0) {
         
     | 
| 
      
 82 
     | 
    
         
            +
                            path = path.slice(1)
         
     | 
| 
      
 83 
     | 
    
         
            +
                        }
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                        return fs.existsSync(resolve(process.cwd(), path))
         
     | 
| 
      
 86 
     | 
    
         
            +
                    },
         
     | 
| 
      
 87 
     | 
    
         
            +
                    tel: (value) => {
         
     | 
| 
      
 88 
     | 
    
         
            +
                        return value.replace(/\s+/g, '').replace('(', '').replace(')', '')
         
     | 
| 
      
 89 
     | 
    
         
            +
                    }
         
     | 
| 
      
 90 
     | 
    
         
            +
                },
         
     | 
| 
      
 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 
     | 
    
         
            +
                        })
         
     | 
| 
      
 132 
     | 
    
         
            +
                    },
         
     | 
| 
      
 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 
     | 
    
         
            +
                ]
         
     | 
| 
      
 174 
     | 
    
         
            +
            }
         
     |