Create Ruby version

This commit is contained in:
Wilson Lin 2020-01-19 19:19:33 +11:00
parent 5c1b618610
commit e192aa6c3f
12 changed files with 199 additions and 6 deletions

85
.github/workflows/ruby.yml vendored Normal file
View File

@ -0,0 +1,85 @@
name: Build, package, and upload Ruby gem
on:
create:
tags:
- 'v*'
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
NAME: linux
FILE: 'libhyperbuild_ruby_lib.so'
- os: windows-latest
NAME: windows
FILE: 'hyperbuild_ruby_lib.dll'
- os: macos-latest
NAME: macos
FILE: 'libhyperbuild_ruby_lib.dylib'
steps:
- uses: actions/checkout@v1
- name: Get version
id: version
shell: bash
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}
- name: Set up Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
default: true
- name: Build Ruby native library
run: cargo build --release
working-directory: ./ruby
- name: Upload built library
uses: actions/upload-artifact@v1
with:
name: ${{ matrix.NAME }}
path: ./ruby/target/release/${{ matrix.FILE }}
package:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v1
- name: Get version
id: version
shell: bash
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/v}
- name: Get file name
id: file
shell: bash
run: echo ::set-output name=FILE::${{ steps.version.outputs.VERSION }}.jar
- name: Set up JDK
uses: actions/setup-ruby@v1
with:
ruby-version: '2.5'
- name: Download Windows built library
uses: actions/download-artifact@v1
with:
name: windows
path: ruby/lib
- name: Download Linux built library
uses: actions/download-artifact@v1
with:
name: linux
path: ruby/lib
- name: Download macOS built library
uses: actions/download-artifact@v1
with:
name: macos
path: ruby/lib
- name: Package gem
working-directory: ./ruby
run: gem build hyperbuild.gemspec
- uses: chrislennon/action-aws-cli@v1.1
- name: Upload to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-west-2
run: aws s3 cp ./ruby/hyperbuild-${{ steps.version.outputs.VERSION }}.gem s3://${{ secrets.AWS_S3_BUCKET }}/hyperbuild/bin/${{ steps.version.outputs.VERSION }}.gem

View File

@ -1,6 +1,6 @@
[package]
name = "hyperbuild"
description = "One-pass in-place HTML minifier written in Rust with context-aware whitespace handling"
description = "Fast one-pass in-place HTML minifier written in Rust with context-aware whitespace handling"
license = "MIT"
homepage = "https://github.com/wilsonzlin/hyperbuild"
readme = "README.md"

View File

@ -5,7 +5,7 @@ A fast one-pass in-place HTML minifier written in Rust with context-aware whites
Available as:
- CLI for Windows, macOS, and Linux.
- Rust library.
- Native library for Node.js, Python, and Java.
- Native library for Node.js, Python, Java, and Ruby.
## Features
@ -140,6 +140,25 @@ minified = hyperbuild.minify("<p> Hello, world! </p>")
</details>
<details>
<summary><strong>Ruby</strong></summary>
hyperbuild is available as a [native module](https://github.com/danielpclark/rutie), and supports Ruby versions 2.5 and higher.
##### Get
Download and install the [gem](https://wilsonl.in/hyperbuild/bin/0.0.20.gem).
##### Use
```ruby
require 'hyperbuild'
print hyperbuild.minify "<p> Hello, world! </p>"
```
</details>
## Minification
### Whitespace

View File

@ -9,7 +9,7 @@
<version>0.0.20</version>
<name>hyperbuild</name>
<description>One-pass in-place HTML minifier written in Rust with context-aware whitespace handling</description>
<description>Fast one-pass in-place HTML minifier written in Rust with context-aware whitespace handling</description>
<developers>
<developer>
<name>Wilson Lin</name>

View File

@ -1,7 +1,7 @@
{
"name": "hyperbuild",
"version": "0.0.20",
"description": "One-pass in-place HTML minifier written in Rust with context-aware whitespace handling",
"description": "Fast one-pass in-place HTML minifier written in Rust with context-aware whitespace handling",
"main": "lib/index.js",
"repository": {
"type": "git",

3
ruby/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/Cargo.lock
/Gemfile.lock
/target

14
ruby/Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "hyperbuild-ruby"
publish = false
version = "0.0.20"
authors = ["Wilson Lin <code@wilsonl.in>"]
edition = "2018"
[lib]
name = "hyperbuild_ruby_lib"
crate-type = ["cdylib"]
[dependencies]
hyperbuild = "0.0.20"
rutie = "0.7.0"

3
ruby/Gemfile Normal file
View File

@ -0,0 +1,3 @@
source "https://rubygems.org"
gemspec

16
ruby/hyperbuild.gemspec Normal file
View File

@ -0,0 +1,16 @@
require 'rake'
Gem::Specification.new do |spec|
spec.name = "hyperbuild"
spec.version = "0.0.20"
spec.authors = ["Wilson Lin"]
spec.email = ["code@wilsonl.in"]
spec.license = "MIT"
spec.files = FileList["lib/*"].to_a
spec.summary = "Fast one-pass in-place HTML minifier written in Rust with context-aware whitespace handling"
spec.homepage = "https://github.com/wilsonzlin/hyperbuild"
spec.require_paths = ["lib"]
spec.add_dependency "fiddle", "~> 1.0"
end

18
ruby/lib/hyperbuild.rb Normal file
View File

@ -0,0 +1,18 @@
require 'fiddle'
class HyperbuildLoader
def self.operating_system
case RbConfig::CONFIG['host_os'].downcase
when /linux|bsd|solaris/ then 'linux'
when /darwin/ then 'macos'
when /mingw|mswin/ then 'windows'
else 'unknown'
end
end
def self.lib_path
File.join(__dir__, operating_system)
end
end
Fiddle::Function.new(Fiddle.dlopen(HyperbuildLoader.lib_path)['Init_hyperbuild'], [], Fiddle::TYPE_VOIDP).call

31
ruby/src/lib.rs Normal file
View File

@ -0,0 +1,31 @@
use hyperbuild::hyperbuild as hyperbuild_native;
use rutie::{Class, class, methods, Object, RString, VM};
use std::str::from_utf8_unchecked;
class!(Hyperbuild);
methods! {
Hyperbuild,
_itself,
fn minify(source: RString) -> RString {
let mut code = source
.map_err(|e| VM::raise_ex(e) )
.unwrap()
.to_string()
.into_bytes();
hyperbuild_native(&mut code)
.map_err(|(err, pos)| VM::raise(Class::from_existing("SyntaxError"), format!("{} [Character {}]", err.message(), pos).as_str()))
.map(|out_len| RString::new_utf8(unsafe { from_utf8_unchecked(&code[0..out_len]) }))
.unwrap()
}
}
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn Init_hyperbuild() {
Class::new("Hyperbuild", None).define(|itself| {
itself.def_self("minify", minify);
});
}

View File

@ -48,11 +48,11 @@ if (cmd('git', 'status', '--porcelain', {throwOnStderr: true, captureStdio: true
throw new Error(`Working directory not clean`);
}
for (const f of ["Cargo.toml", "nodejs/native/Cargo.toml", "java/Cargo.toml", "python/Cargo.toml"]) {
for (const f of ["Cargo.toml", "nodejs/native/Cargo.toml", "java/Cargo.toml", "python/Cargo.toml", "ruby/Cargo.toml"]) {
replaceInFile(f, /^version = "\d+\.\d+\.\d+"\s*$/m, `version = "${NEW_VERSION}"`);
}
for (const f of ["README.md", "nodejs/native/Cargo.toml", "java/Cargo.toml", "python/Cargo.toml"]) {
for (const f of ["README.md", "nodejs/native/Cargo.toml", "java/Cargo.toml", "python/Cargo.toml", "ruby/Cargo.toml"]) {
replaceInFile(f, /^hyperbuild = "\d+\.\d+\.\d+"\s*$/m, `hyperbuild = "${NEW_VERSION}"`);
}
@ -60,6 +60,10 @@ for (const f of ["nodejs/package.json"]) {
replaceInFile(f, /^(\s*)"version": "\d+\.\d+\.\d+",\s*$/m, `$1"version": "${NEW_VERSION}",`);
}
for (const f of ["ruby/hyperbuild.gemspec"]) {
replaceInFile(f, /^(\s*spec\.version\s*=\s*)"\d+\.\d+\.\d+"\s*$/m, `$1"${NEW_VERSION}",`);
}
for (const f of ["java/pom.xml"]) {
replaceInFile(f, /(<artifactId>hyperbuild<\/artifactId>\s*<version>)\d+\.\d+\.\d+(<\/version>)/, `$1${NEW_VERSION}$2`);
}