nav tabs on admin dashboard
This commit is contained in:
60
node_modules/vue/src/server/template-renderer/index.js
generated
vendored
60
node_modules/vue/src/server/template-renderer/index.js
generated
vendored
@@ -11,11 +11,12 @@ import type { ParsedTemplate } from './parse-template'
|
||||
import type { AsyncFileMapper } from './create-async-file-mapper'
|
||||
|
||||
type TemplateRendererOptions = {
|
||||
template: ?string;
|
||||
template?: string | (content: string, context: any) => string;
|
||||
inject?: boolean;
|
||||
clientManifest?: ClientManifest;
|
||||
shouldPreload?: (file: string, type: string) => boolean;
|
||||
shouldPrefetch?: (file: string, type: string) => boolean;
|
||||
serializer?: Function;
|
||||
};
|
||||
|
||||
export type ClientManifest = {
|
||||
@@ -41,26 +42,39 @@ type Resource = {
|
||||
export default class TemplateRenderer {
|
||||
options: TemplateRendererOptions;
|
||||
inject: boolean;
|
||||
parsedTemplate: ParsedTemplate | null;
|
||||
parsedTemplate: ParsedTemplate | Function | null;
|
||||
publicPath: string;
|
||||
clientManifest: ClientManifest;
|
||||
preloadFiles: Array<Resource>;
|
||||
prefetchFiles: Array<Resource>;
|
||||
mapFiles: AsyncFileMapper;
|
||||
serialize: Function;
|
||||
|
||||
constructor (options: TemplateRendererOptions) {
|
||||
this.options = options
|
||||
this.inject = options.inject !== false
|
||||
// if no template option is provided, the renderer is created
|
||||
// as a utility object for rendering assets like preload links and scripts.
|
||||
this.parsedTemplate = options.template
|
||||
? parseTemplate(options.template)
|
||||
|
||||
const { template } = options
|
||||
this.parsedTemplate = template
|
||||
? typeof template === 'string'
|
||||
? parseTemplate(template)
|
||||
: template
|
||||
: null
|
||||
|
||||
// function used to serialize initial state JSON
|
||||
this.serialize = options.serializer || (state => {
|
||||
return serialize(state, { isJSON: true })
|
||||
})
|
||||
|
||||
// extra functionality with client manifest
|
||||
if (options.clientManifest) {
|
||||
const clientManifest = this.clientManifest = options.clientManifest
|
||||
this.publicPath = clientManifest.publicPath.replace(/\/$/, '')
|
||||
// ensure publicPath ends with /
|
||||
this.publicPath = clientManifest.publicPath === ''
|
||||
? ''
|
||||
: clientManifest.publicPath.replace(/([^\/])$/, '$1/')
|
||||
// preload/prefetch directives
|
||||
this.preloadFiles = (clientManifest.initial || []).map(normalizeFile)
|
||||
this.prefetchFiles = (clientManifest.async || []).map(normalizeFile)
|
||||
@@ -79,12 +93,17 @@ export default class TemplateRenderer {
|
||||
}
|
||||
|
||||
// render synchronously given rendered app content and render context
|
||||
renderSync (content: string, context: ?Object) {
|
||||
render (content: string, context: ?Object): string | Promise<string> {
|
||||
const template = this.parsedTemplate
|
||||
if (!template) {
|
||||
throw new Error('renderSync cannot be called without a template.')
|
||||
throw new Error('render cannot be called without a template.')
|
||||
}
|
||||
context = context || {}
|
||||
|
||||
if (typeof template === 'function') {
|
||||
return template(content, context)
|
||||
}
|
||||
|
||||
if (this.inject) {
|
||||
return (
|
||||
template.head(context) +
|
||||
@@ -108,13 +127,13 @@ export default class TemplateRenderer {
|
||||
}
|
||||
|
||||
renderStyles (context: Object): string {
|
||||
const cssFiles = this.clientManifest
|
||||
? this.clientManifest.all.filter(isCSS)
|
||||
: []
|
||||
const initial = this.preloadFiles || []
|
||||
const async = this.getUsedAsyncFiles(context) || []
|
||||
const cssFiles = initial.concat(async).filter(({ file }) => isCSS(file))
|
||||
return (
|
||||
// render links for css files
|
||||
(cssFiles.length
|
||||
? cssFiles.map(file => `<link rel="stylesheet" href="${this.publicPath}/${file}">`).join('')
|
||||
? cssFiles.map(({ file }) => `<link rel="stylesheet" href="${this.publicPath}${file}">`).join('')
|
||||
: '') +
|
||||
// context.styles is a getter exposed by vue-style-loader which contains
|
||||
// the inline component styles collected during SSR
|
||||
@@ -153,7 +172,7 @@ export default class TemplateRenderer {
|
||||
extra = ` type="font/${extension}" crossorigin`
|
||||
}
|
||||
return `<link rel="preload" href="${
|
||||
this.publicPath}/${file
|
||||
this.publicPath}${file
|
||||
}"${
|
||||
asType !== '' ? ` as="${asType}"` : ''
|
||||
}${
|
||||
@@ -179,7 +198,7 @@ export default class TemplateRenderer {
|
||||
if (alreadyRendered(file)) {
|
||||
return ''
|
||||
}
|
||||
return `<link rel="prefetch" href="${this.publicPath}/${file}">`
|
||||
return `<link rel="prefetch" href="${this.publicPath}${file}">`
|
||||
}).join('')
|
||||
} else {
|
||||
return ''
|
||||
@@ -191,22 +210,23 @@ export default class TemplateRenderer {
|
||||
contextKey = 'state',
|
||||
windowKey = '__INITIAL_STATE__'
|
||||
} = options || {}
|
||||
const state = serialize(context[contextKey], { isJSON: true })
|
||||
const state = this.serialize(context[contextKey])
|
||||
const autoRemove = process.env.NODE_ENV === 'production'
|
||||
? ';(function(){var s;(s=document.currentScript||document.scripts[document.scripts.length-1]).parentNode.removeChild(s);}());'
|
||||
: ''
|
||||
const nonceAttr = context.nonce ? ` nonce="${context.nonce}"` : ''
|
||||
return context[contextKey]
|
||||
? `<script>window.${windowKey}=${state}${autoRemove}</script>`
|
||||
? `<script${nonceAttr}>window.${windowKey}=${state}${autoRemove}</script>`
|
||||
: ''
|
||||
}
|
||||
|
||||
renderScripts (context: Object): string {
|
||||
if (this.clientManifest) {
|
||||
const initial = this.preloadFiles
|
||||
const async = this.getUsedAsyncFiles(context)
|
||||
const needed = [initial[0]].concat(async || [], initial.slice(1))
|
||||
return needed.filter(({ file }) => isJS(file)).map(({ file }) => {
|
||||
return `<script src="${this.publicPath}/${file}" defer></script>`
|
||||
const initial = this.preloadFiles.filter(({ file }) => isJS(file))
|
||||
const async = (this.getUsedAsyncFiles(context) || []).filter(({ file }) => isJS(file))
|
||||
const needed = [initial[0]].concat(async, initial.slice(1))
|
||||
return needed.map(({ file }) => {
|
||||
return `<script src="${this.publicPath}${file}" defer></script>`
|
||||
}).join('')
|
||||
} else {
|
||||
return ''
|
||||
|
||||
Reference in New Issue
Block a user