yamd/lib/yamd/code.rb
2025-03-20 21:03:29 +04:00

60 lines
1.7 KiB
Ruby

# YAMD
# Copyright (C) 2025 kp2pml30
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
require 'erb'
module YAMD::Code
HIGHLIGHTS = {
/\b(?:[A-Z][a-zA-Z\-_0-9]*)\b*/ => 'type',
/#(\s|$)[^\n]*/ => 'comment',
/\b(?:open|final|class|fn|let|var|if|else|while|loop|return|namespace|new)\b/ => 'kw',
/\b(?:null|undefined|true|false|this|self)\b/i => 'const',
/[:,;()\[\]{}<>]/ => 'punct',
/0|(0x[0-9a-fA-F]+)|([1-9][0-9]*(\.[0-9]+)?)/ => 'number',
/"(?:\\.|[^\\"])*"/ => 'str',
/'(?:\\.|[^\\'])*'/ => 'str',
}
def self.highlight(txt, highlights=HIGHLIGHTS)
idx = 0
res = String.new
old_idx = 0
flush = Proc.new {
next if old_idx == idx
res << ERB::Util.html_escape(txt[old_idx...idx])
old_idx = idx
}
while idx < txt.size
pattern = nil
highlights.each { |pat, klass|
match = pat.match txt, idx
next if not match
next if match.offset(0)[0] != idx
pattern = pat
flush.()
res << "<span class=\"highlight-#{klass}\">" << ERB::Util.html_escape(match[0]) << "</span>"
idx += match[0].size
old_idx = idx
break
}
if pattern.nil?
idx += 1
end
end
flush.()
res.freeze
end
end