diff --git a/src/Http/View/View.imba b/src/Http/View/View.imba index d72ff7b0..24e7b27f 100644 --- a/src/Http/View/View.imba +++ b/src/Http/View/View.imba @@ -7,6 +7,7 @@ import isString from '../../Support/Helpers/isString' import querystring from 'querystring' import UndefinedDataPropException from './Exceptions/UndefinedDataPropException' import Language from '../../Support/Language/Language' +import viteHelper from '../../Support/Helpers/vite' export default class View @@ -36,6 +37,40 @@ export default class View self + def vite file\string|string[] + if Array.isArray(file) + let tags = [] + + for asset in file + if !isString(asset) + throw TypeError "Expected string." + + const jsTagExtensions = ['js', 'ts'] + const cssTagExtensions = ['css', 'scss', 'sass', 'less', 'styl', 'stylus'] + const imgTagExtensions = ['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp', 'avif'] + const fontTagExtensions = ['woff', 'woff2', 'eot', 'ttf', 'otf'] + + const extension = asset.split('.').pop!.toLowerCase! + + if !isString(extension) + throw new Error "Could not determine file extension for: {asset}" + + if jsTagExtensions.includes(extension) + tags.push("") + else if cssTagExtensions.includes(extension) + tags.push("") + else if imgTagExtensions.includes(extension) + tags.push("") + else if fontTagExtensions.includes(extension) + tags.push("") + else + throw new Error "Unsupported file extension: {extension}" + + if tags.length > 0 + tags.join('\n') + else + viteHelper(file) + def translate key\string, default\any self.#_language.get(key, default) diff --git a/src/Support/Helpers/index.imba b/src/Support/Helpers/index.imba index 00d15530..01a6a3fd 100644 --- a/src/Support/Helpers/index.imba +++ b/src/Support/Helpers/index.imba @@ -35,6 +35,7 @@ const { default: toBoolean } = require './toBoolean' const { default: updateLine } = require './updateLine' const { default: version } = require './version' const { default: view } = require './view' +const { default: vite } = require './vite' const { default: wildcard } = require './wildcard' const { default: without } = require './without' @@ -81,6 +82,7 @@ export { updateLine version view + vite wildcard without } diff --git a/src/Support/Helpers/vite.imba b/src/Support/Helpers/vite.imba new file mode 100644 index 00000000..258f3cf5 --- /dev/null +++ b/src/Support/Helpers/vite.imba @@ -0,0 +1,4 @@ +import Repository from '../../Vite/Repository' + +export default def vite file\string + Repository.get file diff --git a/src/Vite/Repository.imba b/src/Vite/Repository.imba new file mode 100644 index 00000000..ab4904c6 --- /dev/null +++ b/src/Vite/Repository.imba @@ -0,0 +1,46 @@ +import { readFileSync, existsSync } from 'fs' +import { join } from 'path' + +export default class Repository + + static manifestCache\ViteManifest|null = null + + static def get file\string + const manifest = self.getManifest! + + if !manifest + return file + + const normalizedFile = file.startsWith('/') ? file.slice(1) : file + + if manifest[normalizedFile] + return '/build/' + manifest[normalizedFile].file + + if normalizedFile == 'css/app.css' + for [key, value] in Object.entries(manifest) + if key.includes('css/app.css') + return '/build/' + value.file + + if normalizedFile == 'js/app.js' + for [key, value] in Object.entries(manifest) + if key.includes('js/app.ts') + return '/build/' + value.file + + file + + static def getManifest\ViteManifest|null + if self.manifestCache != null + return self.manifestCache + + const location = join(process.cwd!, 'public', 'build', '.vite', 'manifest.json') + + try + if existsSync(location) + const content = readFileSync(location, 'utf8') + self.manifestCache = content ? JSON.parse(content) : null + else + self.manifestCache = null + catch err + self.manifestCache = null + + self.manifestCache diff --git a/types/Http/View/View.d.ts b/types/Http/View/View.d.ts index 359b369b..d0fd2672 100644 --- a/types/Http/View/View.d.ts +++ b/types/Http/View/View.d.ts @@ -31,6 +31,14 @@ export default class View { */ __(key: string, default$?: string): string; + /** + * Get asset path(s) from Vite manifest. + * + * @param {string | string[]} file + * @returns {string} + */ + vite(file: string | string[]): string; + /** * Get old input. */ diff --git a/types/Support/Helpers/mix.d.ts b/types/Support/Helpers/mix.d.ts index 293e0865..8c9d5d68 100644 --- a/types/Support/Helpers/mix.d.ts +++ b/types/Support/Helpers/mix.d.ts @@ -1,4 +1,7 @@ /** -@param {string} file -*/ + * Get asset path from Laravel Mix manifest. + * @param {string} file + * @returns {string} + * @deprecated + */ export default function mix(file: string): string; diff --git a/types/Support/Helpers/vite.d.ts b/types/Support/Helpers/vite.d.ts new file mode 100644 index 00000000..7e06aebc --- /dev/null +++ b/types/Support/Helpers/vite.d.ts @@ -0,0 +1,7 @@ +/** + * Get asset path(s) from Vite manifest. + * + * @param {string | string[]} file + * @returns {string} + */ +export default function vite(file: string | string[]): string; diff --git a/types/Vite/Repository.d.ts b/types/Vite/Repository.d.ts new file mode 100644 index 00000000..56040b83 --- /dev/null +++ b/types/Vite/Repository.d.ts @@ -0,0 +1,16 @@ +interface ViteManifest { + [key: string]: { + file: string; + src?: string; + isEntry?: boolean; + imports?: string[]; + css?: string[]; + assets?: string[]; + }; +} + +export default class Repository { + static manifestCache: ViteManifest | null = null; + static file(file: string): string; + static getManifest(): ViteManifest | null; +}