Skip to content
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
32 changes: 32 additions & 0 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Ruby Tests

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Install dependencies
run: sudo apt-get install check

- name: make
run: make

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true

- name: Setup extension
working-directory: ./ext/erbx
run: bundle install

- name: Build extension
working-directory: ./ext/erbx
run: bundle exec rake

- name: Test extension
run: bundle exec ruby ext/erbx/test.rb
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
/erbx
/run_erbx_tests

# ERBx Ruby extension
/ext/erbx/extconf.h
/ext/erbx/erbx.bundle
/ext/erbx/Makefile
/lib/erbx/erbx.bundle

# Prerequisites
*.d

Expand Down
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

source "https://rubygems.org"

gemspec
30 changes: 30 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
PATH
remote: .
specs:
erbx (0.0.1)
ffi

GEM
remote: https://rubygems.org/
specs:
ffi (1.17.0)
ffi (1.17.0-x86_64-darwin)
maxitest (5.5.0)
minitest (>= 5.14.0, < 5.24.0)
minitest (5.23.1)
rake (13.2.1)
rake-compiler (1.2.7)
rake

PLATFORMS
ruby
x86_64-darwin-23

DEPENDENCIES
erbx!
maxitest
rake (~> 13.2)
rake-compiler (~> 1.2)

BUNDLED WITH
2.5.11
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ test_sources = $(wildcard test/*.c)
test_objects = $(test_sources:.c=.o)
non_main_objects = $(filter-out src/main.o, $(objects))

soext ?= $(shell ruby -e 'puts RbConfig::CONFIG["SOEXT"]')
lib_name = lib$(exec).$(soext)
ruby_extension = ext/erbx/$(lib_name)

os := $(shell uname -s)

flags = -g -Wall -fPIC
Expand All @@ -23,11 +27,15 @@ ifeq ($(os),Darwin)
test_ldflags = -L$(brew_prefix)/lib -lcheck -lm
endif

all: $(exec) test
all: $(exec) $(lib_name) test

$(exec): $(objects)
gcc $(objects) $(flags) -o $(exec)

$(lib_name): $(objects)
gcc -shared $(objects) $(flags) -o $(lib_name)
# cp $(lib_name) $(ruby_extension)

%.o: %.c include/%.h
gcc -c $(flags) $< -o $@

Expand All @@ -38,5 +46,5 @@ test: $(test_objects) $(non_main_objects)
gcc $(test_objects) $(non_main_objects) $(test_cflags) $(test_ldflags) -o $(test_exec)

clean:
rm -f $(exec) $(test_exec)
rm -f $(exec) $(test_exec) $(lib_name) $(ruby_extension)
rm -f src/*.o test/*.o
39 changes: 39 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
require "bundler/gem_tasks"
require "rake/extensiontask"
require "rake/testtask"

Rake::ExtensionTask.new do |ext|
ext.name = "erbx"
ext.source_pattern = "*.{c,h}"
ext.ext_dir = "ext/erbx"
ext.lib_dir = "lib/erbx"
ext.gem_spec = Gem::Specification.load("erbx.gemspec")
end

Rake::TestTask.new(:test) do |t|
t.libs << "test"
t.libs << "lib"
t.test_files = FileList["ext/erbx/test/**/*_test.rb"]
end

Rake::Task[:compile].enhance do
IO.popen("make") do |output|
output.each_line do |line|
puts "#{line}"
end
end

if $?.exitstatus != 0
raise "src/* could not be compiled #{$?.exitstatus}"
end
end

Rake::Task[:clean].enhance do
IO.popen("make clean") do |output|
output.each_line do |line|
puts "#{line}"
end
end
end

task default: [:compile, :test]
32 changes: 32 additions & 0 deletions erbx.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

Gem::Specification.new do |spec|
spec.name = "erbx"
spec.version = "0.0.1"
spec.authors = ["Marco Roth"]
spec.email = ["marco.roth@intergga.ch"]

spec.summary = "HTML-aware ERB parser"
spec.homepage = "https://github.com/marcoroth/erbx"
spec.license = "MIT"

spec.required_ruby_version = ">= 3.0.0"

spec.require_paths = ["lib"]
spec.files = [
"ext/erbx/extension.c",
"lib/erbx.rb",
# "lib/erbx/version.rb"
]

spec.extensions = ["ext/erbx/extconf.rb"]
spec.metadata["allowed_push_host"] = "https://rubygems.org"
spec.metadata["source_code_uri"] = "https://github.com/marcoroth/erbx"
spec.metadata["changelog_uri"] = "https://github.com/marcoroth/erbx/releases"

spec.add_dependency "ffi"

spec.add_development_dependency "rake", "~> 13.2"
spec.add_development_dependency "rake-compiler", "~> 1.2"
spec.add_development_dependency "maxitest"
end
5 changes: 5 additions & 0 deletions examples/ruby/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

source "https://rubygems.org"

gem "erbx", path: "../.."
18 changes: 18 additions & 0 deletions examples/ruby/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
PATH
remote: ../..
specs:
erbx (0.0.1)

GEM
remote: https://rubygems.org/
specs:

PLATFORMS
ruby
x86_64-darwin-23

DEPENDENCIES
erbx!

BUNDLED WITH
2.5.10
3 changes: 3 additions & 0 deletions examples/ruby/test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
require "erbx"

puts ERBX.lex("<html><html>")
24 changes: 24 additions & 0 deletions ext/erbx/extconf.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require "mkmf"

extension_name = "erbx"
include_path = File.expand_path("../../src/include", __dir__)

dir_config(extension_name, include_path)

unless find_header("#{extension_name}.h", include_path)
abort "#{extension_name}.h can't be found"
end

# expected_functions = [
# "erbx_lex",
# "erbx_lex_file",
# ]
#
# expected_functions.each do |expected_function|
# unless find_library(extension_name, expected_function)
# abort "lib#{extension_name}.so can't be found or #{expected_function}() not defined in it"
# end
# end

create_header
create_makefile("#{extension_name}/#{extension_name}")
32 changes: 32 additions & 0 deletions ext/erbx/extension.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "ruby.h"
#include "extconf.h"
#include "extension.h"

#include "../../src/include/erbx.h"

static const char *check_string(VALUE value) {
if (NIL_P(value)) {
return NULL;
}

if (!RB_TYPE_P(value, T_STRING)) {
rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(value));
}

return RSTRING_PTR(value);
}

VALUE rb_erbx_lex(VALUE self, VALUE source) {
const char *string = check_string(source);

erbx_lex((char *) string);

return Qnil;
}

void Init_erbx() {
VALUE ERBX = rb_define_module("LibERBX");
VALUE Lexer = rb_define_class_under(ERBX, "Lexer", rb_cObject);

rb_define_method(Lexer, "lex", rb_erbx_lex, 1);
}
Empty file added ext/erbx/extension.h
Empty file.
7 changes: 7 additions & 0 deletions ext/erbx/test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

$LOAD_PATH.unshift File.expand_path('../../lib', __dir__)

require "erbx"

ERBX.lex("<html><html>")
21 changes: 21 additions & 0 deletions ext/erbx/test/lexer_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require_relative "test_helper"

class LexerTest < Minitest::Test
def test_lexer
result = ERBX.lex("<html></html>")

expected = [
"TOKEN_START_TAG_START",
"TOKEN_TAG_NAME",
"TOKEN_START_TAG_END",
"TOKEN_END_TAG_START",
"TOKEN_TAG_NAME",
"TOKEN_END_TAG_END",
"TOKEN_EOF"
]

assert_equal expected, result.array.items.map(&:type)
end
end
4 changes: 4 additions & 0 deletions ext/erbx/test/test_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)

require "erbx"
require "maxitest/autorun"
30 changes: 30 additions & 0 deletions lib/erbx.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# frozen_string_literal: true

require "erbx/liberbx"
require "erbx/liberbx/buffer"
require "erbx/liberbx/array"
require "erbx/liberbx/token"

require "erbx/lex_result"

module ERBX
VERSION = LibERBX.erbx_version.read_string

def self.lex_to_buffer(source)
LibERBX::Buffer.with do |output|
LibERBX.erbx_lex_to_buffer(source, output.pointer)

output.read
end
end

def self.lex(source)
LexResult.new(
LibERBX.erbx_lex(source)
)
end

def self.lex_file(path)
lex(File.read(path))
end
end
17 changes: 17 additions & 0 deletions lib/erbx/lex_result.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require "forwardable"

module ERBX
class LexResult
extend Forwardable

def_delegators :@array, :items, :size, :capacity

attr_accessor :array

def initialize(pointer)
@array = LibERBX::Array.new(pointer, LibERBX::Token)
end
end
end
28 changes: 28 additions & 0 deletions lib/erbx/liberbx.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

require "ffi"
require "rbconfig"

module ERBX
module LibERBX
extend FFI::Library

def self.library_extension
RbConfig::CONFIG["SOEXT"]
end

def self.library_name
"liberbx.#{library_extension}"
end

def self.library_path
File.expand_path("../../#{library_name}", __dir__)
end

ffi_lib(library_path)

attach_function :erbx_lex_to_buffer, [:pointer, :pointer], :void
attach_function :erbx_lex, [:pointer], :pointer
attach_function :erbx_version, [], :pointer
end
end
Loading