@@ -23,9 +23,9 @@ import { kIncludeAfterBody, kIncludeInHeader } from "../../config/constants.ts";
2323import { TempContext } from "../../core/temp.ts" ;
2424import { lines } from "../../core/lib/text.ts" ;
2525import { copyFileIfNewer } from "../../core/copy.ts" ;
26- import { ProjectContext } from "../../project/types.ts" ;
2726import {
2827 appendDependencies ,
28+ HtmlAttachmentDependency ,
2929 HtmlFormatDependency ,
3030} from "./pandoc-dependencies.ts" ;
3131import { fixupCssReferences , isCssFile } from "../../core/css.ts" ;
@@ -54,32 +54,60 @@ export function readAndInjectDependencies(
5454 inputDir : string ,
5555 libDir : string ,
5656 doc : Document ,
57- project ?: ProjectContext ,
5857) {
5958 const dependencyJsonStream = Deno . readTextFileSync ( dependenciesFile ) ;
6059 const htmlDependencies : FormatDependency [ ] = [ ] ;
60+ const htmlAttachments : HtmlAttachmentDependency [ ] = [ ] ;
6161 lines ( dependencyJsonStream ) . forEach ( ( json ) => {
6262 if ( json ) {
6363 const dependency = JSON . parse ( json ) ;
6464 if ( dependency . type === "html" ) {
6565 htmlDependencies . push ( dependency . content ) ;
66+ } else if ( dependency . type === "html-attachment" ) {
67+ htmlAttachments . push ( dependency ) ;
6668 }
6769 }
6870 } ) ;
6971
72+ const injectedDependencies = [ ] ;
7073 if ( htmlDependencies . length > 0 ) {
7174 const injector = domDependencyInjector ( doc ) ;
72- processHtmlDependencies (
75+ const injected = processHtmlDependencies (
7376 htmlDependencies ,
7477 inputDir ,
7578 libDir ,
7679 injector ,
77- project ,
7880 ) ;
81+ injectedDependencies . push ( ...injected ) ;
7982 // Finalize the injection
8083 injector . finalizeInjection ( ) ;
8184 }
8285
86+ if ( htmlAttachments . length > 0 ) {
87+ for ( const attachment of htmlAttachments ) {
88+ // Find the 'parent' dependencies for this attachment
89+ const parentDependency = injectedDependencies . find ( ( dep ) => {
90+ return dep . name === attachment . content . name ;
91+ } ) ;
92+
93+ if ( parentDependency ) {
94+ // Compute the target directory
95+ const directoryInfo = targetDirectoryInfo (
96+ inputDir ,
97+ libDir ,
98+ parentDependency ,
99+ ) ;
100+
101+ // copy the file
102+ copyDependencyFile (
103+ attachment . content . file ,
104+ directoryInfo . absolute ,
105+ ! ! parentDependency . external ,
106+ ) ;
107+ }
108+ }
109+ }
110+
83111 return Promise . resolve ( {
84112 resources : [ ] ,
85113 supporting : [ ] ,
@@ -91,7 +119,6 @@ export function resolveDependencies(
91119 inputDir : string ,
92120 libDir : string ,
93121 temp : TempContext ,
94- project : ProjectContext | undefined ,
95122) {
96123 // deep copy to not mutate caller's object
97124 extras = ld . cloneDeep ( extras ) ;
@@ -106,7 +133,6 @@ export function resolveDependencies(
106133 inputDir ,
107134 libDir ,
108135 injector ,
109- project ,
110136 ) ;
111137 // Finalize the injection
112138 injector . finalizeInjection ( ) ;
@@ -170,25 +196,24 @@ function processHtmlDependencies(
170196 inputDir : string ,
171197 libDir : string ,
172198 injector : HtmlInjector ,
173- project ?: ProjectContext ,
174199) {
175- const copiedDependencies : string [ ] = [ ] ;
200+ const copiedDependencies : FormatDependency [ ] = [ ] ;
176201 for ( const dependency of dependencies ) {
177202 // Ensure that we copy (and render HTML for) each named dependency only once
178- if ( copiedDependencies . includes ( dependency . name ) ) {
203+ if (
204+ copiedDependencies . find ( ( copiedDep ) => {
205+ return copiedDep . name === dependency . name ;
206+ } )
207+ ) {
179208 continue ;
180209 }
181210
182211 // provide a format libs (i.e. freezer protected) scope for injected deps
183- const targetLibDir = dependency . external
184- ? join ( libDir , "quarto-contrib" )
185- : libDir ;
186-
187- // Directory information for the dependency
188- const dir = dependency . version
189- ? `${ dependency . name } -${ dependency . version } `
190- : dependency . name ;
191- const targetDir = join ( inputDir , targetLibDir , dir ) ;
212+ const directoryInfo = targetDirectoryInfo (
213+ inputDir ,
214+ libDir ,
215+ dependency ,
216+ ) ;
192217
193218 const copyFile = (
194219 file : DependencyFile ,
@@ -198,22 +223,13 @@ function processHtmlDependencies(
198223 afterBody ?: boolean ,
199224 ) => void ,
200225 ) => {
201- const targetPath = join ( targetDir , file . name ) ;
202- // If this is a user resource, treat it as a resource (resource ref discovery)
203- // if this something that we're injecting, just copy it
204- if ( dependency . external ) {
205- ensureDirSync ( dirname ( targetPath ) ) ;
206- copyFileIfNewer ( file . path , targetPath ) ;
207- console . log ( "Copying " + file . path + " to " + targetPath ) ;
208- if ( isCssFile ( file . path ) ) {
209- processCssFile ( dirname ( file . path ) , targetPath ) ;
210- }
211- } else {
212- copyFileIfNewer ( file . path , targetPath ) ;
213- }
214-
215- const href = join ( targetLibDir , dir , file . name ) ;
226+ copyDependencyFile (
227+ file ,
228+ directoryInfo . absolute ,
229+ dependency . external || false ,
230+ ) ;
216231 if ( inject ) {
232+ const href = join ( directoryInfo . relative , file . name ) ;
217233 inject ( href , file . attribs , file . afterBody ) ;
218234 }
219235 } ;
@@ -260,10 +276,50 @@ function processHtmlDependencies(
260276 dependency . resources . forEach ( ( resource ) => copyFile ( resource ) ) ;
261277 }
262278
263- copiedDependencies . push ( dependency . name ) ;
279+ copiedDependencies . push ( dependency ) ;
280+ }
281+ return copiedDependencies ;
282+ }
283+
284+ function copyDependencyFile (
285+ file : DependencyFile ,
286+ targetDir : string ,
287+ external : boolean ,
288+ ) {
289+ const targetPath = join ( targetDir , file . name ) ;
290+ // If this is a user resource, treat it as a resource (resource ref discovery)
291+ // if this something that we're injecting, just copy it
292+ ensureDirSync ( dirname ( targetPath ) ) ;
293+ copyFileIfNewer ( file . path , targetPath ) ;
294+
295+ if ( external && isCssFile ( file . path ) ) {
296+ processCssFile ( dirname ( file . path ) , targetPath ) ;
264297 }
265298}
266299
300+ function targetDirectoryInfo (
301+ inputDir : string ,
302+ libDir : string ,
303+ dependency : FormatDependency ,
304+ ) {
305+ // provide a format libs (i.e. freezer protected) scope for injected deps
306+ const targetLibDir = dependency . external
307+ ? join ( libDir , "quarto-contrib" )
308+ : libDir ;
309+
310+ // Directory information for the dependency
311+ const dir = dependency . version
312+ ? `${ dependency . name } -${ dependency . version } `
313+ : dependency . name ;
314+
315+ const relativeTargetDir = join ( targetLibDir , dir ) ;
316+ const absoluteTargetDir = join ( inputDir , relativeTargetDir ) ;
317+ return {
318+ absolute : absoluteTargetDir ,
319+ relative : relativeTargetDir ,
320+ } ;
321+ }
322+
267323// fixup root ('/') css references and also copy references to other
268324// stylesheet or resources (e.g. images) to alongside the destFile
269325function processCssFile (
0 commit comments