108 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import { GlobalConfiguration } from '../cfg'
 | 
						|
import { QuartzComponent } from '../components/types'
 | 
						|
import { StaticResources } from '../resources'
 | 
						|
import { joinStyles } from '../theme'
 | 
						|
import { EmitCallback, PluginTypes } from './types'
 | 
						|
import styles from '../styles/base.scss'
 | 
						|
import { FilePath, ServerSlug } from '../path'
 | 
						|
 | 
						|
export type ComponentResources = {
 | 
						|
  css: string[],
 | 
						|
  beforeDOMLoaded: string[],
 | 
						|
  afterDOMLoaded: string[]
 | 
						|
}
 | 
						|
 | 
						|
export function getComponentResources(plugins: PluginTypes): ComponentResources {
 | 
						|
  const allComponents: Set<QuartzComponent> = new Set()
 | 
						|
  for (const emitter of plugins.emitters) {
 | 
						|
    const components = emitter.getQuartzComponents()
 | 
						|
    for (const component of components) {
 | 
						|
      allComponents.add(component)
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  const componentResources = {
 | 
						|
    css: new Set<string>(),
 | 
						|
    beforeDOMLoaded: new Set<string>(),
 | 
						|
    afterDOMLoaded: new Set<string>()
 | 
						|
  }
 | 
						|
 | 
						|
  for (const component of allComponents) {
 | 
						|
    const { css, beforeDOMLoaded, afterDOMLoaded } = component
 | 
						|
    if (css) {
 | 
						|
      componentResources.css.add(css)
 | 
						|
    }
 | 
						|
    if (beforeDOMLoaded) {
 | 
						|
      componentResources.beforeDOMLoaded.add(beforeDOMLoaded)
 | 
						|
    }
 | 
						|
    if (afterDOMLoaded) {
 | 
						|
      componentResources.afterDOMLoaded.add(afterDOMLoaded)
 | 
						|
    }
 | 
						|
  }
 | 
						|
  
 | 
						|
  return {
 | 
						|
    css: [...componentResources.css],
 | 
						|
    beforeDOMLoaded: [...componentResources.beforeDOMLoaded],
 | 
						|
    afterDOMLoaded: [...componentResources.afterDOMLoaded]
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function joinScripts(scripts: string[]): string {
 | 
						|
  // wrap with iife to prevent scope collision
 | 
						|
  return scripts.map(script => `(function () {${script}})();`).join("\n")
 | 
						|
}
 | 
						|
 | 
						|
export async function emitComponentResources(cfg: GlobalConfiguration, res: ComponentResources, emit: EmitCallback): Promise<FilePath[]> {
 | 
						|
  const fps = await Promise.all([
 | 
						|
    emit({
 | 
						|
      slug: "index",
 | 
						|
      ext: ".css",
 | 
						|
      content: joinStyles(cfg.theme, styles, ...res.css)
 | 
						|
    }),
 | 
						|
    emit({
 | 
						|
      slug: "prescript",
 | 
						|
      ext: ".js",
 | 
						|
      content: joinScripts(res.beforeDOMLoaded)
 | 
						|
    }),
 | 
						|
    emit({
 | 
						|
      slug: "postscript",
 | 
						|
      ext: ".js",
 | 
						|
      content: joinScripts(res.afterDOMLoaded)
 | 
						|
    })
 | 
						|
  ])
 | 
						|
  return fps
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
export function getStaticResourcesFromPlugins(plugins: PluginTypes) {
 | 
						|
  const staticResources: StaticResources = {
 | 
						|
    css: [],
 | 
						|
    js: [],
 | 
						|
  }
 | 
						|
 | 
						|
  for (const transformer of plugins.transformers) {
 | 
						|
    const res = transformer.externalResources ? transformer.externalResources() : {}
 | 
						|
    if (res?.js) {
 | 
						|
      staticResources.js.push(...res.js)
 | 
						|
    }
 | 
						|
    if (res?.css) {
 | 
						|
      staticResources.css.push(...res.css)
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return staticResources
 | 
						|
}
 | 
						|
 | 
						|
export * from './transformers'
 | 
						|
export * from './filters'
 | 
						|
export * from './emitters'
 | 
						|
 | 
						|
declare module 'vfile' {
 | 
						|
  // inserted in processors.ts
 | 
						|
  interface DataMap {
 | 
						|
    slug: ServerSlug
 | 
						|
    allSlugs: ServerSlug[]
 | 
						|
    filePath: FilePath
 | 
						|
  }
 | 
						|
}
 |