@@ -4,7 +4,7 @@ import {dirname, join, resolve} from "node:path";
44import { fileURLToPath } from "node:url" ;
55import type { TemplateLiteral } from "acorn" ;
66import { JSDOM } from "jsdom" ;
7- import type { PluginOption } from "vite" ;
7+ import type { PluginOption , IndexHtmlTransformContext } from "vite" ;
88import type { Cell } from "../lib/notebook.js" ;
99import { deserialize } from "../lib/serialize.js" ;
1010import { Sourcemap } from "../javascript/sourcemap.js" ;
@@ -23,13 +23,16 @@ export interface ObservableOptions {
2323 serializer ?: XMLSerializer ;
2424 /** The path to the page template; defaults to the default template. */
2525 template ?: string ;
26+ /** A function which performs a per-page transformation of the template HTML. */
27+ transformTemplate ?: ( template : string , context : IndexHtmlTransformContext ) => string | Promise < string > ;
2628}
2729
2830export function observable ( {
2931 window = new JSDOM ( ) . window ,
3032 parser = new window . DOMParser ( ) ,
3133 serializer = new window . XMLSerializer ( ) ,
32- template = fileURLToPath ( import . meta. resolve ( "../templates/default.html" ) )
34+ template = fileURLToPath ( import . meta. resolve ( "../templates/default.html" ) ) ,
35+ transformTemplate = undefined
3336} : ObservableOptions = { } ) : PluginOption {
3437 return {
3538 name : "observable" ,
@@ -45,7 +48,10 @@ export function observable({
4548 order : "pre" ,
4649 async handler ( input , context ) {
4750 const notebook = deserialize ( input , { parser} ) ;
48- const tsource = await readFile ( template , "utf-8" ) ;
51+ let tsource = await readFile ( template , "utf-8" ) ;
52+ if ( transformTemplate !== undefined ) {
53+ tsource = await transformTemplate ( tsource , context ) ;
54+ }
4955 const document = parser . parseFromString ( tsource , "text/html" ) ;
5056 const statics = new Set < Cell > ( ) ;
5157 const assets = new Set < string > ( ) ;
0 commit comments