Module: TypstRails::Helpers
- Included in:
- Renderer
- Defined in:
- lib/typst_rails/helpers.rb
Overview
Helper methods for working with Typst templates.
This module provides utilities for:
- Escaping special Typst characters
- Converting HTML to Markdown and Typst
- Converting Markdown to Typst syntax
- Including external Markdown files
- Sanitizing HTML for security
- URL encoding
These helpers are included in the Renderer and available in Rails ERB templates when using the Typst template handler.
Constant Summary collapse
- DEFAULT_ALLOWED_TAGS =
MARK: - HTML Sanitization
%w[ h1 h2 h3 h4 h5 h6 p br strong em u s del ins ul ol li blockquote pre code a img table thead tbody tr th td ].freeze
- DEFAULT_ALLOWED_ATTRIBUTES =
%w[href src alt title].freeze
Instance Method Summary collapse
-
#escape_typst(text) ⇒ String
MARK: - Text Escaping Escapes text for safe use in Typst documents.
-
#html_to_markdown(html, options = {}) ⇒ String
Converts HTML to Markdown for use in Typst documents.
-
#html_to_typst(html, options = {}) ⇒ String
Converts HTML to Typst-compatible markup.
-
#include_markdown(markdown_path) ⇒ String
Reads and includes Markdown content, converting it to Typst syntax.
-
#markdown_to_typst(markdown) ⇒ String
Converts Markdown to Typst syntax.
-
#sanitize_html(html, allowed_tags: nil, allowed_attributes: nil) ⇒ String
Sanitizes HTML before conversion to prevent XSS attacks.
-
#url_encode(text) ⇒ String
URL-encodes text for safe use in links.
Instance Method Details
#escape_typst(text) ⇒ String
MARK: - Text Escaping Escapes text for safe use in Typst documents.
Escapes special Typst characters that have syntactic meaning:
#(code/scripting)$(math mode)*(emphasis)_(emphasis)[,](content blocks)\(escape character)<,>(labels and references){`, `}(code blocks)@(references)
62 63 64 65 66 67 68 69 |
# File 'lib/typst_rails/helpers.rb', line 62 def escape_typst(text) return "" if text.nil? raise ArgumentError, "text must be a String" unless text.is_a?(String) # Escape special Typst characters # See: https://typst.app/docs/reference/syntax/ text.gsub(/([#\$*_\[\]\\<>{}@])/, '\\\\\1') end |
#html_to_markdown(html, options = {}) ⇒ String
Converts HTML to Markdown for use in Typst documents.
Typst has excellent support for Markdown syntax, making this a convenient way to include HTML content in Typst documents. The conversion uses the ReverseMarkdown library.
98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/typst_rails/helpers.rb', line 98 def html_to_markdown(html, = {}) return "" if html.nil? raise ArgumentError, "html must be a String" unless html.is_a?(String) raise ArgumentError, "options must be a Hash" unless .is_a?(Hash) begin ReverseMarkdown.convert(html, ) rescue StandardError => e raise Error, "Failed to convert HTML to Markdown: #{e.}" end end |
#html_to_typst(html, options = {}) ⇒ String
Converts HTML to Typst-compatible markup.
This is a convenience method that combines html_to_markdown with markdown_to_typst to convert HTML directly to Typst syntax.
132 133 134 135 |
# File 'lib/typst_rails/helpers.rb', line 132 def html_to_typst(html, = {}) markdown = html_to_markdown(html, ) markdown_to_typst(markdown) end |
#include_markdown(markdown_path) ⇒ String
File path is relative to the current working directory
Reads and includes Markdown content, converting it to Typst syntax.
This method is useful for including external Markdown files in Typst documents. The file is read and converted to Typst syntax.
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/typst_rails/helpers.rb', line 234 def include_markdown(markdown_path) raise ArgumentError, "markdown_path must be a String" unless markdown_path.is_a?(String) raise ArgumentError, "markdown_path cannot be empty" if markdown_path.empty? begin markdown_content = File.read(markdown_path) markdown_to_typst(markdown_content) rescue Errno::ENOENT raise Error, "Markdown file not found: #{markdown_path}" rescue Errno::EACCES raise Error, "Permission denied reading Markdown file: #{markdown_path}" rescue StandardError => e raise Error, "Failed to read Markdown file #{markdown_path}: #{e.}" end end |
#markdown_to_typst(markdown) ⇒ String
Converts Markdown to Typst syntax.
Handles common Markdown patterns and converts them to Typst equivalents:
- Headings (
#→=) - Bold (
**text**→*text*) - Italic (
*text*→_text_) - Links (
[text](url)→#link("url")[text]) - Images (
→#image("url"))
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/typst_rails/helpers.rb', line 169 def markdown_to_typst(markdown) return "" if markdown.nil? raise ArgumentError, "markdown must be a String" unless markdown.is_a?(String) result = markdown.dup # Convert Markdown headers to Typst headers # # Title -> = Title # ## Subtitle -> == Subtitle # etc. result.gsub!(/^(#{Regexp.quote("#")}{1,6})\s+(.+)$/) do "#{"=" * Regexp.last_match(1).length} #{Regexp.last_match(2)}" end # Convert Markdown bold to Typst bold, using placeholder bytes (\x01 text \x02) # so the italic pass below doesn't re-convert the resulting *text* markers. # **text** or __text__ -> *text* result.gsub!(/(\*\*|__)(.+?)\1/, "\x01\\2\x02") # Convert Markdown italic to Typst italic (underscore style) # *text* or _text_ -> _text_ result.gsub!(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/, '_\1_') result.gsub!(/(?<!_)_(?!_)(.+?)(?<!_)_(?!_)/, '_\1_') # Replace bold placeholders with Typst bold markers result.gsub!("\x01", "*") result.gsub!("\x02", "*") # Convert Markdown code to Typst code # `code` -> `code` (same in Typst) # Convert Markdown images (must run before links, since  # would otherwise be matched by the link pattern below) #  -> #image("url") result.gsub!(/!\[([^\]]*)\]\(([^)]+)\)/, '#image("\2")') # Convert Markdown links # [text](url) -> #link("url")[text] result.gsub!(/\[([^\]]+)\]\(([^)]+)\)/, '#link("\2")[\1]') result end |
#sanitize_html(html, allowed_tags: nil, allowed_attributes: nil) ⇒ String
This is basic sanitization. For production use with untrusted HTML, consider using a dedicated sanitization library like Loofah or Sanitize
Sanitizes HTML before conversion to prevent XSS attacks.
This method removes potentially dangerous tags and attributes from HTML before conversion to Typst. It provides basic XSS protection by:
- Removing
<script>and<style>tags - Removing event handler attributes (onclick, onload, etc.)
- Optionally filtering to allowed tags and attributes
288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/typst_rails/helpers.rb', line 288 def sanitize_html(html, allowed_tags: nil, allowed_attributes: nil) return "" if html.nil? raise ArgumentError, "html must be a String" unless html.is_a?(String) ||= DEFAULT_ALLOWED_TAGS allowed_attributes ||= DEFAULT_ALLOWED_ATTRIBUTES fragment = Nokogiri::HTML5.fragment(html) strip_disallowed_nodes(fragment, , allowed_attributes) fragment.to_html end |
#url_encode(text) ⇒ String
URL-encodes text for safe use in links.
Uses CGI.escape to encode special characters for URL safety. Useful when constructing URLs or query parameters in Typst templates.
347 348 349 350 351 352 |
# File 'lib/typst_rails/helpers.rb', line 347 def url_encode(text) return "" if text.nil? raise ArgumentError, "text must be a String" unless text.is_a?(String) CGI.escape(text) end |