From 13544d26d9b403b76a9f9497b948f93f3d76587f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Belin?= Date: Mon, 4 Nov 2024 22:06:33 +0100 Subject: [PATCH] Port the `GulpPlugin` class --- lib/fast_transformer.d.ts | 4 +- lib/gulp_plugin.d.ts | 43 ++++++++++++++++++++ lib/index.d.ts | 24 +----------- lib/safe_transformer.d.ts | 4 +- lib/transformer.d.ts | 18 --------- src/fast_transformer.coffee | 2 +- src/gulp_plugin.coffee | 34 ++++++++++++++++ src/index.coffee | 1 + src/php_minifier/GulpPlugin.hx | 61 ----------------------------- src/php_minifier/TransformMode.hx | 11 ------ test/gulp_plugin_test.coffee | 35 +++++++++++++++++ test/php_minifier/GulpPluginTest.hx | 34 ---------------- 12 files changed, 118 insertions(+), 153 deletions(-) create mode 100644 lib/gulp_plugin.d.ts delete mode 100644 lib/transformer.d.ts delete mode 100644 src/php_minifier/GulpPlugin.hx delete mode 100644 src/php_minifier/TransformMode.hx delete mode 100644 test/php_minifier/GulpPluginTest.hx diff --git a/lib/fast_transformer.d.ts b/lib/fast_transformer.d.ts index e63b30e0..1458d6e4 100644 --- a/lib/fast_transformer.d.ts +++ b/lib/fast_transformer.d.ts @@ -1,9 +1,7 @@ -import {Transformer} from "./transformer.js"; - /** * Removes comments and whitespace from a PHP script, by calling a Web service. */ -export class FastTransformer implements Transformer { +export class FastTransformer { /** * Creates a new fast transformer. diff --git a/lib/gulp_plugin.d.ts b/lib/gulp_plugin.d.ts new file mode 100644 index 00000000..0a30d1a1 --- /dev/null +++ b/lib/gulp_plugin.d.ts @@ -0,0 +1,43 @@ +import {Transform, TransformCallback} from "node:stream"; + +/** + * Defines the options of a {@link GulpPlugin} instance. + */ +export type GulpPluginOptions = Partial<{ + + /** + * The path to the PHP executable. + */ + binary: string; + + /** + * The operation mode of the plugin. + */ + mode: "fast"|"safe"; + + /** + * Value indicating whether to silence the plugin output. + */ + silent: boolean; +}>; + +/** + * Minifies PHP source code by removing comments and whitespace. + */ +export class GulpPlugin extends Transform { + + /** + * Creates a new plugin. + * @param options An object providing values to initialize this instance. + */ + constructor(options?: GulpPluginOptions); + + /** + * Transforms input and produces output. + * @param chunk The chunk to transform. + * @param encoding The encoding type if the chunk is a string. + * @param callback The function to invoke when the supplied chunk has been processed. + * @returns The transformed chunk. + */ + _transform(chunk: File, encoding: NodeJS.BufferEncoding, callback: TransformCallback): Promise; +} diff --git a/lib/index.d.ts b/lib/index.d.ts index fb2dd80d..455d5d72 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,28 +1,8 @@ import {Transform} from "node:stream"; +import {GulpPluginOptions} from "./gulp_plugin.js"; export * from "./fast_transformer.js"; +export * from "./gulp_plugin.js"; export * from "./safe_transformer.js"; -export * from "./transformer.js"; - -/** - * Defines the options of a {@link GulpPlugin} instance. - */ -export type GulpPluginOptions = Partial<{ - - /** - * The path to the PHP executable. - */ - binary: string; - - /** - * The operation mode of the plugin. - */ - mode: "fast"|"safe"; - - /** - * Value indicating whether to silence the plugin output. - */ - silent: boolean; -}>; /** * Creates a new plugin. diff --git a/lib/safe_transformer.d.ts b/lib/safe_transformer.d.ts index cd83b09e..451b19e0 100644 --- a/lib/safe_transformer.d.ts +++ b/lib/safe_transformer.d.ts @@ -1,9 +1,7 @@ -import {Transformer} from "./transformer.js"; - /** * Removes comments and whitespace from a PHP script, by calling a PHP process. */ -export class SafeTransformer implements Transformer { +export class SafeTransformer { /** * Creates a new safe transformer. diff --git a/lib/transformer.d.ts b/lib/transformer.d.ts deleted file mode 100644 index 955632ff..00000000 --- a/lib/transformer.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Removes comments and whitespace from a PHP script. - */ -export interface Transformer { - - /** - * Closes this transformer and releases any resources associated with it. - * @returns Resolves when the transformer is finally disposed. - */ - close(): Promise; - - /** - * Processes a PHP script. - * @param file The path to the PHP script. - * @returns The transformed script. - */ - transform(file: string): Promise; -} diff --git a/src/fast_transformer.coffee b/src/fast_transformer.coffee index 68559c6d..8f504a5d 100644 --- a/src/fast_transformer.coffee +++ b/src/fast_transformer.coffee @@ -45,7 +45,7 @@ export class FastTransformer # Gets an ephemeral TCP port chosen by the system. _getPort: -> new Promise (fulfill, reject) -> - server = createServer().unref().on "error", reject + server = createServer().unref().on("error", reject) server.listen host: "127.0.0.1", port: 0, -> {port} = server.address() server.close -> fulfill port diff --git a/src/gulp_plugin.coffee b/src/gulp_plugin.coffee index e69de29b..dc8735a0 100644 --- a/src/gulp_plugin.coffee +++ b/src/gulp_plugin.coffee @@ -0,0 +1,34 @@ +import log from "fancy-log" +import {Buffer} from "node:buffer" +import {Transform} from "node:stream" +import {FastTransformer} from "./fast_transformer.js" +import {SafeTransformer} from "./safe_transformer.js" + +# Minifies PHP source code by removing comments and whitespace. +export class GulpPlugin extends Transform + + # Creates a new plugin. + constructor: (options = {}) -> + super objectMode: true + + binary = options.binary ? "php" + transformer = if options.mode ? "safe" is "fast" then new FastTransformer binary else new SafeTransformer binary + close = -> await transformer.close() + @on("end", close).on("error", close) + + # Value indicating whether to silence the plugin output. + @_silent = options.silent ? no + + # The instance used to process the PHP code + @_transformer = transformer + + # Transforms input and produces output. + _transform: (chunk, encoding, callback) -> + try + log "Minifying: #{chunk.relative}" unless @_silent + chunk.contents = Buffer.from await @_transformer.transform(chunk.path), encoding + callback null, chunk + + catch error + failure = if error instanceof Error then error else String error + callback new PluginError "@cedx/php-minifier", failure, fileName: chunk.path diff --git a/src/index.coffee b/src/index.coffee index 1dab24c4..9f98af13 100644 --- a/src/index.coffee +++ b/src/index.coffee @@ -1,2 +1,3 @@ export * from "./fast_transformer.js" +export * from "./gulp_plugin.js" export * from "./safe_transformer.js" diff --git a/src/php_minifier/GulpPlugin.hx b/src/php_minifier/GulpPlugin.hx deleted file mode 100644 index f26cf071..00000000 --- a/src/php_minifier/GulpPlugin.hx +++ /dev/null @@ -1,61 +0,0 @@ -package php_minifier; - -import js.fancy_log.Logger; -import js.lib.Error; -import js.node.Buffer; -import js.node.stream.Transform; -import js.plugin_error.PluginError; -import js.vinyl.File; - -/** Minifies PHP source code by removing comments and whitespace. **/ -final class GulpPlugin extends Transform { - - /** Value indicating whether to silence the plugin output. **/ - final silent: Bool; - - /** The instance used to process the PHP code. **/ - final transformer: Transformer; - - /** Creates a new plugin. **/ - public function new(?options: GulpPluginOptions) { - super({objectMode: true}); - - final binary = options?.binary ?? "php"; - silent = options?.silent ?? false; - transformer = (options?.mode ?? Safe) == Fast ? new FastTransformer(binary) : new SafeTransformer(binary); - - final close = () -> transformer.close().eager(); - on("end", close).on("error", close); - } - - /** Creates a new plugin. **/ - @:expose("phpMinify") - static inline function create(?options: GulpPluginOptions): GulpPlugin - return new GulpPlugin(options); - - /** Transforms input and produces output. **/ - override function _transform(chunk: Dynamic, encoding: String, callback: (Null, Any) -> Void): Void { - final file: File = chunk; - if (!silent) Logger.log('Minifying: ${file.relative}'); - transformer.transform(file.path).handle(outcome -> switch outcome { - case Failure(error): - callback(new PluginError("@cedx/php-minifier", error.message, {fileName: file.path}), null); - case Success(output): - file.contents = Buffer.from(output, encoding); - callback(null, file); - }); - } -} - -/** Defines the options of a `GulpPlugin` instance. **/ -typedef GulpPluginOptions = { - - /** The path to the PHP executable. **/ - var ?binary: String; - - /** The operation mode of the plugin. **/ - var ?mode: TransformMode; - - /** Value indicating whether to silence the plugin output. **/ - var ?silent: Bool; -} diff --git a/src/php_minifier/TransformMode.hx b/src/php_minifier/TransformMode.hx deleted file mode 100644 index 426c2364..00000000 --- a/src/php_minifier/TransformMode.hx +++ /dev/null @@ -1,11 +0,0 @@ -package php_minifier; - -/** The operation mode of the minifier. **/ -enum abstract TransformMode(String) from String to String { - - /** Applies a fast transformation. **/ - var Fast = "fast"; - - /** Applies a safe transformation. **/ - var Safe = "safe"; -} diff --git a/test/gulp_plugin_test.coffee b/test/gulp_plugin_test.coffee index e69de29b..e8aaf73c 100644 --- a/test/gulp_plugin_test.coffee +++ b/test/gulp_plugin_test.coffee @@ -0,0 +1,35 @@ +import {GulpPlugin} from "@cedx/php-minifier" +import {doesNotReject, ifError, ok} from "node:assert/strict" +import {resolve} from "node:path" +import {after, describe, it} from "node:test" +import File from "vinyl" + +# Tests the features of the `GulpPlugin` class. +describe "GulpPlugin", -> + describe "_transform()", -> + map = new Map [ + ["should remove the inline comments", ""] + ["should remove the multi-line comments", "namespace dummy; class Dummy"] + ["should remove the single-line comments", "$className = get_class($this); return $className;"] + ["should remove the whitespace", "__construct() { $this->property"] + ] + + describe "fast", -> + file = new File path: resolve "res/sample.php" + plugin = new GulpPlugin mode: "fast", silent: yes + after -> plugin.emit "end" + + for [key, value] from map then it key, -> + await doesNotReject plugin._transform file, "utf8", (error, chunk) -> + ifError error + ok chunk.contents.toString().includes value + + describe "safe", -> + file = new File path: resolve "res/sample.php" + plugin = new GulpPlugin mode: "safe", silent: yes + after -> plugin.emit "end" + + for [key, value] from map then it key, -> + await doesNotReject plugin._transform file, "utf8", (error, chunk) -> + ifError error + ok chunk.contents.toString().includes value diff --git a/test/php_minifier/GulpPluginTest.hx b/test/php_minifier/GulpPluginTest.hx deleted file mode 100644 index 7b303f00..00000000 --- a/test/php_minifier/GulpPluginTest.hx +++ /dev/null @@ -1,34 +0,0 @@ -package php_minifier; - -import asys.FileSystem; -import js.node.Buffer; -import js.vinyl.File; -using StringTools; - -/** Tests the features of the `GulpPlugin` class. **/ -@:asserts final class GulpPluginTest { - - /** Creates a new test. **/ - public function new() {} - - /** Tests the `transform()` method. **/ - @:variant(Fast) - @:variant(Safe) - public function transform(input: TransformMode) { - final file = new File({path: FileSystem.absolutePath("res/sample.php")}); - final plugin = new GulpPlugin({mode: input, silent: true}); - @:privateAccess plugin._transform(file, "utf8", (error, chunk) -> { - plugin.emit("end"); - asserts.assert(error == null); - - final script = ((chunk: File).contents: Buffer).toString(); - asserts.assert(script.contains("")); - asserts.assert(script.contains("namespace dummy; class Dummy")); - asserts.assert(script.contains("$className = get_class($this); return $className;")); - asserts.assert(script.contains("__construct() { $this->property")); - asserts.done(); - }); - - return asserts; - } -}