use std::fs;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use crate::typst::io::write_if_changed;
const GENERATED_SYNTAX_THEME_FILE: &str = "runtime/00_syntax-theme.typ";
struct RuntimeFile {
path: &'static str,
source: &'static str,
}
include!(concat!(env!("OUT_DIR"), "/typst_runtime_assets.rs"));
fn runtime_source_files() -> &'static [RuntimeFile] {
RUNTIME_FILES
}
fn runtime_facade_source() -> Result<String> {
Ok(r#"// Generated by Calepin. Do not edit.
#import "runtime/core/state.typ" as state
#import "runtime/core/target.typ" as target
#import "runtime/notebook/render.typ" as render
#import "runtime/notebook/options.typ" as options
#import "runtime/notebook/chunk.typ" as chunks
#import "runtime/elements/mod.typ" as elementmod
#let pages = state.pages
#let setup = options.setup
#let chunk = chunks.chunk
#let inline = chunks.inline
#let results = chunks.results
#let chunk_from_raw_plain = chunks.chunk_from_raw_plain
#let code-block = render.code-block
#let elements = elementmod
#let _mode = target._mode
#let _is-html = target._is-html
#let _is-paged = target._is-paged
#let _is-query = target._is-query
#let _is-render = target._is-render
#let _call-defaults = state._call-defaults
#let _disable-raw-chunk-transforms = state._disable-raw-chunk-transforms
#let _resolve-options = options._resolve-options
#let _html-themed-raw-block = render._html-themed-raw-block
#let _without-raw-chunk-transforms = chunks._without-raw-chunk-transforms
#let _fenced-chunks-runs = chunks._fenced-chunks-runs
"#
.to_string())
}
#[cfg(test)]
pub fn write_runtime(root: &Path) -> Result<PathBuf> {
write_runtime_with_syntax_theme(root, &crate::html::HtmlSyntaxTheme::builtin())
}
pub(crate) fn write_runtime_with_syntax_theme(
root: &Path,
syntax_theme: &crate::html::HtmlSyntaxTheme,
) -> Result<PathBuf> {
let calepin_dir = root.join(".calepin");
let runtime_dir = calepin_dir.join("runtime");
fs::create_dir_all(&runtime_dir)
.with_context(|| format!("failed to create {}", runtime_dir.display()))?;
write_if_changed(
&calepin_dir.join(GENERATED_SYNTAX_THEME_FILE),
syntax_theme.typst_runtime_source(),
)?;
for source_file in runtime_source_files() {
let destination = runtime_dir.join(source_file.path);
write_if_changed(&destination, source_file.source)?;
}
let facade = calepin_dir.join("calepin.typ");
write_if_changed(&facade, runtime_facade_source()?)?;
Ok(facade)
}
#[cfg(test)]
mod embedded_runtime_tests {
use super::*;
#[test]
fn runtime_source_files_are_embedded_relative_typ_files() {
let files = runtime_source_files();
assert!(!files.is_empty(), "expected embedded Typst runtime files");
for file in files {
let path = Path::new(file.path);
assert!(
path.is_relative(),
"runtime asset path should be relative: {}",
file.path
);
assert_eq!(
path.extension().and_then(|extension| extension.to_str()),
Some("typ")
);
assert!(
!file.source.is_empty(),
"runtime asset should have embedded source: {}",
file.path
);
}
}
}
#[cfg(test)]
#[path = "runtime_tests.rs"]
mod runtime_tests;