Skip to content
Open
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 .devspace.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This is for doing development in a container using devspace
# (https://github.com/gdotdesign/devspace).

image = "crystallang/crystal:1.19.1-alpine"
image = "crystallang/crystal:1.21.0-alpine"
name = "mint"
gui = true

Expand Down
7 changes: 7 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
Comment thread
gdotdesign marked this conversation as resolved.
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
16 changes: 16 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ jobs:
- os: macos-latest
openssl: 3

- os: windows-latest
openssl: default

runs-on: ${{ matrix.os }}

steps:
Expand All @@ -49,6 +52,7 @@ jobs:
uses: rlespinasse/github-slug-action@v5

- name: Set architecture environment variable
shell: bash
run: |
if [ "$RUNNER_ARCH" == "X64" ]; then
echo "ARCH=x86_64" >> $GITHUB_ENV
Expand All @@ -59,6 +63,7 @@ jobs:
fi

- name: Set OpenSSL suffix
shell: bash
run: |
if [ "${{ matrix.openssl }}" == "3" ]; then
echo "OPENSSL_SUFFIX=-openssl3" >> $GITHUB_ENV
Expand Down Expand Up @@ -128,6 +133,17 @@ jobs:
-o build/mint-${GITHUB_REF_SLUG}-osx-${ARCH}${OPENSSL_SUFFIX} \
--no-debug --release

# We are linking statically so the binary can be used on its own,
# otherwise the DLLs it's linked against need to be next to it.
- if: matrix.os == 'windows-latest'
name: Build binary (Windows)
shell: bash
run: |
mkdir build
crystal build src/mint.cr \
-o build/mint-${GITHUB_REF_SLUG}-windows-${ARCH}.exe \
--static --no-debug --release

- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci-base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, macos-15-intel]
os: [ubuntu-latest, macos-latest, macos-15-intel, windows-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 15

Expand Down Expand Up @@ -45,7 +45,7 @@ jobs:
run: shards build mint --error-on-warnings --error-trace

- name: Run CLI specs
run: crystal spec spec_cli/*_spec.cr spec_cli/**/*_spec.cr --error-on-warnings --error-trace
run: crystal spec spec_cli --error-on-warnings --error-trace

- name: Run core specs (Firefox)
working-directory: ./core/tests
Expand Down
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
crystal 1.19.1
crystal 1.21.0
mint 0.20.0
nodejs 20.10.0
yarn 1.22.19
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# We are using crystal as image we are building the binary on
FROM crystallang/crystal:1.19.1-alpine AS build
FROM crystallang/crystal:1.21.0-alpine AS build

# Create a build directory and set it as default
RUN mkdir -p /opt/mint
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ spec:

.PHONY: spec-cli
spec-cli: build
crystal spec spec_cli/*_spec.cr spec_cli/**/*_spec.cr --error-on-warnings --error-trace --progress
crystal spec spec_cli --error-on-warnings --error-trace --progress

.PHONY: format
format:
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
version: "2"
services:
app:
image: crystallang/crystal:1.19.1-alpine
image: crystallang/crystal:1.21.0-alpine
working_dir: /app
volumes:
- .:/app
5 changes: 4 additions & 1 deletion spec/compilers_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ Dir
{Config.new, raw}
end

file_path =
Path[__DIR__, "..", file].normalize.to_s

# Parse the sample
ast = Mint::Parser.parse(sample, File.dirname(__FILE__) + file.lchop("./spec"))
ast = Mint::Parser.parse(sample, file_path)
ast.class.should eq(Mint::Ast)

artifacts =
Expand Down
16 changes: 16 additions & 0 deletions spec/ext/uri_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require "../spec_helper"

describe "URI.file_path" do
it "returns unix file path" do
URI.parse("file://etc/hosts").file_path.should eq("/hosts")
end

it "return unix file path" do
URI.parse("file:///etc/hosts").file_path.should eq("/etc/hosts")
end

it "return windows file path" do
URI.parse("file:///c:/project/readme.md").file_path.should eq("C:\\project\\readme.md")
URI.parse("file:///C%3A/project/readme.md").file_path.should eq("C:\\project\\readme.md")
end
end
5 changes: 3 additions & 2 deletions spec/language_server_spec.cr
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
require "./spec_helper"

def clean_json(workspace : Workspace, path : String)
path.strip.gsub("\#{root_path}", workspace.root_path)
path.strip.gsub("\#{root_path}", workspace.root_path.to_lsp_path)
end

Dir
Expand Down Expand Up @@ -73,7 +73,8 @@ Dir
json.to_json.should contain(expected.to_json)
else
begin
expected_response[0].should eq(actual_response)
JSON.parse(actual_response)
.should eq(JSON.parse(expected_response[0]))
rescue
fail diff(expected_response[0], actual_response)
end
Expand Down
10 changes: 3 additions & 7 deletions spec/mint_json_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,11 @@ Dir
end

it "non existent file" do
# The OS specific error message differs so we only check the beginning.
Mint::MintJson.parse("test.json")
rescue error : Mint::Error
error.to_terminal.to_s.uncolorize.should eq(<<-TEXT)
░ ERROR (MINT_JSON_INVALID) ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░

There was a problem trying to open a mint.json file: test.json

Error opening file with mode 'r': 'test.json': No such file or directory
TEXT
error.to_terminal.to_s.uncolorize.should contain(
"There was a problem trying to open a mint.json file: test.json")
end

it "no mint.json in directory or parents" do
Expand Down
3 changes: 3 additions & 0 deletions spec/static_documentation_generator_spec.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# We don't test this on windows because there is no `xmllint`.
{% skip_file if flag?(:windows) %}

require "./spec_helper"

Dir
Expand Down
4 changes: 2 additions & 2 deletions spec/watcher_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe Mint::Watcher do
watcher =
Mint::Watcher
.new { |items| modified = items }
.tap(&.patterns = ["#{directory}/**/*"])
.tap(&.patterns = ["#{directory.to_posix}/**/*"])

# Returns all files
modified.should eq([file1, file2])
Expand All @@ -37,7 +37,7 @@ describe Mint::Watcher do
modified.should eq([file2])

# Returns all files
watcher.patterns = ["#{directory}/**/*"]
watcher.patterns = ["#{directory.to_posix}/**/*"]
watcher.scan(:modified)
modified.should eq([file1])
ensure
Expand Down
11 changes: 5 additions & 6 deletions spec_cli/build_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ context "build" do
end

it "displays help with '--help' flag" do
expect_output ["build", "--help"], <<-TEXT
expect_output %w[build --help], <<-TEXT
Usage:
×××× build [flags...] [arg...]

Expand All @@ -36,7 +36,7 @@ context "build" do
end

it "builds the project" do
expect_output ["build"], <<-TEXT
expect_output %w[build --skip-icons], <<-TEXT
Mint - Building for production
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙ Clearing the "dist" directory... ××××
Expand All @@ -50,7 +50,7 @@ context "build" do
end

it "shows timings with the `--timings` flag" do
expect_output ["build", "--timings"], <<-TEXT
expect_output %w[build --timings --skip-icons], <<-TEXT
Mint - Building for production
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙ Clearing the "dist" directory... ××××
Expand All @@ -66,7 +66,6 @@ context "build" do
Calculating dependencies for bundles... | ××××
Bundling and generating JavaScript... | ××××
Generating index.html | ××××
Generating icons | ××××
Copying assets | ××××
Generating index.css | ××××
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Expand All @@ -75,7 +74,7 @@ context "build" do
end

it "generates manifeset with the `--generate-manifest` flag" do
expect_output ["build", "--generate-manifest"], <<-TEXT
expect_output %w[build --generate-manifest --skip-icons], <<-TEXT
Mint - Building for production
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙ Clearing the "dist" directory... ××××
Expand All @@ -91,7 +90,7 @@ context "build" do
end

it "logs the files using the `--verbose` flag" do
expect_output ["build", "--verbose"], <<-TEXT
expect_output %w[build --verbose --skip-icons], <<-TEXT
Mint - Building for production
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚙ Clearing the "dist" directory... ××××
Expand Down
26 changes: 26 additions & 0 deletions spec_cli/spec_helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ def run(args : Array(String), input : String = "", clear_env = true)
path =
Path[__DIR__, "..", "bin", "mint"].normalize.to_s

# On Windows the binary needs `PATH` to find the DLLs it is linked against,
# without them it exits before `main` runs (no output, no exit code).
{% if flag?(:windows) %}
clear_env = false
{% end %}

status =
Process.run(
clear_env: clear_env,
Expand All @@ -26,6 +32,26 @@ def run(args : Array(String), input : String = "", clear_env = true)
"NO_COLOR" => "1",
})

# A command is allowed to fail (that's what some of the specs check) but it
# must not crash, otherwise the specs fail in confusing ways later on.
unless status.normal_exit?
raise <<-TEXT
COMMAND CRASHED!

COMMAND:
#{path} #{args.join(' ')}

EXIT:
#{status.exit_reason}

OUTPUT:
#{output.rewind.gets_to_end}

ERROR:
#{error.rewind.gets_to_end}
TEXT
end

{
output.rewind.gets_to_end,
error.rewind.gets_to_end,
Expand Down
4 changes: 4 additions & 0 deletions src/ast/directives/file_based.cr
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ module Mint
File.relative_path_from_ancestor(path, "mint.json")
end

getter relative_path_posix : String do
Path[relative_path].to_posix.to_s
end

# The real path of the asset on the disk.
getter real_path : Path do
if path.starts_with?("/")
Expand Down
5 changes: 3 additions & 2 deletions src/bundler.cr
Original file line number Diff line number Diff line change
Expand Up @@ -441,8 +441,9 @@ module Mint

def generate_icons?
!config.skip_icons &&
Process.find_executable("convert") &&
File.exists?(json.application.icon)
!json.application.icon.blank? &&
!IconGenerator.executable.nil? &&
File.exists?(File.join(File.dirname(json.path), json.application.icon))
end

def generate_icons
Expand Down
2 changes: 1 addition & 1 deletion src/compilers/dbg.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Mint
end
else
location =
js.string("#{node.file.relative_path}:#{node.from.line}:#{node.from.column}")
js.string("#{node.file.relative_path_posix}:#{node.from.line}:#{node.from.column}")

var =
[Variable.new] of Item
Expand Down
2 changes: 1 addition & 1 deletion src/compilers/suite.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Mint
Raw.new({
start: {node.from.line, node.from.column},
end: {node.to.line, node.to.column},
filename: node.file.relative_path,
filename: node.file.relative_path_posix,
}.to_json),
]

Expand Down
2 changes: 1 addition & 1 deletion src/compilers/test.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module Mint
Raw.new({
start: {node.from.line, node.from.column},
end: {node.to.line, node.to.column},
filename: node.file.relative_path,
filename: node.file.relative_path_posix,
}.to_json),
]

Expand Down
2 changes: 1 addition & 1 deletion src/ext/file.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class File
root = File.dirname(base)

loop do
return if root == "." || root == "/"
return if root.in?(".", "/", Path[root].anchor.to_s)

# ameba:disable Lint/AssignmentInCallArgument
if File.exists?(path = Path[root, name])
Expand Down
8 changes: 8 additions & 0 deletions src/ext/string.cr
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ class String
lines.join('\n', &.rstrip)
end

def to_lsp_path
if matches_full?(/([A-Z]):\\(.*)/i)
"/#{gsub('\\', '/')}"
else
self
end
end

def shrink_to_minimum_leading_whitespace : String
# We start from the maximum number for indent size
indent_size =
Expand Down
15 changes: 15 additions & 0 deletions src/ext/uri.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class URI
# Returns proper file path on Windows and Unix
def file_path : String
raise "Not a file path!" unless scheme == "file"

path =
URI.decode(self.path.lchop("/"))

if match = path.match_full(/([A-Z]):\/(.*)/i)
"#{match[1].upcase}:\\#{match[2].gsub('/', '\\')}"
else
self.path
end
end
end
2 changes: 1 addition & 1 deletion src/ls/code_actions/module_actions.cr
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Mint
node.functions.sort_by(&.name.value))
.each_with_index { |entity, index| entity.from = order[index] }

case formatted = workspace.format(URI.parse(uri).path.to_s)
case formatted = workspace.format(URI.parse(uri).file_path)
in String
LSP::CodeAction.new(
title: "Order Entities",
Expand Down
Loading