mirror of
https://github.com/ralsina/tartrazine.git
synced 2025-07-01 12:27:08 -03:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
4432da2893 | |||
6a6827f26a | |||
766f9b4708 | |||
9d49ff78d6 | |||
fb924543a0 |
12
CHANGELOG.md
12
CHANGELOG.md
@ -2,6 +2,18 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.9.0] - 2024-09-21
|
||||
|
||||
### 🚀 Features
|
||||
|
||||
- PNG writer based on Stumpy libs
|
||||
|
||||
### ⚙️ Miscellaneous Tasks
|
||||
|
||||
- Clean
|
||||
- Detect version bump in release script
|
||||
- Improve changelog handling
|
||||
|
||||
## [0.8.0] - 2024-09-21
|
||||
|
||||
### 🚀 Features
|
||||
|
@ -113,3 +113,11 @@ tasks:
|
||||
kcov --clean --include-path=./src ${PWD}/coverage ./bin/run_tests
|
||||
outputs:
|
||||
- coverage/index.html
|
||||
|
||||
loc:
|
||||
phony: true
|
||||
always_run: true
|
||||
dependencies:
|
||||
- src
|
||||
commands: |
|
||||
tokei src -e src/constants/
|
||||
|
@ -67,7 +67,6 @@ commit_parsers = [
|
||||
{ message = "^chore\\(deps.*\\)", skip = true },
|
||||
{ message = "^chore\\(pr\\)", skip = true },
|
||||
{ message = "^chore\\(pull\\)", skip = true },
|
||||
{ message = "^chore\\(ignore\\)", skip = true },
|
||||
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
|
||||
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
|
||||
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
|
||||
|
@ -2,12 +2,12 @@
|
||||
set e
|
||||
|
||||
PKGNAME=$(basename "$PWD")
|
||||
VERSION=$(git cliff --bumped-version |cut -dv -f2)
|
||||
VERSION=$(git cliff --bumped-version --unreleased |cut -dv -f2)
|
||||
|
||||
sed "s/^version:.*$/version: $VERSION/g" -i shard.yml
|
||||
git add shard.yml
|
||||
hace lint test
|
||||
git cliff --bump -o
|
||||
git cliff --bump -u -p CHANGELOG.md
|
||||
git commit -a -m "bump: Release v$VERSION"
|
||||
git tag "v$VERSION"
|
||||
git push --tags
|
||||
|
BIN
fonts/courier-bold-oblique.pcf.gz
Normal file
BIN
fonts/courier-bold-oblique.pcf.gz
Normal file
Binary file not shown.
BIN
fonts/courier-bold.pcf.gz
Normal file
BIN
fonts/courier-bold.pcf.gz
Normal file
Binary file not shown.
BIN
fonts/courier-oblique.pcf.gz
Normal file
BIN
fonts/courier-oblique.pcf.gz
Normal file
Binary file not shown.
BIN
fonts/courier-regular.pcf.gz
Normal file
BIN
fonts/courier-regular.pcf.gz
Normal file
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
name: tartrazine
|
||||
version: 0.8.0
|
||||
version: 0.9.0
|
||||
|
||||
authors:
|
||||
- Roberto Alsina <roberto.alsina@gmail.com>
|
||||
@ -18,6 +18,10 @@ dependencies:
|
||||
github: ralsina/sixteen
|
||||
docopt:
|
||||
github: chenkovsky/docopt.cr
|
||||
stumpy_utils:
|
||||
github: stumpycr/stumpy_utils
|
||||
stumpy_png:
|
||||
github: stumpycr/stumpy_png
|
||||
|
||||
crystal: ">= 1.13.0"
|
||||
|
||||
|
113
src/formatters/png.cr
Normal file
113
src/formatters/png.cr
Normal file
@ -0,0 +1,113 @@
|
||||
require "../formatter"
|
||||
require "stumpy_png"
|
||||
require "stumpy_utils"
|
||||
require "compress/gzip"
|
||||
|
||||
module Tartrazine
|
||||
def self.to_png(text : String, language : String,
|
||||
theme : String = "default-dark",
|
||||
line_numbers : Bool = false) : String
|
||||
Tartrazine::Png.new(
|
||||
theme: Tartrazine.theme(theme),
|
||||
line_numbers: line_numbers
|
||||
).format(text, Tartrazine.lexer(name: language))
|
||||
end
|
||||
|
||||
class FontFiles
|
||||
extend BakedFileSystem
|
||||
bake_folder "../../fonts", __DIR__
|
||||
end
|
||||
|
||||
class Png < Formatter
|
||||
include StumpyPNG
|
||||
property? line_numbers : Bool = false
|
||||
@font_regular : PCFParser::Font
|
||||
@font_bold : PCFParser::Font
|
||||
@font_oblique : PCFParser::Font
|
||||
@font_bold_oblique : PCFParser::Font
|
||||
@font_width = 15
|
||||
@font_height = 24
|
||||
|
||||
def initialize(@theme : Theme = Tartrazine.theme("default-dark"), @line_numbers : Bool = false)
|
||||
@font_regular = load_font("/courier-regular.pcf.gz")
|
||||
@font_bold = load_font("/courier-bold.pcf.gz")
|
||||
@font_oblique = load_font("/courier-oblique.pcf.gz")
|
||||
@font_bold_oblique = load_font("/courier-bold-oblique.pcf.gz")
|
||||
end
|
||||
|
||||
private def load_font(name : String) : PCFParser::Font
|
||||
compressed = FontFiles.get(name)
|
||||
uncompressed = Compress::Gzip::Reader.open(compressed) do |gzip|
|
||||
gzip.gets_to_end
|
||||
end
|
||||
PCFParser::Font.new(IO::Memory.new uncompressed)
|
||||
end
|
||||
|
||||
private def line_label(i : Int32) : String
|
||||
"#{i + 1}".rjust(4).ljust(5)
|
||||
end
|
||||
|
||||
def format(text : String, lexer : BaseLexer, outp : IO) : Nil
|
||||
# Create canvas of correct size
|
||||
lines = text.split("\n")
|
||||
canvas_height = lines.size * @font_height
|
||||
canvas_width = lines.max_of(&.size)
|
||||
canvas_width += 5 if line_numbers?
|
||||
canvas_width *= @font_width
|
||||
|
||||
bg_color = RGBA.from_hex("##{theme.styles["Background"].background.try &.hex}")
|
||||
canvas = Canvas.new(canvas_width, canvas_height, bg_color)
|
||||
|
||||
tokenizer = lexer.tokenizer(text)
|
||||
x = 0
|
||||
y = @font_height
|
||||
i = 0
|
||||
if line_numbers?
|
||||
canvas.text(x, y, line_label(i), @font_regular, RGBA.from_hex("##{theme.styles["Background"].color.try &.hex}"))
|
||||
x += 5 * @font_width
|
||||
end
|
||||
|
||||
tokenizer.each do |token|
|
||||
font, color = token_style(token[:type])
|
||||
# These fonts are very limited
|
||||
t = token[:value].gsub(/[^[:ascii:]]/, "?")
|
||||
canvas.text(x, y, t.rstrip("\n"), font, color)
|
||||
if token[:value].includes?("\n")
|
||||
x = 0
|
||||
y += @font_height
|
||||
i += 1
|
||||
if line_numbers?
|
||||
canvas.text(x, y, line_label(i), @font_regular, RGBA.from_hex("##{theme.styles["Background"].color.try &.hex}"))
|
||||
x += 4 * @font_width
|
||||
end
|
||||
end
|
||||
|
||||
x += token[:value].size * @font_width
|
||||
end
|
||||
|
||||
StumpyPNG.write(canvas, outp)
|
||||
end
|
||||
|
||||
def token_style(token : String) : {PCFParser::Font, RGBA}
|
||||
if theme.styles.has_key?(token)
|
||||
s = theme.styles[token]
|
||||
else
|
||||
# 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.
|
||||
s = theme.styles[theme.style_parents(token).reverse.find { |parent|
|
||||
theme.styles.has_key?(parent)
|
||||
}]
|
||||
end
|
||||
|
||||
color = RGBA.from_hex("##{theme.styles["Background"].color.try &.hex}")
|
||||
color = RGBA.from_hex("##{s.color.try &.hex}") if s.color
|
||||
|
||||
return {@font_bold_oblique, color} if s.bold && s.italic
|
||||
return {@font_bold, color} if s.bold
|
||||
return {@font_oblique, color} if s.italic
|
||||
return {@font_regular, color}
|
||||
end
|
||||
end
|
||||
end
|
10
src/main.cr
10
src/main.cr
@ -4,6 +4,10 @@ require "./tartrazine"
|
||||
HELP = <<-HELP
|
||||
tartrazine: a syntax highlighting tool
|
||||
|
||||
You can use the CLI to generate HTML, terminal, JSON or SVG output
|
||||
from a source file using different themes.
|
||||
Keep in mind that not all formatters support all features.
|
||||
|
||||
Usage:
|
||||
tartrazine (-h, --help)
|
||||
tartrazine FILE -f html [-t theme][--standalone][--line-numbers]
|
||||
@ -13,6 +17,8 @@ Usage:
|
||||
[-o output]
|
||||
tartrazine FILE -f svg [-t theme][--standalone][--line-numbers]
|
||||
[-l lexer][-o output]
|
||||
tartrazine FILE -f png [-t theme][--line-numbers]
|
||||
[-l lexer][-o output]
|
||||
tartrazine FILE -f json [-o output]
|
||||
tartrazine --list-themes
|
||||
tartrazine --list-lexers
|
||||
@ -78,6 +84,10 @@ if options["-f"]
|
||||
formatter.standalone = options["--standalone"] != nil
|
||||
formatter.line_numbers = options["--line-numbers"] != nil
|
||||
formatter.theme = theme
|
||||
when "png"
|
||||
formatter = Tartrazine::Png.new
|
||||
formatter.line_numbers = options["--line-numbers"] != nil
|
||||
formatter.theme = theme
|
||||
else
|
||||
puts "Invalid formatter: #{formatter}"
|
||||
exit 1
|
||||
|
Reference in New Issue
Block a user