Skip to content

Commit

Permalink
Implement @highlight-file directive. (#674)
Browse files Browse the repository at this point in the history
  • Loading branch information
gdotdesign committed Sep 23, 2023
1 parent db82722 commit fef27ee
Show file tree
Hide file tree
Showing 11 changed files with 184 additions and 1 deletion.
29 changes: 29 additions & 0 deletions spec/compilers/directives/highlight-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
component Main {
fun render : Html {
@highlight-file(../../fixtures/Test.mint)
}
}
--------------------------------------------------------------------------------
class A extends _C {
render() {
return _h(React.Fragment, {}, [_h('span', { className: 'keyword' }, [`component`]),
` `,
_h('span', { className: 'type' }, [`Main`]),
` {
`,
_h('span', { className: 'keyword' }, [`fun`]),
` render : `,
_h('span', { className: 'type' }, [`Html`]),
` {
<`,
_h('span', { className: 'namespace' }, [`div`]),
`></`,
_h('span', { className: 'namespace' }, [`div`]),
`>
}
}
`]);
}
};

A.displayName = "Main";
30 changes: 30 additions & 0 deletions spec/examples/directives/highlight_file
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
--------------------------highlight_file_directive_expected_opening_parenthesis
component Main {
fun render : String {
@highlight-file
-----------------------------------------highlight_file_directive_expected_path
component Main {
fun render : String {
@highlight-file(
--------------------------highlight_file_directive_expected_closing_parenthesis
component Main {
fun render : String {
@highlight-file(path
-----------------------------------------highlight_file_directive_expected_file
component Main {
fun render : Html {
@highlight-file(File.mint)
}
}
-----------------------------------------highlight_file_directive_expected_mint
component Main {
fun render : Html {
@highlight-file(../../fixtures/icon-not-svg)
}
}
-------------------------------------------------------------------------------
component Main {
fun render : Html {
@highlight-file(../../../core/source/Array.mint)
}
}
5 changes: 5 additions & 0 deletions spec/fixtures/Test.mint
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
component Main {
fun render : Html {
<div></div>
}
}
11 changes: 11 additions & 0 deletions spec/formatters/directives/highlight-file
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
component Main {
fun render : Html {
@highlight-file(../../fixtures/Test.mint)
}
}
--------------------------------------------------------------------------------
component Main {
fun render : Html {
@highlight-file(../../fixtures/Test.mint)
}
}
3 changes: 3 additions & 0 deletions src/ast/directives/file_based.cr
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ module Mint

class Svg < FileBased
end

class HighlightFile < FileBased
end
end
end
end
26 changes: 26 additions & 0 deletions src/compilers/directives/highlight_file.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module Mint
class Compiler
def _compile(node : Ast::Directives::HighlightFile) : String
contents =
File.read(node.real_path)

parser = Parser.new(contents, node.real_path.to_s)
parser.parse

parts =
SemanticTokenizer.tokenize(parser.ast)

mapped =
parts.map do |item|
case item
in String
"`#{skip { escape_for_javascript(item) }}`"
in Tuple(SemanticTokenizer::TokenType, String)
"_h('span', { className: '#{item[0].to_s.underscore}' }, [`#{skip { escape_for_javascript(item[1]) }}`])"
end
end

"_h(React.Fragment, {}, [#{mapped.join(",\n")}])"
end
end
end
7 changes: 7 additions & 0 deletions src/formatters/directives/highlight_file.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module Mint
class Formatter
def format(node : Ast::Directives::HighlightFile)
"@highlight-file(#{node.path})"
end
end
end
3 changes: 2 additions & 1 deletion src/parsers/base_expression.cr
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ module Mint
when '`'
js
when '@'
documentation_directive ||
highlight_file_directive ||
documentation_directive ||
highlight_directive ||
format_directive ||
inline_directive ||
Expand Down
33 changes: 33 additions & 0 deletions src/parsers/directives/highlight_file.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Mint
class Parser
def highlight_file_directive : Ast::Directives::HighlightFile?
parse do |start_position|
next unless word! "@highlight-file"
whitespace

next error :highlight_file_directive_expected_opening_parenthesis do
expected "the opening parenthesis of an highlight file directive", word
snippet self
end unless char! '('
whitespace

next error :highlight_file_directive_expected_path do
expected "the path (to the file) of an highlight file directive", word
snippet self
end unless path = gather { chars { char != ')' } }.presence.try(&.strip)
whitespace

next error :highlight_file_directive_expected_closing_parenthesis do
expected "the closing parenthesis of an highlight file directive", word
snippet self
end unless char! ')'

Ast::Directives::HighlightFile.new(
from: start_position,
to: position,
file: file,
path: path)
end
end
end
end
1 change: 1 addition & 0 deletions src/scope.cr
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ module Mint

case node
when Ast::Directives::Documentation,
Ast::Directives::HighlightFile,
Ast::Directives::Highlight,
Ast::Directives::Inline,
Ast::Directives::Asset,
Expand Down
37 changes: 37 additions & 0 deletions src/type_checkers/directives/highlight_file.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module Mint
class TypeChecker
def check(node : Ast::Directives::HighlightFile) : Checkable
error! :highlight_file_directive_expected_file do
block "The path specified for an highlight file directive does not exist: "

if ENV["SPEC"]?
snippet node.path.to_s
else
snippet node.real_path.to_s
end

snippet "The highlight file directive in question is here:", node
end unless node.exists?

contents =
File.read(node.real_path)

parser = Parser.new(contents, node.real_path.to_s)
parser.parse
parser.eof!

error! :highlight_file_directive_expected_mint do
block "I was expecting a Mint file for a highlight file directive " \
"but I could not parse it."

snippet(
"These are the first few lines of the file:",
contents.lines[0..4].join("\n"))

snippet "The highlight file directive in question is here:", node
end unless parser.errors.empty?

HTML
end
end
end

0 comments on commit fef27ee

Please sign in to comment.