diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9c3926dc..fa918f66 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -571,6 +571,94 @@ jobs: DEFAULT_CROSS_BUILD_ENV_URL: "https://github.com/pyodide/pyodide/releases/download/0.28.0a3/xbuildenv-0.28.0a3.tar.bz2" RUSTFLAGS: "-C link-arg=-sSIDE_MODULE=2 -Z link-native-libraries=no -Z emscripten-wasm-eh" + test-php: + strategy: + fail-fast: false + matrix: + os: [ubuntu-22.04, macos-15] + php-version: ["8.2", "8.3", "8.4"] + clang: ["20"] + + name: PHP ${{ matrix.php-version }} on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v6 + + - uses: dtolnay/rust-toolchain@stable + + - name: Cache LLVM and Clang + id: cache-llvm + uses: actions/cache@v4 + if: matrix.os == 'ubuntu-22.04' + with: + path: ${{ runner.temp }}/llvm-${{ matrix.clang }} + key: ${{ matrix.os }}-llvm-${{ matrix.clang }} + + - name: Setup LLVM & Clang + id: clang + uses: KyleMayes/install-llvm-action@v2 + if: matrix.os == 'ubuntu-22.04' + with: + version: ${{ matrix.clang }} + directory: ${{ runner.temp }}/llvm-${{ matrix.clang }} + cached: ${{ steps.cache-llvm.outputs.cache-hit }} + + - name: Configure Clang + if: matrix.os == 'ubuntu-22.04' + run: | + echo "LIBCLANG_PATH=${{ runner.temp }}/llvm-${{ matrix.clang }}/lib" >> $GITHUB_ENV + echo "LLVM_VERSION=${{ steps.clang.outputs.version }}" >> $GITHUB_ENV + echo "LLVM_CONFIG_PATH=${{ runner.temp }}/llvm-${{ matrix.clang }}/bin/llvm-config" >> $GITHUB_ENV + + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + extensions: mbstring + coverage: none + + - name: Build PHP extension + run: | + export PHP_CONFIG=$(which php-config) + + cargo build --release + + EXT_DIR=$(php -r "echo ini_get('extension_dir');") + + if [[ "${{ matrix.os }}" == "macos-15" ]]; then + BUILT_LIB=$(find target/release -name "libcss_inline_php.dylib" -o -name "css_inline_php.dylib" | head -1) + if [[ -z "$BUILT_LIB" ]]; then + BUILT_LIB=$(find target/release -name "*.dylib" | head -1) + fi + sudo cp "$BUILT_LIB" "$EXT_DIR/css_inline.so" + else + BUILT_LIB=$(find target/release -name "*.so" | head -1) + sudo cp "$BUILT_LIB" "$EXT_DIR/css_inline.so" + fi + working-directory: ./bindings/php + shell: bash + + - name: Enable and verify extension + run: | + if [[ "${{ matrix.os }}" == "macos-15" ]]; then + PHP_INI_DIR=$(php -i | grep "Scan this dir for additional .ini files" | cut -d' ' -f9 | tr -d ' ') + echo "extension=css_inline" | sudo tee "$PHP_INI_DIR/99-css_inline.ini" + else + echo "extension=css_inline" | sudo tee /etc/php/${{ matrix.php-version }}/cli/conf.d/99-css_inline.ini + fi + shell: bash + + - name: Install dependencies + run: composer install --no-interaction --prefer-dist + working-directory: ./bindings/php + + - name: Lint PHP code + run: composer lint + working-directory: ./bindings/php + + - name: Run tests + run: composer test + working-directory: ./bindings/php + test-ruby: strategy: fail-fast: false diff --git a/.github/workflows/php-release.yml b/.github/workflows/php-release.yml new file mode 100644 index 00000000..f5db1f60 --- /dev/null +++ b/.github/workflows/php-release.yml @@ -0,0 +1,125 @@ +name: "[PHP] Release" + +on: + push: + tags: + - php-v* + +jobs: + build: + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-22.04 + target: x86_64-unknown-linux-gnu + php: "8.2" + artifact: libcss_inline_php.so + - os: ubuntu-22.04 + target: x86_64-unknown-linux-gnu + php: "8.3" + artifact: libcss_inline_php.so + - os: ubuntu-22.04 + target: x86_64-unknown-linux-gnu + php: "8.4" + artifact: libcss_inline_php.so + - os: macos-15 + target: x86_64-apple-darwin + php: "8.2" + artifact: libcss_inline_php.dylib + cross: true + - os: macos-15 + target: x86_64-apple-darwin + php: "8.3" + artifact: libcss_inline_php.dylib + cross: true + - os: macos-15 + target: x86_64-apple-darwin + php: "8.4" + artifact: libcss_inline_php.dylib + cross: true + - os: macos-15 + target: aarch64-apple-darwin + php: "8.2" + artifact: libcss_inline_php.dylib + - os: macos-15 + target: aarch64-apple-darwin + php: "8.3" + artifact: libcss_inline_php.dylib + - os: macos-15 + target: aarch64-apple-darwin + php: "8.4" + artifact: libcss_inline_php.dylib + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v6 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + + - name: Install Rust + uses: dtolnay/rust-toolchain@stable + with: + targets: ${{ matrix.cross && matrix.target || '' }} + + - uses: Swatinem/rust-cache@v2 + with: + workspaces: bindings/php + cache-all-crates: "true" + + - name: Build + run: | + if [ "${{ matrix.cross }}" = "true" ]; then + cargo build --release --target ${{ matrix.target }} + else + cargo build --release + fi + working-directory: bindings/php + + - name: Rename artifact + run: | + mkdir -p dist + if [ "${{ matrix.cross }}" = "true" ]; then + cp bindings/php/target/${{ matrix.target }}/release/${{ matrix.artifact }} dist/css_inline-php${{ matrix.php }}-${{ matrix.target }}.so + else + cp bindings/php/target/release/${{ matrix.artifact }} dist/css_inline-php${{ matrix.php }}-${{ matrix.target }}.so + fi + + - name: Upload artifact + uses: actions/upload-artifact@v6 + with: + name: css_inline-php${{ matrix.php }}-${{ matrix.target }} + path: dist/ + + release: + needs: build + runs-on: ubuntu-22.04 + permissions: + contents: write + + steps: + - uses: actions/checkout@v6 + + - name: Extract Version + run: echo "version=${GITHUB_REF#refs/tags/php-v}" >> $GITHUB_ENV + + - name: Download all artifacts + uses: actions/download-artifact@v7 + with: + path: artifacts + merge-multiple: true + + - name: List artifacts + run: ls -la artifacts/ + + - name: GitHub Release + uses: softprops/action-gh-release@v2 + with: + make_latest: false + draft: true + name: "[PHP] Release ${{ env.version }}" + files: artifacts/* diff --git a/README.md b/README.md index b69b7462..683a27b8 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ into: - Optionally caches external stylesheets - Works on Linux, Windows, and macOS - Supports HTML5 & CSS3 -- Bindings for [Python](https://github.com/Stranger6667/css-inline/tree/master/bindings/python), [Ruby](https://github.com/Stranger6667/css-inline/tree/master/bindings/ruby), [JavaScript](https://github.com/Stranger6667/css-inline/tree/master/bindings/javascript), [Java](https://github.com/Stranger6667/css-inline/tree/master/bindings/java), [C](https://github.com/Stranger6667/css-inline/tree/master/bindings/c), and a [WebAssembly](https://github.com/Stranger6667/css-inline/tree/master/bindings/javascript/wasm) module to run in browsers. +- Bindings for [Python](https://github.com/Stranger6667/css-inline/tree/master/bindings/python), [Ruby](https://github.com/Stranger6667/css-inline/tree/master/bindings/ruby), [JavaScript](https://github.com/Stranger6667/css-inline/tree/master/bindings/javascript), [Java](https://github.com/Stranger6667/css-inline/tree/master/bindings/java), [C](https://github.com/Stranger6667/css-inline/tree/master/bindings/c), [PHP](https://github.com/Stranger6667/css-inline/tree/master/bindings/php), and a [WebAssembly](https://github.com/Stranger6667/css-inline/tree/master/bindings/javascript/wasm) module to run in browsers. - Command Line Interface ## Playground diff --git a/bindings/javascript/wasm/index.html b/bindings/javascript/wasm/index.html index 4a23bb83..600874b8 100644 --- a/bindings/javascript/wasm/index.html +++ b/bindings/javascript/wasm/index.html @@ -9,7 +9,7 @@ />
css-inline uses components from Mozilla's Servo project and provides
- bindings for Rust, Python, Ruby, JavaScript, Java, and C. The
+ bindings for Rust, Python, Ruby, JavaScript, Java, C, and PHP. The
playground runs the library compiled to WebAssembly in the browser.
Paste HTML with CSS into the text area and click "Inline" to process
the output.
diff --git a/bindings/php/.cargo/config.toml b/bindings/php/.cargo/config.toml
new file mode 100644
index 00000000..d566dec3
--- /dev/null
+++ b/bindings/php/.cargo/config.toml
@@ -0,0 +1,12 @@
+[target.x86_64-unknown-linux-gnu]
+rustflags = ["-C", "link-arg=-Wl,-undefined,dynamic_lookup"]
+
+[target.x86_64-apple-darwin]
+rustflags = ["-C", "link-arg=-Wl,-undefined,dynamic_lookup"]
+
+[target.aarch64-apple-darwin]
+rustflags = ["-C", "link-arg=-Wl,-undefined,dynamic_lookup"]
+
+[target.x86_64-pc-windows-msvc]
+linker = "rust-lld"
+rustflags = ["-C", "link-arg=/FORCE"]
diff --git a/bindings/php/.gitignore b/bindings/php/.gitignore
new file mode 100644
index 00000000..7993a8ef
--- /dev/null
+++ b/bindings/php/.gitignore
@@ -0,0 +1,4 @@
+/vendor/
+/composer.lock
+/.phpunit.cache/
+/.php-cs-fixer.cache
diff --git a/bindings/php/.php-cs-fixer.dist.php b/bindings/php/.php-cs-fixer.dist.php
new file mode 100644
index 00000000..00477833
--- /dev/null
+++ b/bindings/php/.php-cs-fixer.dist.php
@@ -0,0 +1,21 @@
+in(__DIR__ . '/tests')
+ ->in(__DIR__ . '/stubs')
+ ->in(__DIR__ . '/benchmarks')
+ ->name('*.php');
+
+return (new PhpCsFixer\Config())
+ ->setRiskyAllowed(true)
+ ->setRules([
+ '@PER-CS' => true,
+ '@PHP82Migration' => true,
+ 'array_syntax' => ['syntax' => 'short'],
+ 'declare_strict_types' => true,
+ 'no_unused_imports' => true,
+ 'ordered_imports' => ['sort_algorithm' => 'alpha'],
+ 'single_quote' => true,
+ 'trailing_comma_in_multiline' => true,
+ ])
+ ->setFinder($finder);
diff --git a/bindings/php/Cargo.toml b/bindings/php/Cargo.toml
new file mode 100644
index 00000000..e88065fb
--- /dev/null
+++ b/bindings/php/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "css_inline"
+version = "0.18.0"
+edition = "2021"
+authors = ["Dmitry Dygalo ](https://github.com/Stranger6667/css-inline/actions/workflows/build.yml)
+[
](https://app.codecov.io/github/Stranger6667/css-inline)
+[
](https://gitter.im/Stranger6667/css-inline)
+
+`css_inline` is a high-performance library for inlining CSS into HTML 'style' attributes.
+
+This library is designed for scenarios such as preparing HTML emails or embedding HTML into third-party web pages.
+
+For instance, the library transforms HTML like this:
+
+```html
+
+
+
+
+
+
Big Text
+
+
+```
+
+into:
+
+```html
+
+
+
+ Big Text
+
+
+```
+
+- Uses reliable components from Mozilla's Servo project
+- 3-25x faster than alternatives
+- Inlines CSS from `style` and `link` tags
+- Removes `style` and `link` tags
+- Resolves external stylesheets (including local files)
+- Optionally caches external stylesheets
+- Can process multiple documents in parallel
+- Works on Linux and macOS (Windows is not supported)
+- Supports HTML5 & CSS3
+
+## Playground
+
+If you'd like to try `css-inline`, you can check the WebAssembly-powered [playground](https://css-inline.org/) to see the results instantly.
+
+## Installation
+
+`css_inline` is distributed as a PHP extension. You'll need to compile it from source:
+
+```shell
+git clone https://github.com/Stranger6667/css-inline.git
+cd css-inline/bindings/php
+cargo build --release
+```
+
+Then copy the compiled extension to your PHP extensions directory:
+
+```shell
+# Linux
+cp target/release/libcss_inline_php.so $(php-config --extension-dir)/css_inline.so
+
+# macOS
+cp target/release/libcss_inline_php.dylib $(php-config --extension-dir)/css_inline.so
+```
+
+Enable the extension in your `php.ini`:
+
+```ini
+extension=css_inline
+```
+
+Requirements:
+- PHP 8.2 or higher
+- Rust toolchain (for building from source)
+- Linux or macOS (Windows is not supported by the underlying `ext-php-rs` library)
+
+## Usage
+
+```php
+
+
+
+
+
+ Big Text
+
+