Skip to content
Merged

Cli #392

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
40 changes: 40 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Rust Check

on:
push:
branches:
- main
paths:
- 'packages/liquid-forge-native/**'
- '.github/workflows/rust.yml'
pull_request:
branches:
- main
paths:
- 'packages/liquid-forge-native/**'
- '.github/workflows/rust.yml'

jobs:
check:
runs-on: ubuntu-latest
defaults:
run:
working-directory: packages/liquid-forge-native

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-unknown-linux-gnu

- name: Check code
run: cargo check --lib --target x86_64-unknown-linux-gnu

- name: Run tests
run: cargo test --lib --target x86_64-unknown-linux-gnu

- name: Run clippy
run: cargo clippy --lib --target x86_64-unknown-linux-gnu -- -D warnings
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,8 @@
},
"eslint.workingDirectories": [
{ "mode": "auto" }
],
"rust-analyzer.linkedProjects": [
"${workspaceFolder}/packages/liquid-forge-native/Cargo.toml"
]
}
10 changes: 5 additions & 5 deletions packages/liquid-forge-native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ license = "Apache-2.0"
description = "High-performance Rust filters for Liquid template engine"

[lib]
crate-type = ["cdylib"]
crate-type = ["cdylib", "rlib"]

[dependencies]
# NAPI-RS for Node.js bindings
napi = "2.16"
napi-derive = "2.16"
napi = "3.7"
napi-derive = "3.4"

# Core dependencies
regex = "1.10"
once_cell = "1.19"
unicode-normalization = "0.1"

[build-dependencies]
napi-build = "2.1"
napi-build = "2.3"

[profile.release]
lto = true
Expand All @@ -36,5 +36,5 @@ name = "filters_bench"
harness = false

[dev-dependencies]
criterion = "0.5"
criterion = "0.8"

3 changes: 2 additions & 1 deletion packages/liquid-forge-native/benches/filters_bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
//!
//! Run with: cargo bench

use criterion::{black_box, criterion_group, criterion_main, Criterion};
use criterion::{criterion_group, criterion_main, Criterion};
use liquid_forge_native::*;
use std::hint::black_box;

fn bench_handleize(c: &mut Criterion) {
c.bench_function("handleize_simple", |b| {
Expand Down
11 changes: 1 addition & 10 deletions packages/liquid-forge-native/examples/benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

const { performance } = require('perf_hooks');

// Cargar módulo nativo (si está disponible)
let nativeFilters = null;
try {
nativeFilters = require('../index.js');
Expand All @@ -18,7 +17,6 @@ try {
process.exit(1);
}

// Implementaciones JavaScript para comparación
const jsHandleize = (text) => {
if (!text) return '';
return text
Expand All @@ -45,7 +43,6 @@ const jsTruncate = (text, length = 50, suffix = '...') => {
return text.substring(0, length - suffix.length) + suffix;
};

// Test data
const testData = {
handleize: [
'Hello World',
Expand All @@ -68,33 +65,28 @@ const testData = {
],
};

// Función de benchmark
function benchmark(name, nativeFn, jsFn, data, iterations = 10000) {
// Warm up
for (let i = 0; i < 100; i++) {
data.forEach((input) => {
nativeFn(input);
jsFn(input);
});
}

// Benchmark Native
const startNative = performance.now();
for (let i = 0; i < iterations; i++) {
data.forEach((input) => nativeFn(input));
}
const endNative = performance.now();
const nativeTime = endNative - startNative;

// Benchmark JavaScript
const startJs = performance.now();
for (let i = 0; i < iterations; i++) {
data.forEach((input) => jsFn(input));
}
const endJs = performance.now();
const jsTime = endJs - startJs;

// Results
const speedup = (jsTime / nativeTime).toFixed(2);
const saved = (((jsTime - nativeTime) / jsTime) * 100).toFixed(1);

Expand All @@ -107,7 +99,6 @@ function benchmark(name, nativeFn, jsFn, data, iterations = 10000) {
return { nativeTime, jsTime, speedup, saved };
}

// Ejecutar benchmarks
console.log('Benchmark: Native filters vs JavaScript');
console.log(` Iteraciones: ${10000}`);
console.log(` Inputs por filtro: variado\n`);
Expand Down Expand Up @@ -141,7 +132,7 @@ console.log(` Ahorro promedio: ${avgSaved}%`);
console.log('\nImpact on production:');
console.log(' Para 1000 req/s con 200 filtros por página:');
const totalSavedMs = results.reduce((sum, r) => sum + (r.jsTime - r.nativeTime), 0);
const savedPerRequest = totalSavedMs / 10000; // Normalizado
const savedPerRequest = totalSavedMs / 10000;
const savedPerSecond = savedPerRequest * 1000;
console.log(` Ahorro: ~${savedPerSecond.toFixed(0)}ms CPU por segundo`);
console.log(` Equivalente a: ${(savedPerSecond / 1000).toFixed(1)}s CPU ahorrados por segundo de requests`);
Expand Down
12 changes: 0 additions & 12 deletions packages/liquid-forge-native/examples/usage.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
* node examples/usage.js
*/

// Cargar módulo nativo
let filters = null;
try {
filters = require('../index.js');
Expand All @@ -19,71 +18,60 @@ try {
console.log('Native filters examples\n');
console.log('═'.repeat(60));

// append
console.log('\nappend(input, value)');
console.log(` Input: "Hello", " World"`);
console.log(` Output: "${filters.append('Hello', ' World')}"`);

// prepend
console.log('\nprepend(input, value)');
console.log(` Input: "World", "Hello "`);
console.log(` Output: "${filters.prepend('World', 'Hello ')}"`);

// handleize
console.log('\nhandleize(text)');
const testTexts = ['Hello World', 'Ñoño & Friends', 'Café con Leche', ' Multiple Spaces '];
testTexts.forEach((text) => {
console.log(` "${text}" → "${filters.handleize(text)}"`);
});

// escape
console.log('\nescape(text)');
const htmlTexts = ['Rock & Roll', '<script>alert("XSS")</script>', 'She said "Hello"'];
htmlTexts.forEach((text) => {
console.log(` "${text}"`);
console.log(` → "${filters.escape(text)}"`);
});

// truncate
console.log('\ntruncate(text, length, suffix)');
const longText = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit';
console.log(` "${longText}"`);
console.log(` → "${filters.truncate(longText, 20)}"`);
console.log(` → "${filters.truncate(longText, 20, '…')}"`);

// pluralize
console.log('\npluralize(count, singular, plural)');
[0, 1, 2, 5].forEach((count) => {
console.log(` ${count} ${filters.pluralize(count, 'item', 'items')}`);
});

// defaultValue
console.log('\ndefaultValue(value, default)');
console.log(` null → "${filters.defaultValue(null, 'N/A')}"`);
console.log(` "" → "${filters.defaultValue('', 'N/A')}"`);
console.log(` "Hello" → "${filters.defaultValue('Hello', 'N/A')}"`);

// stripHtml
console.log('\nstripHtml(text)');
const htmlContent = '<p>Hello <strong>World</strong>!</p>';
console.log(` "${htmlContent}"`);
console.log(` → "${filters.stripHtml(htmlContent)}"`);

// stripNewlines
console.log('\nstripNewlines(text)');
const multiline = 'Line 1\nLine 2\r\nLine 3';
console.log(` "Line 1\\nLine 2\\r\\nLine 3"`);
console.log(` → "${filters.stripNewlines(multiline)}"`);

// newlineToBr
console.log('\nnewlineToBr(text)');
console.log(` "Line 1\\nLine 2"`);
console.log(` → "${filters.newlineToBr('Line 1\nLine 2')}"`);

console.log('\n' + '═'.repeat(60));
console.log('\nNative filters are working correctly!\n');

// Casos edge
console.log('Edge cases:\n');

console.log(' handleize(null):', `"${filters.handleize(null)}"`);
Expand Down
6 changes: 3 additions & 3 deletions packages/liquid-forge-native/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@fasttify/liquid-forge-native",
"version": "1.0.0",
"description": "High-performance native filters for Liquid templates",
"description": "High-performance native modules for Liquid Forge",
"main": "index.js",
"types": "index.d.ts",
"private": true,
Expand Down Expand Up @@ -34,10 +34,10 @@
"version": "napi version"
},
"devDependencies": {
"@napi-rs/cli": "^2.18.0"
"@napi-rs/cli": "^3.5.0"
},
"engines": {
"node": ">= 18"
"node": ">= 20"
},
"files": [
"index.js",
Expand Down
5 changes: 2 additions & 3 deletions packages/liquid-forge-native/src/filters/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub fn escape(text: Option<String>) -> String {
};

// Fast path: check if escaping is needed
if !text.contains(&['&', '<', '>', '"', '\'']) {
if !text.contains(['&', '<', '>', '"', '\'']) {
return text;
}

Expand Down Expand Up @@ -179,8 +179,7 @@ pub fn newline_to_br(text: Option<String>) -> String {
};

text.replace("\r\n", "<br>")
.replace('\n', "<br>")
.replace('\r', "<br>")
.replace(['\n', '\r'], "<br>")
}

#[cfg(test)]
Expand Down
Loading
Loading