Copy a directory into the output
Bring an existing file or directory tree into the output, templating text on the way.
Rendered from
docs/how-to/copy-a-directory.md
in the generator repository — where a correction belongs, and where the
test suite runs every example on this page or states why it does not.
Copy brings in a file or a whole tree. Text files pass through the
template system, so $$path$$ works in copied content; binaries are
copied byte for byte.
The source tree is under tpl/. A templated asset, tpl/assets/logo.svg:
<svg><!-- $$title$$ --></svg>
Something a level deeper, tpl/assets/style/site.css:
body { font-family: sans-serif; }
And a single file to rename, tpl/readme.txt:
# $$title$$
import { Jostraca, Project, Folder, Copy } from 'jostraca'
const jostraca = Jostraca({ model: { title: 'My App' } })
await jostraca.generate({ folder: './out' }, () => {
Project({ folder: 'app' }, () => {
Folder({ name: 'static' }, () => {
Copy({ from: './tpl/assets' })
})
Copy({ from: './tpl/readme.txt', to: 'README.txt' })
})
})
app/README.txt
app/static/logo.svg
app/static/style/site.css
The tree keeps its shape, and $$title$$ was substituted in
logo.svg:
<svg><!-- My App --></svg>
to renames a single file and names a subfolder for a directory. Both
may contain slashes.
The one asymmetry to remember: a relative from resolves against the
process working directory, not against the output folder the way
Fragment’s from does. In a generator you publish, build an absolute
path from import.meta.url rather than relying on where the user
happened to be standing.
Text or binary is decided by the extension first, against a fixed list
of around 250. Because no such list is complete, the content is then
sniffed: a NUL byte in the first 8192 promotes an unlisted file to
binary, which is what keeps .wasm and extensionless files intact.
See also#
- Skip files when copying.
- Component reference for every prop.