Class: Typstify::Workspace
- Inherits:
-
Object
- Object
- Typstify::Workspace
- Defined in:
- lib/typstify/workspace.rb
Overview
A throwaway directory holding everything one compile is allowed to see.
<tmp>/main.typ the template
<tmp>/data.json your data
<tmp>/shared/ config.shared_dir, copied
Typst is invoked with this directory as its root, so #read("../.env")
cannot reach your application — not because we filter it, but because the
file is not there. That is the whole security model, and it is why the
template is copied to the root of the workspace rather than nested: Typst
resolves relative imports against the importing file, so main-at-root is
what makes #import "shared/branding.typ" work from any view subdirectory.
Every render gets its own workspace, which is also what makes concurrent rendering safe.
Constant Summary collapse
- MAIN =
"main.typ"- DATA =
"data.json"
Instance Attribute Summary collapse
-
#dir ⇒ Object
readonly
Returns the value of attribute dir.
Class Method Summary collapse
-
.build(source:, data:, config: Typstify.config) ⇒ Object
Yields a Workspace and removes it afterwards, exception or not.
Instance Method Summary collapse
-
#copy_shared ⇒ Object
Copy config.shared_dir in, if it exists.
-
#initialize(dir, config) ⇒ Workspace
constructor
A new instance of Workspace.
- #main_path ⇒ Object
-
#write_data(data) ⇒ Object
Takes the already-serialised JSON string: validation happens in Document, before a workspace exists.
- #write_main(source) ⇒ Object
Constructor Details
#initialize(dir, config) ⇒ Workspace
Returns a new instance of Workspace.
40 41 42 43 |
# File 'lib/typstify/workspace.rb', line 40 def initialize(dir, config) @dir = dir @config = config end |
Instance Attribute Details
#dir ⇒ Object (readonly)
Returns the value of attribute dir.
27 28 29 |
# File 'lib/typstify/workspace.rb', line 27 def dir @dir end |
Class Method Details
.build(source:, data:, config: Typstify.config) ⇒ Object
Yields a Workspace and removes it afterwards, exception or not.
30 31 32 33 34 35 36 37 38 |
# File 'lib/typstify/workspace.rb', line 30 def self.build(source:, data:, config: Typstify.config) Dir.mktmpdir("typstify-") do |tmp| workspace = new(Pathname.new(tmp), config) workspace.write_main(source) workspace.write_data(data) workspace.copy_shared yield workspace end end |
Instance Method Details
#copy_shared ⇒ Object
Copy config.shared_dir in, if it exists. Copies rather than symlinks: a symlink inside the root points outside the root, which would hand back exactly the file-system access the workspace exists to remove. Symlinks found in the source tree are skipped for the same reason.
61 62 63 64 65 66 67 |
# File 'lib/typstify/workspace.rb', line 61 def copy_shared source = @config.template_root.join(@config.shared_dir) return unless source.directory? destination = dir.join(@config.shared_dir) copy_tree(source, destination) end |
#main_path ⇒ Object
45 |
# File 'lib/typstify/workspace.rb', line 45 def main_path = dir.join(MAIN) |
#write_data(data) ⇒ Object
Takes the already-serialised JSON string: validation happens in Document, before a workspace exists.
53 54 55 |
# File 'lib/typstify/workspace.rb', line 53 def write_data(data) File.write(dir.join(DATA), data || "{}", encoding: Encoding::UTF_8) end |
#write_main(source) ⇒ Object
47 48 49 |
# File 'lib/typstify/workspace.rb', line 47 def write_main(source) File.write(main_path, source, encoding: Encoding::UTF_8) end |