Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow referencing assets from the root of the project. #707

Merged
merged 2 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spec/compilers/dbg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { inspect as A } from "./runtime.js";
export const B = () => {
return (() => {
const a = `Hello World!`;
console.log(`./spec/compilers/dbg:3:4`);
console.log(`compilers/dbg:3:4`);
console.log(A(a));
return a
})()
Expand Down
2 changes: 1 addition & 1 deletion spec/compilers/dbg_as_function
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { inspect as A } from "./runtime.js";

export const B = () => {
return (a) => {
console.log(`./spec/compilers/dbg_as_function:3:22`);
console.log(`compilers/dbg_as_function:3:22`);
console.log(A(a));
return a
}(`Hello World!`)
Expand Down
2 changes: 1 addition & 1 deletion spec/compilers/dbg_bang
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ component Main {
export const A = () => {
return (() => {
const a = `Hello World!`;
console.log(`./spec/compilers/dbg_bang:3:4`);
console.log(`compilers/dbg_bang:3:4`);
console.log(a);
return a
})()
Expand Down
15 changes: 15 additions & 0 deletions spec/compilers/directives/asset-absolute
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
component Main {
fun render : String {
@asset(/fixtures/icon.svg)
}
}
--------------------------------------------------------------------------------
---=== /__mint__/index.js ===---
export const A = () => {
return `/__mint__/icon_c97b81630bc53286dadc8996727d348e.svg`
};

---=== /__mint__/icon_c97b81630bc53286dadc8996727d348e.svg ===---
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z"/>
</svg>
67 changes: 67 additions & 0 deletions spec/compilers/directives/highlight-file-absolute
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
component Main {
fun render : Html {
@highlight-file(/fixtures/Test.mint)
}
}
--------------------------------------------------------------------------------
import {
createElement as A,
fragment as B
} from "./runtime.js";

export const C = () => {
return A(B, {}, [
A("span", {
className: "line"
}, [
A("span", {
className: "keyword"
}, [`component`]),
` `,
A("span", {
className: "type"
}, [`Main`]),
` {
`
]),
A("span", {
className: "line"
}, [
` `,
A("span", {
className: "keyword"
}, [`fun`]),
` render : `,
A("span", {
className: "type"
}, [`Html`]),
` {
`
]),
A("span", {
className: "line"
}, [
` <`,
A("span", {
className: "namespace"
}, [`div`]),
`></`,
A("span", {
className: "namespace"
}, [`div`]),
`>
`
]),
A("span", {
className: "line"
}, [` }
`]),
A("span", {
className: "line"
}, [`}
`]),
A("span", {
className: "line"
}, [``])
])
};
10 changes: 10 additions & 0 deletions spec/compilers/directives/inline-absolute
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
component Main {
fun render : String {
@inline(/fixtures/data.txt)
}
}
--------------------------------------------------------------------------------
export const A = () => {
return `Hello World!
`
};
20 changes: 20 additions & 0 deletions spec/compilers/directives/svg-absolute
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
component Main {
fun render : Html {
@svg(/fixtures/icon.svg)
}
}
--------------------------------------------------------------------------------
import { createElement as A } from "./runtime.js";

export const
a = A(`svg`, {
dangerouslySetInnerHTML: {
__html: `<path d="M24 10h-10v-10h-4v10h-10v4h10v10h4v-10h10z"/>`
},
viewBox: `0 0 24 24`,
height: `24`,
width: `24`
}),
B = () => {
return a
};
2 changes: 1 addition & 1 deletion spec/compilers_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Dir
sample, expected = File.read(file).split("-" * 80)

# Parse the sample
ast = Mint::Parser.parse(sample, file)
ast = Mint::Parser.parse(sample, File.dirname(__FILE__) + file.lchop("./spec"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of chopping off the ./spec from the filepath?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

File.dirname(__FILE__) is the spec directory, so we need to remove that from the test file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And what's wrong with that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would not find the assets defined in specs.

/path/to/spec/.spec/test-file where /path/to/spec/.spec is not a file or a directory.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't because you've added a mint.json file to the spec/ folder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the spec folder becomes the root folder / for the tests. So for example /fixtures/data.txt is reachable so as ../../fixtures/data.txt from spec/compilers/directives/inline test.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And why don't you reference the files from the root folder instead? Unless I'm mistaken this way it wouldn't need any hacks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't follow. We would still need to chop ./spec off. It doesn't matter if it's absolute or relative. And we still need to find the closest mint.json to figure out the root folder.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps I don't fully grok the situation. I'm gonna approve it and come back to it later, once I familiarize myself with the recent changes - and there's a lot of 'em 😅

ast.class.should eq(Mint::Ast)

artifacts =
Expand Down
3 changes: 3 additions & 0 deletions spec/mint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "ROOT FOR TESTS"
}
1 change: 0 additions & 1 deletion spec/spec_helper.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require "spec"

ENV["SPEC"] = "TRUE"
MINT_ENV["TEST"] = "TRUE"

require "./spec_helpers"
Expand Down
18 changes: 14 additions & 4 deletions src/ast/directives/file_based.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,29 @@ module Mint
class FileBased < Node
include Errorable

# The real path of the asset on the disk.
getter real_path : Path

# The given path of the asset, relative to the source file.
getter path : String

# The relative path of the asset to the project root (closest `mint.json`).
getter relative_path : String do
File.relative_path_from_ancestor(path, "mint.json")
end

# The real path of the asset on the disk.
getter real_path : Path do
if path.starts_with?("/")
if json = File.find_in_ancestors(file.path, "mint.json")
Path[json].sibling(path.lchop('/')).expand
end
end || Path[file.path].sibling(path).expand
end

def initialize(
@from : Parser::Location,
@to : Parser::Location,
@file : Parser::File,
@path : String
)
@real_path = Path[file.path].sibling(path).expand
end

# Returns the hashed filename of the target. For the build version it
Expand Down
2 changes: 1 addition & 1 deletion src/compilers/dbg.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module Mint
def compile(node : Ast::Dbg) : Compiled
compile node do
location =
js.string("#{node.file.path}:#{node.from.line}:#{node.from.column}")
js.string("#{node.file.relative_path}:#{node.from.line}:#{node.from.column}")

var =
[Variable.new] of Item
Expand Down
5 changes: 5 additions & 0 deletions src/ext/file.cr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ class File
File.write path, contents
end

def self.relative_path_from_ancestor(path : String, name : String) : String
return path unless directory = File.find_in_ancestors(path, name)
Path[path].relative_to(File.dirname(directory)).to_s
end

def self.find_in_ancestors(base : String, name : String) : String?
root = File.dirname(base)

Expand Down
5 changes: 5 additions & 0 deletions src/parser/file.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ module Mint
class File
getter contents, path

# The relative path of the file to the project root (closest `mint.json`).
getter relative_path : String do
::File.relative_path_from_ancestor(path, "mint.json")
end

def initialize(@contents : String, @path : String)
end

Expand Down
9 changes: 1 addition & 8 deletions src/type_checkers/directives/asset.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ module Mint
class TypeChecker
def check(node : Ast::Directives::Asset) : Checkable
error! :asset_directive_expected_file do
block "The path specified for an asset directive does not exist: "

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

snippet "The path specified for an asset directive does not exist:", node.relative_path
snippet "The asset directive in question is here:", node
end unless node.exists?

Expand Down
9 changes: 1 addition & 8 deletions src/type_checkers/directives/highlight_file.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ 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 path specified for an highlight file directive does not exist:", node.relative_path
snippet "The highlight file directive in question is here:", node
end unless node.exists?

Expand Down
9 changes: 1 addition & 8 deletions src/type_checkers/directives/inline.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ module Mint
class TypeChecker
def check(node : Ast::Directives::Inline) : Checkable
error! :inline_directive_expected_file do
block "The path specified for an inline directive does not exist:"

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

snippet "The path specified for an inline directive does not exist:", node.relative_path
snippet "The inline directive in question is here:", node
end unless node.exists?

Expand Down
9 changes: 1 addition & 8 deletions src/type_checkers/directives/svg.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ module Mint
class TypeChecker
def check(node : Ast::Directives::Svg) : Checkable
error! :svg_directive_expected_file do
path =
if ENV["SPEC"]?
node.path.to_s
else
node.real_path.to_s
end

snippet "The specified file for an svg directive does not exist:", path
snippet "The specified file for an svg directive does not exist:", node.relative_path
snippet "The svg directive in question is here:", node
end unless node.exists?

Expand Down