From fd5af6ba3b1caf40a8497a06ce3678ae27087379 Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Fri, 9 Aug 2024 11:57:23 -0300 Subject: [PATCH] Starting to add options to HTML formatter: standalone --- src/formatters/html.cr | 137 +++++++++++++++++++++++++---------------- src/main.cr | 4 +- 2 files changed, 87 insertions(+), 54 deletions(-) diff --git a/src/formatters/html.cr b/src/formatters/html.cr index 6110f36..3f3510e 100644 --- a/src/formatters/html.cr +++ b/src/formatters/html.cr @@ -1,59 +1,90 @@ require "../formatter" module Tartrazine - class Html < Formatter - def format(text : String, lexer : Lexer, theme : Theme) : String - output = String.build do |outp| - outp << "" - outp << "
"
-            lexer.tokenize(text).each do |token|
-              fragment = "#{token[:value]}"
-              outp << fragment
-            end
-            outp << "
" - end - output + class Html < Formatter + # Not all of these options are implemented + + property? standalone : Bool = false + + # property class_prefix : String = "" + # property with_classes : Bool = true + # property tab_width = 8 + # property surrounding_pre : Bool = true + # property wrap_long_lines : Bool = false + # property line_numbers : Bool = false + # property line_number_in_table : Bool = false + # property linkable_line_numbers : Bool = false + # property highlight_lines : Array(Range(Int32, Int32)) = [] of Range(Int32, Int32) + # property base_line_number : Int32 = 1 + + def format(text : String, lexer : Lexer, theme : Theme) : String + text = format_text(text, lexer, theme) + if standalone? + text = wrap_standalone(text, theme) + end + text + end + + # Wrap text into a full HTML document, including the CSS for the theme + def wrap_standalone(text, theme) : String + output = String.build do |outp| + outp << "" + outp << text + outp << "" + end + output + end + + def format_text(text : String, lexer : Lexer, theme : Theme) : String + output = String.build do |outp| + outp << "
"
+        lexer.tokenize(text).each do |token|
+          fragment = "#{token[:value]}"
+          outp << fragment
         end
-    
-        # ameba:disable Metrics/CyclomaticComplexity
-        def get_style_defs(theme : Theme) : String
-          output = String.build do |outp|
-            theme.styles.each do |token, style|
-              outp << ".#{get_css_class(token, theme)} {"
-              # These are set or nil
-              outp << "color: #{style.color.try &.hex};" if style.color
-              outp << "background-color: #{style.background.try &.hex};" if style.background
-              outp << "border: 1px solid #{style.border.try &.hex};" if style.border
-    
-              # These are true/false/nil
-              outp << "border: none;" if style.border == false
-              outp << "font-weight: bold;" if style.bold
-              outp << "font-weight: 400;" if style.bold == false
-              outp << "font-style: italic;" if style.italic
-              outp << "font-style: normal;" if style.italic == false
-              outp << "text-decoration: underline;" if style.underline
-              outp << "text-decoration: none;" if style.underline == false
-    
-              outp << "}"
-            end
-          end
-          output
-        end
-    
-        # Given a token type, return the CSS class to use.
-        def get_css_class(token, theme)
-          return Abbreviations[token] if theme.styles.has_key?(token)
-    
-          # Themes don't contain information for each specific
-          # token type. However, they may contain information
-          # for a parent style. Worst case, we go to the root
-          # (Background) style.
-          Abbreviations[theme.style_parents(token).reverse.find { |parent|
-            theme.styles.has_key?(parent)
-          }]
+        outp << "
" + end + output + end + + # ameba:disable Metrics/CyclomaticComplexity + def get_style_defs(theme : Theme) : String + output = String.build do |outp| + theme.styles.each do |token, style| + outp << ".#{get_css_class(token, theme)} {" + # These are set or nil + outp << "color: ##{style.color.try &.hex};" if style.color + outp << "background-color: ##{style.background.try &.hex};" if style.background + outp << "border: 1px solid ##{style.border.try &.hex};" if style.border + + # These are true/false/nil + outp << "border: none;" if style.border == false + outp << "font-weight: bold;" if style.bold + outp << "font-weight: 400;" if style.bold == false + outp << "font-style: italic;" if style.italic + outp << "font-style: normal;" if style.italic == false + outp << "text-decoration: underline;" if style.underline + outp << "text-decoration: none;" if style.underline == false + + outp << "}" end end - -end \ No newline at end of file + output + end + + # Given a token type, return the CSS class to use. + def get_css_class(token, theme) + return Abbreviations[token] if theme.styles.has_key?(token) + + # Themes don't contain information for each specific + # token type. However, they may contain information + # for a parent style. Worst case, we go to the root + # (Background) style. + Abbreviations[theme.style_parents(token).reverse.find { |parent| + theme.styles.has_key?(parent) + }] + end + end +end diff --git a/src/main.cr b/src/main.cr index 99cf49e..9fd7c5d 100644 --- a/src/main.cr +++ b/src/main.cr @@ -2,4 +2,6 @@ require "./**" lexer = Tartrazine.lexer("crystal") theme = Tartrazine.theme(ARGV[1]) -puts Tartrazine::Html.new.format(File.read(ARGV[0]), lexer, theme) +formatter = Tartrazine::Html.new +formatter.standalone = true +puts formatter.format(File.read(ARGV[0]), lexer, theme)