-
Notifications
You must be signed in to change notification settings - Fork 63
Add bindings for dart #136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
m-haisham
wants to merge
11
commits into
wilsonzlin:master
Choose a base branch
from
m-haisham:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
d942a86
Create initial dart project
6af6286
Add rust extern minify function
8876f98
Write initial binding code for dart
8101ce5
Return and parse utf8 string with length
b470239
Add dart example
75ca7a6
Allocate only required length of memory
46a08d4
Remove unused libBuildOutDir function
23a4620
Delete changelog and readme
182432a
Update locator to look for library in script directory and current di…
da2fe6d
Remove print statement
5000d34
refactor: dont search parents for native library
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # https://dart.dev/guides/libraries/private-files | ||
| # Created by `dart pub` | ||
| .dart_tool/ | ||
|
|
||
| # Avoid committing pubspec.lock for library packages; see | ||
| # https://dart.dev/guides/libraries/private-files#pubspeclock. | ||
| pubspec.lock |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # This file configures the static analysis results for your project (errors, | ||
| # warnings, and lints). | ||
| # | ||
| # This enables the 'recommended' set of lints from `package:lints`. | ||
| # This set helps identify many issues that may lead to problems when running | ||
| # or consuming Dart code, and enforces writing Dart using a single, idiomatic | ||
| # style and format. | ||
| # | ||
| # If you want a smaller set of lints you can change this to specify | ||
| # 'package:lints/core.yaml'. These are just the most critical lints | ||
| # (the recommended set includes the core lints). | ||
| # The core lints are also what is used by pub.dev for scoring packages. | ||
|
|
||
| include: package:lints/recommended.yaml | ||
|
|
||
| # Uncomment the following section to specify additional rules. | ||
|
|
||
| # linter: | ||
| # rules: | ||
| # - camel_case_types | ||
|
|
||
| # analyzer: | ||
| # exclude: | ||
| # - path/to/excluded/files/** | ||
|
|
||
| # For more information about the core and recommended set of lints, see | ||
| # https://dart.dev/go/core-lints | ||
|
|
||
| # For additional information about configuring this file, see | ||
| # https://dart.dev/guides/language/analysis-options |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| import 'package:minify_html/minify_html.dart'; | ||
|
|
||
| void main(List<String> args) { | ||
| final minified = minifyHtml("<p> Hello, world! </p>"); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| library minify_html; | ||
|
|
||
| export 'src/minify_html.dart'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| // ignore_for_file: non_constant_identifier_names, camel_case_types | ||
|
|
||
| import 'dart:ffi'; | ||
|
|
||
| import 'package:ffi/ffi.dart'; | ||
| import 'package:minify_html/src/locator.dart'; | ||
|
|
||
| typedef minify_html_native = Int32 Function( | ||
| Pointer<Utf8> input, | ||
| Uint32 length, | ||
| Bool do_not_minify_doctype, | ||
| Bool ensure_spec_compliant_unquoted_attribute_values, | ||
| Bool keep_closing_tags, | ||
| Bool keep_html_and_head_opening_tags, | ||
| Bool keep_spaces_between_attributes, | ||
| Bool keep_comments, | ||
| Bool minify_css, | ||
| Bool minify_css_level_1, | ||
| Bool minify_css_level_2, | ||
| Bool minify_css_level_3, | ||
| Bool minify_js, | ||
| Bool remove_bangs, | ||
| Bool remove_processing_instructions, | ||
| ); | ||
|
|
||
| typedef get_last_result_native = Pointer<Utf8> Function(); | ||
|
|
||
| typedef clear_last_result_native = Void Function(); | ||
|
|
||
| class MinifyHtmlBindings { | ||
| late DynamicLibrary _library; | ||
|
|
||
| late int Function( | ||
| Pointer<Utf8> input, | ||
| int length, | ||
| bool do_not_minify_doctype, | ||
| bool ensure_spec_compliant_unquoted_attribute_values, | ||
| bool keep_closing_tags, | ||
| bool keep_html_and_head_opening_tags, | ||
| bool keep_spaces_between_attributes, | ||
| bool keep_comments, | ||
| bool minify_css, | ||
| bool minify_css_level_1, | ||
| bool minify_css_level_2, | ||
| bool minify_css_level_3, | ||
| bool minify_js, | ||
| bool remove_bangs, | ||
| bool remove_processing_instructions, | ||
| ) minifyHtml; | ||
|
|
||
| late Pointer<Utf8> Function() getLastResult; | ||
|
|
||
| late void Function() clearLastResult; | ||
|
|
||
| MinifyHtmlBindings() { | ||
| _library = loadDynamicLibrary(); | ||
|
|
||
| minifyHtml = _library | ||
| .lookup<NativeFunction<minify_html_native>>("minify_html") | ||
| .asFunction(); | ||
| getLastResult = _library | ||
| .lookup<NativeFunction<get_last_result_native>>("get_last_result") | ||
| .asFunction(); | ||
| clearLastResult = _library | ||
| .lookup<NativeFunction<clear_last_result_native>>("clear_last_result") | ||
| .asFunction(); | ||
| } | ||
| } | ||
|
|
||
| MinifyHtmlBindings? _cachedBindings; | ||
| MinifyHtmlBindings get bindings => _cachedBindings ??= MinifyHtmlBindings(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| import 'dart:ffi'; | ||
| import 'dart:io'; | ||
|
|
||
| /// Attempts to locate the MinifyHtml dynamic library. | ||
| /// | ||
| /// Throws [MinifyHtmlLocatorError] if the dynamic library could not be found. | ||
| DynamicLibrary loadDynamicLibrary() { | ||
| if (Platform.isIOS) { | ||
| return DynamicLibrary.process(); | ||
| } else if (Platform.isMacOS) { | ||
| return _locateOrError(appleLib); | ||
| } else if (Platform.isWindows) { | ||
| return _locate(windowsLib) ?? DynamicLibrary.executable(); | ||
| } else if (Platform.isLinux) { | ||
| return _locateOrError(linuxLib); | ||
| } else if (Platform.isAndroid) { | ||
| return DynamicLibrary.open(linuxLib); | ||
|
m-haisham marked this conversation as resolved.
|
||
| } else if (Platform.isFuchsia) { | ||
| throw MinifyHtmlLocatorError( | ||
| 'MinifyHtml is currently not supported on Fuchsia.', | ||
| ); | ||
| } else { | ||
| throw MinifyHtmlLocatorError( | ||
| 'MinifyHtml is currently not supported on this platform.', | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| /// This error is thrown when the dynamic library could not be found. | ||
| class MinifyHtmlLocatorError extends Error { | ||
| final String message; | ||
|
|
||
| MinifyHtmlLocatorError( | ||
| this.message, | ||
| ); | ||
|
|
||
| @override | ||
| String toString() => 'MinifyHtmlLocatorError: $message'; | ||
| } | ||
|
|
||
| /// The command that can be used to set up this package. | ||
| const invocationString = 'dart run minifyhtml:setup'; | ||
|
|
||
| /// The expected name of the MinifyHtml library when compiled for Apple devices. | ||
| const appleLib = 'libminifyhtml.dylib'; | ||
|
|
||
| /// The expected name of the MinifyHtml library when compiled for Linux devices. | ||
| const linuxLib = 'libminifyhtml.so'; | ||
|
|
||
| /// The expected name of the MinifyHtml library when compiled for Windows devices. | ||
| const windowsLib = 'minifyhtml.dll'; | ||
|
|
||
| const _minifyhtmlToolDir = '.dart_tool/minifyhtml/'; | ||
|
|
||
| DynamicLibrary? _locate(String libName) { | ||
| if (FileSystemEntity.isFileSync(libName)) { | ||
| return DynamicLibrary.open(libName); | ||
| } | ||
|
|
||
| final toolLib = | ||
| Directory.current.uri.resolve("$_minifyhtmlToolDir$libName").toFilePath(); | ||
| if (FileSystemEntity.isFileSync(toolLib)) { | ||
| return DynamicLibrary.open(toolLib); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| DynamicLibrary _locateOrError(String libName) { | ||
| final value = _locate(libName); | ||
| if (value != null) { | ||
| return value; | ||
| } else { | ||
| throw MinifyHtmlLocatorError('MinifyHtml library not found'); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import 'package:ffi/ffi.dart'; | ||
| import 'package:minify_html/src/bindings.dart'; | ||
| import 'package:minify_html/src/models.dart'; | ||
| import 'package:minify_html/src/resource.dart'; | ||
|
|
||
| String minifyHtml(String source, [Cfg? cfg]) { | ||
| cfg = cfg ??= Cfg(); | ||
|
|
||
| final srcC = Utf8Resource(source); | ||
|
|
||
| try { | ||
| final length = bindings.minifyHtml( | ||
| srcC.unsafe(), | ||
| srcC.length, | ||
| cfg.doNotMinifyDoctype, | ||
| cfg.ensureSpecCompliantUnquotedAttributeValues, | ||
| cfg.keepClosingTags, | ||
| cfg.keepHtmlAndHeadOpeningTags, | ||
| cfg.keepSpacesBetweenAttributes, | ||
| cfg.keepComments, | ||
| cfg.minifyCss, | ||
| cfg.minifyCssLevel1, | ||
| cfg.minifyCssLevel2, | ||
| cfg.minifyCssLevel3, | ||
| cfg.minifyJs, | ||
| cfg.removeBangs, | ||
| cfg.removeProcessingInstructions, | ||
| ); | ||
|
|
||
| final value = bindings.getLastResult().toDartString(length: length); | ||
| bindings.clearLastResult(); | ||
|
|
||
| return value; | ||
| } finally { | ||
| srcC.free(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| class Cfg { | ||
| const Cfg({ | ||
| this.doNotMinifyDoctype = false, | ||
| this.ensureSpecCompliantUnquotedAttributeValues = false, | ||
| this.keepClosingTags = false, | ||
| this.keepHtmlAndHeadOpeningTags = false, | ||
| this.keepSpacesBetweenAttributes = false, | ||
| this.keepComments = false, | ||
| this.minifyCss = false, | ||
| this.minifyCssLevel1 = false, | ||
| this.minifyCssLevel2 = false, | ||
| this.minifyCssLevel3 = false, | ||
| this.minifyJs = false, | ||
| this.removeBangs = false, | ||
| this.removeProcessingInstructions = false, | ||
| }); | ||
|
|
||
| const Cfg.specCompliant() | ||
| : this( | ||
| doNotMinifyDoctype: true, | ||
| ensureSpecCompliantUnquotedAttributeValues: true, | ||
| keepSpacesBetweenAttributes: true, | ||
| ); | ||
|
|
||
| final bool doNotMinifyDoctype; | ||
| final bool ensureSpecCompliantUnquotedAttributeValues; | ||
| final bool keepClosingTags; | ||
| final bool keepHtmlAndHeadOpeningTags; | ||
| final bool keepSpacesBetweenAttributes; | ||
| final bool keepComments; | ||
| final bool minifyCss; | ||
| final bool minifyCssLevel1; | ||
| final bool minifyCssLevel2; | ||
| final bool minifyCssLevel3; | ||
| final bool minifyJs; | ||
| final bool removeBangs; | ||
| final bool removeProcessingInstructions; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import 'dart:convert'; | ||
| import 'dart:ffi'; | ||
| import 'dart:typed_data'; | ||
|
|
||
| import 'package:ffi/ffi.dart'; | ||
|
|
||
| final DynamicLibrary stdlib = DynamicLibrary.process(); | ||
| final posixFree = stdlib.lookup<NativeFunction<Void Function(Pointer)>>("free"); | ||
|
|
||
| class Utf8Resource implements Finalizable { | ||
| static final NativeFinalizer _finalizer = NativeFinalizer(posixFree); | ||
|
|
||
| /// [_cString] must never escape [Utf8Resource], otherwise the | ||
| /// [_finalizer] will run prematurely. | ||
| late final Pointer<Utf8> _cString; | ||
| late final int length; | ||
|
|
||
| Utf8Resource(String source) { | ||
| final units = utf8.encode(source); | ||
| length = units.length; | ||
|
|
||
| final Pointer<Uint8> result = malloc<Uint8>(units.length); | ||
| final Uint8List nativeString = result.asTypedList(units.length); | ||
| nativeString.setAll(0, units); | ||
| _cString = result.cast(); | ||
|
|
||
| _finalizer.attach(this, _cString.cast(), detach: this); | ||
| } | ||
|
|
||
| void free() { | ||
| _finalizer.detach(this); | ||
| calloc.free(_cString); | ||
| } | ||
|
|
||
| /// Ensure this [Utf8Resource] stays in scope longer than the inner resource. | ||
| Pointer<Utf8> unsafe() => _cString; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| /target | ||
| Cargo.lock |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| [package] | ||
| name = "minify-html-native" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
|
|
||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
| [lib] | ||
| name = "minifyhtml" | ||
| crate-type = ["cdylib"] | ||
|
|
||
| [dependencies] | ||
| minify-html = { version = "0.10.8", path = "../../rust/main" } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| use std::{cell::RefCell, ptr, slice}; | ||
|
|
||
| use minify_html::Cfg; | ||
|
|
||
| thread_local! { | ||
| static LAST_RESULT: RefCell<Option<Vec<u8>>> = RefCell::new(None); | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub extern "C" fn minify_html( | ||
| input: *const u8, | ||
| length: usize, | ||
| do_not_minify_doctype: bool, | ||
| ensure_spec_compliant_unquoted_attribute_values: bool, | ||
| keep_closing_tags: bool, | ||
| keep_html_and_head_opening_tags: bool, | ||
| keep_spaces_between_attributes: bool, | ||
| keep_comments: bool, | ||
| minify_css: bool, | ||
| minify_css_level_1: bool, | ||
| minify_css_level_2: bool, | ||
| minify_css_level_3: bool, | ||
| minify_js: bool, | ||
| remove_bangs: bool, | ||
| remove_processing_instructions: bool, | ||
| ) -> usize { | ||
| let src = unsafe { slice::from_raw_parts(input, length) }; | ||
|
|
||
| let cfg = Cfg { | ||
| do_not_minify_doctype, | ||
| ensure_spec_compliant_unquoted_attribute_values, | ||
| keep_closing_tags, | ||
| keep_html_and_head_opening_tags, | ||
| keep_spaces_between_attributes, | ||
| keep_comments, | ||
| minify_css, | ||
| minify_css_level_1, | ||
| minify_css_level_2, | ||
| minify_css_level_3, | ||
| minify_js, | ||
| remove_bangs, | ||
| remove_processing_instructions, | ||
| }; | ||
|
|
||
| let result = minify_html::minify(src, &cfg); | ||
| let len = result.len(); | ||
|
|
||
| LAST_RESULT.with(|v| *v.borrow_mut() = Some(result)); | ||
| len | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub extern "C" fn get_last_result() -> *const u8 { | ||
| LAST_RESULT.with(|prev| match prev.borrow().as_ref() { | ||
| Some(bytes) => bytes.as_ptr(), | ||
| None => return ptr::null(), | ||
| }) | ||
| } | ||
|
|
||
| #[no_mangle] | ||
| pub extern "C" fn clear_last_result() { | ||
| LAST_RESULT.with(|value| *value.borrow_mut() = None) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.