From cfe513ed068f907dad1519e0bdd8dbe5520022ee Mon Sep 17 00:00:00 2001
From: Gornytskyi Maxim <50423072+MaxymGorn@users.noreply.github.com>
Date: Sun, 4 Aug 2024 14:37:21 +0300
Subject: [PATCH] Feature/update NuGet to 1.3.3v (#357)
## Update NuGet to 1.3.3v
## Checklist
- [x] Tests cover new or modified code
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the site documentation
- [x] I have made corresponding changes to the README, NuGet README file
- [x] My changes generate no new warnings
- [x] New dependencies added or updated
- [ ] Includes breaking changes
- [x] Version bumped
---------
Co-authored-by: ColdForeign
Co-authored-by: George Radchuk <38187349+ColdForeign@users.noreply.github.com>
Co-authored-by: Xander Van Boom <49340095+C0lpy@users.noreply.github.com>
---
.editorconfig | 102 ++++
.gitattributes | 8 +
.github/PULL_REQUEST_TEMPLATE.md | 6 +-
.github/dependabot.yml | 4 +
.github/linters/.checkov.yaml | 3 +
.github/linters/.jscpd.json | 10 +-
.github/linters/.stylelintrc.json | 18 +-
.github/workflows/build-test-template.yml | 61 ++
.github/workflows/cd.yml | 215 +++----
.github/workflows/ci.yml | 99 ++-
.github/workflows/dependabot-ci.yml | 17 +
.github/workflows/release.yml | 69 +--
NuGet_README.md | 2 +-
README.md | 2 +-
.../Cropper.Blazor.MAUI.Net7.csproj | 2 +-
.../Components/Layout/MainLayout.razor | 1 +
.../Components/Pages/Home.razor.cs | 2 +-
.../Cropper.Blazor.MAUI.Net8.csproj | 8 +-
.../Cropper.Blazor.Server.Net6.csproj | 2 +-
.../Cropper.Blazor.Server.Net7.csproj | 2 +-
.../Cropper.Blazor.Server.Net8.csproj | 2 +-
.../Pages/Index.razor.cs | 2 +-
.../Shared/MainLayout.razor | 1 +
.../Cropper.Blazor.WebView.Net6.csproj | 4 +-
...Cropper.MVC.With.Blazor.Server.Net7.csproj | 2 +-
.../Client/.config/dotnet-tools.json | 2 +-
.../Components/AspectRatioSettings.razor.cs | 2 +-
.../Components/CropperDataPreview.razor.cs | 2 +-
.../Client/Components/Docs/ApiLink.cs | 22 +-
.../Client/Components/Docs/DocsApi.razor | 44 +-
.../Client/Components/Docs/DocsApi.razor.cs | 6 +-
.../Client/Components/Docs/DocsTypeInfo.razor | 2 +-
.../Components/Docs/SectionContent.razor.cs | 32 +-
.../Client/Cropper.Blazor.Client.csproj | 14 +-
.../Examples/CropPolygonImage_ScriptCode.html | 52 +-
.../Examples/CropRoundImage_ScriptCode.html | 40 +-
.../Examples/MinMaxZoomRatio_ScriptCode.html | 4 +-
.../Client/Pages/CropperDemo.razor.cs | 2 +-
.../Client/Pages/CropperDemo.razor.css | 2 +-
.../Client/Pages/DataContract.razor | 1 +
.../InstallationManualCssFontsExample.razor | 2 +-
src/Cropper.Blazor/Client/Pages/Index.razor | 2 +-
.../InstallScriptManualCode.html | 6 +-
...tallServicesForBlazorServerManualCode.html | 18 +-
.../InstallServicesManualCode.html | 8 +-
.../InstallServicesOverrideGlobalCode.html | 6 +-
.../InstallServicesOverrideInternalCode.html | 4 +-
...cInputReplaceImageWithNewSizeExample.razor | 7 +
...InputReplaceImageWithSameSizeExample.razor | 7 +
.../BasicReplaceImageWithNewSizeExample.razor | 7 +
...BasicReplaceImageWithSameSizeExample.razor | 7 +
src/Cropper.Blazor/Client/Program.cs | 2 +-
.../Client/Services/MenuService.cs | 1 +
.../Client/Shared/AppbarButtons.razor.cs | 2 +-
.../Shared/CroppedCanvasDialog.razor.cs | 4 +-
.../Client/Shared/DocsLayout.razor.cs | 2 +-
.../Client/Shared/SeoHeader.razor.cs | 21 +-
.../Shared/Utilities/CropperBlazorLogo.razor | 50 +-
.../Client/Styles/Cropper.Blazor.Client.scss | 27 +-
.../Client/Styles/components/docspage.scss | 10 +-
.../Client/Styles/components/docssection.scss | 32 -
.../{_mainlayout.scss => mainlayout.scss} | 10 +-
.../layout/{_markdown.scss => markdown.scss} | 56 +-
...tector.scss => updateAvaibleDetector.scss} | 0
src/Cropper.Blazor/Client/wwwroot/helper.js | 94 +--
src/Cropper.Blazor/Client/wwwroot/index.html | 110 ++--
.../Client/wwwroot/jsObjectModule.js | 47 +-
.../wwwroot/overrideCropperJsInteropModule.js | 27 +-
.../wwwroot/resizeWindowEventListener.js | 34 +-
.../Client/wwwroot/service-worker.js | 2 +-
.../wwwroot/service-worker.published.js | 116 ++--
.../Client/wwwroot/sw-registrator.js | 52 +-
.../CodeSnippetsCompiler.cs | 12 +-
.../Cropper.Blazor.Client.Compiler.csproj | 11 +-
.../DocStrings.cs | 20 +-
.../ExamplesMarkup.cs | 62 +-
.../Cropper.Blazor.Client.Compiler/Paths.cs | 42 +-
.../Cropper.Blazor.Client.Compiler/Program.cs | 6 +-
.../StyleDictionary.KebabCase.cs | 53 ++
.../Cropper.Blazor.Shared.csproj | 16 +-
.../Extensions/MethodInfoExtensions.cs | 25 +-
.../Extensions/TypeNameHelper.cs | 4 +-
.../Extensions/XmlDocumentationExtension.cs | 6 +-
.../Cropper.Blazor.Sitemap.Generator.csproj | 18 +-
.../Components/CropperComponent_Should.cs | 474 ++++++++++++++-
.../Cropper.Blazor.UnitTests.csproj | 40 +-
.../Services/CropperJsInterop_Should.cs | 2 +-
src/Cropper.Blazor/Cropper.Blazor.sln | 5 +
.../Cropper.Blazor/.config/dotnet-tools.json | 2 +-
.../Components/CropperComponent.razor | 39 +-
.../Components/CropperComponent.razor.cs | 59 +-
.../Cropper.Blazor/Cropper.Blazor.csproj | 8 +-
.../Models/CropperComponentType.cs | 22 +
.../Models/GetCroppedCanvasOptions.cs | 2 +-
.../Services/CropperJsInterop.cs | 2 +-
.../Services/ICropperJsInterop.cs | 2 +-
.../Cropper.Blazor/wwwroot/cropper.min.js | 6 +-
.../wwwroot/cropperJsInterop.js | 568 +++++++++---------
.../Server/Cropper.Blazor.Server.csproj | 3 +-
.../Server/Pages/Error.cshtml.cs | 2 +-
100 files changed, 1939 insertions(+), 1216 deletions(-)
create mode 100644 .editorconfig
create mode 100644 .gitattributes
create mode 100644 .github/linters/.checkov.yaml
create mode 100644 .github/workflows/build-test-template.yml
create mode 100644 .github/workflows/dependabot-ci.yml
rename src/Cropper.Blazor/Client/Styles/layout/{_mainlayout.scss => mainlayout.scss} (87%)
rename src/Cropper.Blazor/Client/Styles/layout/{_markdown.scss => markdown.scss} (80%)
rename src/Cropper.Blazor/Client/Styles/layout/{_updateAvaibleDetector.scss => updateAvaibleDetector.scss} (100%)
create mode 100644 src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/StyleDictionary.KebabCase.cs
create mode 100644 src/Cropper.Blazor/Cropper.Blazor/Models/CropperComponentType.cs
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..53536631
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,102 @@
+root = true
+
+# All files
+[*]
+indent_style = space
+csharp_indent_labels = no_change
+csharp_using_directive_placement = outside_namespace:silent
+csharp_prefer_simple_using_statement = true:suggestion
+csharp_prefer_braces = true:silent
+csharp_style_namespace_declarations = block_scoped:silent
+csharp_style_prefer_method_group_conversion = true:silent
+csharp_style_prefer_top_level_statements = true:silent
+csharp_style_prefer_primary_constructors = true:suggestion
+csharp_style_expression_bodied_methods = false:silent
+csharp_style_expression_bodied_constructors = false:silent
+csharp_style_expression_bodied_operators = false:silent
+csharp_style_expression_bodied_properties = true:silent
+csharp_style_expression_bodied_indexers = true:silent
+csharp_style_expression_bodied_accessors = true:silent
+csharp_style_expression_bodied_lambdas = true:silent
+csharp_style_expression_bodied_local_functions = false:silent
+
+[*.{csproj,sln,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
+indent_size = 4
+tab_width = 4
+indent_style = tab
+
+# Xml build files
+[*.builds]
+indent_size = 2
+
+# Xml files
+[*.{xml,stylecop,resx,ruleset}]
+indent_size = 2
+
+# Xml config files
+[*.{props,targets,config,nuspec}]
+indent_size = 2
+
+# YML files
+[*.yml]
+indent_size = 2
+indent_style = space
+
+[*.{cs,vb}]
+#### Naming styles ####
+
+# Naming rules
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# Symbol specifications
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# Naming styles
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+tab_width = 4
+indent_size = 4
+end_of_line = crlf
+dotnet_style_coalesce_expression = true:suggestion
+insert_final_newline = true
+
+[*.html]
+tab_width = 4
+indent_size = 4
+indent_style = tab
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..f52991a3
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,8 @@
+* text=auto eol=crlf
+
+# Declare files that will always have LF line endings on checkout.
+*.sh text eol=lf
+
+# Don't check these into the repo as LF to work around TeamCity bug
+*.xml -text
+*.targets -text
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 6f792f92..853d37b3 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -12,13 +12,13 @@
-- [ ] Documentation updated
- [ ] Tests cover new or modified code
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
-- [ ] I have made corresponding changes to the documentation
+- [ ] I have made corresponding changes to the site documentation
+- [ ] I have made corresponding changes to the README, NuGet README file
- [ ] My changes generate no new warnings
-- [ ] New dependencies added
+- [ ] New dependencies added or updated
- [ ] Includes breaking changes
- [ ] Version bumped
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 0089655d..62f7c776 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -5,3 +5,7 @@ updates:
target-branch: "dev" # Location of package manifests
schedule:
interval: "monthly"
+ groups:
+ dotnet:
+ patterns:
+ - "*"
diff --git a/.github/linters/.checkov.yaml b/.github/linters/.checkov.yaml
new file mode 100644
index 00000000..85a09f4e
--- /dev/null
+++ b/.github/linters/.checkov.yaml
@@ -0,0 +1,3 @@
+quiet: true
+skip-check:
+ - CKV2_GHA_1
diff --git a/.github/linters/.jscpd.json b/.github/linters/.jscpd.json
index e8fd3bc5..9f757df0 100644
--- a/.github/linters/.jscpd.json
+++ b/.github/linters/.jscpd.json
@@ -4,7 +4,11 @@
"consoleFull"
],
"ignore": [
- "**/src/Cropper.Blazor/Cropper.Blazor.UnitTests/**"
+ "**/src/Cropper.Blazor/Cropper.Blazor.UnitTests/**",
+ "**/examples/**",
+ "**/*.md",
+ "**/*excubowebcompiler.json"
],
- "absolute": true
-}
\ No newline at end of file
+ "absolute": true,
+ "minTokens": 75
+}
diff --git a/.github/linters/.stylelintrc.json b/.github/linters/.stylelintrc.json
index f866bd1d..0d0e2cd0 100644
--- a/.github/linters/.stylelintrc.json
+++ b/.github/linters/.stylelintrc.json
@@ -1,12 +1,12 @@
{
- "extends": "stylelint-config-standard",
+ "extends": [ "stylelint-config-standard", "stylelint-config-standard-scss" ],
"rules": {
- "at-rule-no-unknown": [true, {
- "ignoreAtRules": ["function", "if", "each", "include", "mixin"]
- }],
- "selector-list-comma-newline-after": "always-multi-line",
- "selector-list-comma-newline-before": "never-multi-line",
- "block-closing-brace-newline-before": "always",
+ "at-rule-no-unknown": [
+ true,
+ {
+ "ignoreAtRules": [ "function", "if", "each", "include", "mixin" ]
+ }
+ ],
"selector-pseudo-class-no-unknown": [
true,
{
@@ -19,6 +19,6 @@
"ignorePseudoElements": [ "deep" ]
}
],
- "indentation": 4
+ "media-feature-range-notation": "prefix"
}
-}
\ No newline at end of file
+}
diff --git a/.github/workflows/build-test-template.yml b/.github/workflows/build-test-template.yml
new file mode 100644
index 00000000..79d7dadd
--- /dev/null
+++ b/.github/workflows/build-test-template.yml
@@ -0,0 +1,61 @@
+name: Build and run tests
+
+on:
+ workflow_call:
+ inputs:
+ configuration:
+ description: 'dotnet build configuration'
+ required: false
+ type: string
+ default: 'Debug'
+ publish-coverage:
+ description: 'publish coverage to codecov'
+ required: false
+ type: boolean
+ default: true
+
+jobs:
+ build_and_test:
+ name: Build & Test
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup .NET 8, 7, 6
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 6.0.x
+ 7.0.x
+ 8.0.x
+
+ - name: Install WASM tools Workloads
+ run: |
+ dotnet workload install wasm-tools --ignore-failed-sources
+
+ - name: Restore dependencies
+ run: dotnet restore
+ working-directory: src/Cropper.Blazor
+
+ - name: Restore dotnet tool
+ run: dotnet tool restore
+ working-directory: src/Cropper.Blazor/Cropper.Blazor
+
+ - name: DotNet Build
+ run: dotnet build -c ${{ inputs.configuration }} --no-restore
+ working-directory: src/Cropper.Blazor
+
+ - name: Test
+ run: dotnet test -c ${{ inputs.configuration }} --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:ExcludeByAttribute='ExcludeFromCodeCoverage' /p:SkipAutoProps=true /p:Exclude="[*]Cropper.Blazor.Testing.*"
+ working-directory: src/Cropper.Blazor/Cropper.Blazor.UnitTests
+
+ - name: Coverage
+ if: ${{ inputs.publish-coverage == true }}
+ uses: codecov/codecov-action@v4
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ files: coverage.net6.0.cobertura.xml, coverage.net7.0.cobertura.xml, coverage.net8.0.cobertura.xml
+ fail_ci_if_error: true
+ verbose: true
diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml
index 8a3b7c5f..0e6c1cc0 100644
--- a/.github/workflows/cd.yml
+++ b/.github/workflows/cd.yml
@@ -4,7 +4,6 @@ concurrency:
group: github-pages
cancel-in-progress: true
-# Run workflow on every push to the master branch
on:
push:
branches: [ dev ]
@@ -12,138 +11,114 @@ on:
- '**.md'
jobs:
+ code-quality-check:
+ name: Check code quality
+ uses: CropperBlazor/Cropper.Blazor/.github/workflows/build-test-template.yml@dev
+ secrets: inherit
+
deploy-to-github-pages:
- # use ubuntu-latest image to run steps on
runs-on: ubuntu-latest
environment: github-pages
- needs: demo-projects-build
+ needs: [code-quality-check, demo-projects-build]
steps:
- # uses GitHub's checkout action to checkout code form the master branch
- - uses: actions/checkout@v3
-
- # sets up .NET Core SDK 8, 7, 6
- - name: Setup .NET 8, 7, 6
- uses: actions/setup-dotnet@v3
- with:
- dotnet-version: |
- 6.0.x
- 7.0.x
- 8.0.x
-
- - name: Install WASM tools Workloads
- run: |
- dotnet workload install wasm-tools --ignore-failed-sources
-
- - name: Restore dependencies
- run: dotnet restore
- working-directory: src/Cropper.Blazor
-
- - name: Restore dotnet tool
- run: dotnet tool restore
- working-directory: src/Cropper.Blazor/Cropper.Blazor
-
- - name: Build
- run: dotnet build --no-restore
- working-directory: src/Cropper.Blazor
-
- - name: Test
- run: dotnet test --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:ExcludeByAttribute='ExcludeFromCodeCoverage' /p:SkipAutoProps=true /p:Exclude="[*]Cropper.Blazor.Testing.*"
- working-directory: src/Cropper.Blazor/Cropper.Blazor.UnitTests
-
- - name: Coverage
- uses: codecov/codecov-action@v3.1.4
- with:
- files: coverage.net6.0.cobertura.xml, coverage.net7.0.cobertura.xml, coverage.net8.0.cobertura.xml
- fail_ci_if_error: true
- verbose: true
-
- - name: Wait for Exit Code 1 for Cropper.Blazor.Sitemap.Generator project
- run: |
- dotnet run -c Release
- working-directory: src/Cropper.Blazor/Cropper.Blazor.Sitemap.Generator
-
- - name: Check if sitemap.xml File Exists
- run: |
- filePath="./sitemap.xml"
- if [ -f "$filePath" ]; then
- echo "sitemap.xml file exists"
- else
- echo "File does not exist"
- exit 1
- fi
- working-directory: src/Cropper.Blazor/Client/wwwroot
-
- # publishes Blazor project to the release-folder
- - name: Publish .NET Core Project
- run: dotnet publish ./src/Cropper.Blazor/Client/Cropper.Blazor.Client.csproj -c Release --output release --nologo
-
- # changes the base-tag in index.html from '/' to 'Cropper.Blazor' to match GitHub Pages repository subdirectory
- #- name: Change base-tag in index.html from / to Cropper.Blazor
- # run: sed -i 's///g' release/wwwroot/index.html
-
- - name: Fix service-worker-assets.js hashes
- working-directory: release/wwwroot
- run: |
- jsFile=$( service-worker-assets.js
-
- # copy index.html to 404.html to serve the same file when a file is not found
- - name: copy index.html to 404.html
- run: cp release/wwwroot/index.html release/wwwroot/404.html
-
- # add .nojekyll file to tell GitHub pages to not treat this as a Jekyll project. (Allow files and folders starting with an underscore)
- - name: Add .nojekyll file
- run: touch release/wwwroot/.nojekyll
-
- - name: Uploading files to gh-pages branch
- uses: JamesIves/github-pages-deploy-action@v4.4.0
- with:
- token: ${{ secrets.DEPLOY_KEY }}
- branch: gh-pages
- folder: release/wwwroot
- repository-name: CropperBlazor/CropperBlazor.github.io
+ working-directory: src/Cropper.Blazor/Client/wwwroot
+
+ # publishes Blazor project to the release-folder
+ - name: Publish .NET Core Project
+ run: dotnet publish ./src/Cropper.Blazor/Client/Cropper.Blazor.Client.csproj -c Release --output release --nologo
+
+ # changes the base-tag in index.html from '/' to 'Cropper.Blazor' to match GitHub Pages repository subdirectory
+ #- name: Change base-tag in index.html from / to Cropper.Blazor
+ # run: sed -i 's///g' release/wwwroot/index.html
+
+ - name: Fix service-worker-assets.js hashes
+ working-directory: release/wwwroot
+ run: |
+ jsFile=$( service-worker-assets.js
+
+ # copy index.html to 404.html to serve the same file when a file is not found
+ - name: copy index.html to 404.html
+ run: cp release/wwwroot/index.html release/wwwroot/404.html
+
+ # add .nojekyll file to tell GitHub pages to not treat this as a Jekyll project. (Allow files and folders starting with an underscore)
+ - name: Add .nojekyll file
+ run: touch release/wwwroot/.nojekyll
+
+ - name: Uploading files to gh-pages branch
+ uses: JamesIves/github-pages-deploy-action@v4.4.0
+ with:
+ token: ${{ secrets.DEPLOY_KEY }}
+ branch: gh-pages
+ folder: release/wwwroot
+ repository-name: CropperBlazor/CropperBlazor.github.io
demo-projects-build:
name: Build Demo Projects
runs-on: windows-latest
+ needs: code-quality-check
env:
JAVA_HOME: '/home/runner/android-sdk'
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v4
- # sets up .NET Core SDK 8, 7, 6
- name: Setup .NET 8, 7, 6
- uses: actions/setup-dotnet@v3.2.0
+ uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
@@ -152,7 +127,7 @@ jobs:
- name: Cache JDK
id: cache-jdk
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ${{ env.JAVA_HOME }}
key: ${{ runner.os }}-jdk-11
@@ -161,7 +136,7 @@ jobs:
- name: Setup Java JDK
if: steps.cache-jdk.outputs.cache-hit != 'true'
- uses: actions/setup-java@v3.13.0
+ uses: actions/setup-java@v4
with:
distribution: 'microsoft'
java-version: 11
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 09b60040..06c3edec 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,76 +1,45 @@
-name: Build and run tests
+name: Build, run tests, code linting
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
on:
- push:
- branches:
- - fix/*
- - feature/*
pull_request:
- branches:
- - fix/*
- - feature/*
+ branches-ignore:
+ - master
+ - dependabot/*
jobs:
- build:
- name: Build & Test
- runs-on: ubuntu-latest
+ code-quality-check:
+ name: Check code quality
+ uses: CropperBlazor/Cropper.Blazor/.github/workflows/build-test-template.yml@dev
+ secrets: inherit
+ code-linting:
+ name: Code linting
+ runs-on: ubuntu-latest
+ needs: code-quality-check
steps:
- - uses: actions/checkout@v3
-
- # sets up .NET Core SDK 8, 7, 6
- - name: Setup .NET 8, 7, 6
- uses: actions/setup-dotnet@v3.2.0
- with:
- dotnet-version: |
- 6.0.x
- 7.0.x
- 8.0.x
-
- - name: Install WASM tools Workloads
- run: |
- dotnet workload install wasm-tools --ignore-failed-sources
-
- - name: Restore dependencies
- run: dotnet restore
- working-directory: src/Cropper.Blazor
-
- - name: Restore dotnet tool
- run: dotnet tool restore
- working-directory: src/Cropper.Blazor/Cropper.Blazor
-
- - name: DotNet Build
- run: dotnet build --no-restore
- working-directory: src/Cropper.Blazor
-
- - name: Test
- run: dotnet test --no-build --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:ExcludeByAttribute='ExcludeFromCodeCoverage' /p:SkipAutoProps=true /p:Exclude="[*]Cropper.Blazor.Testing.*"
- working-directory: src/Cropper.Blazor/Cropper.Blazor.UnitTests
-
- - name: Coverage
- uses: codecov/codecov-action@v3.1.4
- with:
- files: coverage.net6.0.cobertura.xml, coverage.net7.0.cobertura.xml, coverage.net8.0.cobertura.xml
- fail_ci_if_error: true
- verbose: true
-
- - name: Super-Linter
- uses: github/super-linter@v4.8.1
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- OUTPUT_FOLDER: Reports
- OUTPUT_DETAILS: detailed
- ERROR_ON_MISSING_EXEC_BIT: true
- VALIDATE_ALL_CODEBASE: true
- VALIDATE_MARKDOWN: false
- VALIDATE_JAVASCRIPT_STANDARD: false
- LOG_LEVEL: WARN
- FILTER_REGEX_EXCLUDE: '(\W|^)(.*([.]min[.]css))($)|(\W|^)(.*([.]min[.]js))($)'
- FILTER_REGEX_INCLUDE: /github/workspace/src/Cropper.Blazor/.*
- JSCPD_CONFIG_FILE: '.jscpd.json'
- HTML_FILE_NAME: '.htmlhintrc'
- CSS_FILE_NAME: '.stylelintrc.json'
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ # super-linter needs the full git history to get the
+ # list of files that changed across commits
+ fetch-depth: 0
+
+ - name: Super-Linter
+ uses: super-linter/super-linter@v6.8.0
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ OUTPUT_FOLDER: Reports
+ OUTPUT_DETAILS: detailed
+ VALIDATE_ALL_CODEBASE: true
+ VALIDATE_MARKDOWN: false
+ VALIDATE_JAVASCRIPT_PRETTIER: false
+ LOG_LEVEL: WARN
+ FILTER_REGEX_EXCLUDE: '(\W|^)(.*([.]min[.]css))($)|(\W|^)(.*([.]min[.]js))($)'
+ FILTER_REGEX_INCLUDE: /github/workspace/src/Cropper.Blazor/.*
+ JSCPD_CONFIG_FILE: '.jscpd.json'
+ HTML_FILE_NAME: '.htmlhintrc'
+ CSS_FILE_NAME: '.stylelintrc.json'
diff --git a/.github/workflows/dependabot-ci.yml b/.github/workflows/dependabot-ci.yml
new file mode 100644
index 00000000..00764677
--- /dev/null
+++ b/.github/workflows/dependabot-ci.yml
@@ -0,0 +1,17 @@
+name: Build & Test
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+ cancel-in-progress: true
+
+on:
+ push:
+ branches:
+ - dependabot/*
+
+jobs:
+ build-and-test:
+ name: Build & Test
+ uses: CropperBlazor/Cropper.Blazor/.github/workflows/build-test-template.yml@dev
+ with:
+ publish-coverage: false
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index aef79afa..676b2b00 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,61 +1,38 @@
name: Deploy to NuGet
-# Run workflow on every push to the master branch
on:
push:
branches:
- master
jobs:
- deploy-to-nuget:
+ build-and-test:
+ name: Build & Test
+ uses: CropperBlazor/Cropper.Blazor/.github/workflows/build-test-template.yml@dev
+ secrets: inherit
+ with:
+ configuration: 'Release'
+ publish-coverage: true
- # use ubuntu-latest image to run steps on
+ deploy-to-nuget:
+ name: Deploy to NuGet
runs-on: ubuntu-latest
+ needs: build-and-test
steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
- # uses GitHub's checkout action to checkout code form the master branch
- - uses: actions/checkout@v3
-
- # sets up .NET Core SDK 8, 7, 6
- - name: Setup .NET 8, 7, 6
- uses: actions/setup-dotnet@v3.2.0
- with:
- dotnet-version: |
- 6.0.x
- 7.0.x
- 8.0.x
-
- - name: Install WASM tools Workloads
- run: |
- dotnet workload install wasm-tools --ignore-failed-sources
-
- - name: Restore dependencies
- run: dotnet restore
- working-directory: src/Cropper.Blazor
-
- - name: Restore dotnet tool
- run: dotnet tool restore
- working-directory: src/Cropper.Blazor/Cropper.Blazor
-
- - name: Build
- run: dotnet build -c Release --no-restore
- working-directory: src/Cropper.Blazor
-
- - name: Test
- run: dotnet test -c Release --no-build --no-restore --verbosity normal /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:ExcludeByAttribute='ExcludeFromCodeCoverage' /p:SkipAutoProps=true /p:Exclude="[*]Cropper.Blazor.Testing.*"
- working-directory: src/Cropper.Blazor/Cropper.Blazor.UnitTests
-
- - name: Pack package
- run: dotnet pack -c Release
- working-directory: src/Cropper.Blazor/Cropper.Blazor
+ - name: Pack package
+ run: dotnet pack -c Release
+ working-directory: src/Cropper.Blazor/Cropper.Blazor
- - name: Push to NuGet Gallery
- run: dotnet nuget push bin/Release/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.NUGET_API_KEY}} --skip-duplicate
- working-directory: src/Cropper.Blazor/Cropper.Blazor
+ - name: Push to NuGet Gallery
+ run: dotnet nuget push bin/Release/*.nupkg --source "https://api.nuget.org/v3/index.json" --api-key ${{secrets.NUGET_API_KEY}} --skip-duplicate
+ working-directory: src/Cropper.Blazor/Cropper.Blazor
- - name: Add NuGet repository source
- run: dotnet nuget add source --username CropperBlazor --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/CropperBlazor/index.json"
+ - name: Add NuGet repository source
+ run: dotnet nuget add source --username CropperBlazor --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text --name github "https://nuget.pkg.github.com/CropperBlazor/index.json"
- - name: Publish NuGet package to GitHub packages
- run: dotnet nuget push bin/Release/*.nupkg --api-key ${{ secrets.GITHUB_TOKEN }} --source "github" --skip-duplicate
- working-directory: src/Cropper.Blazor/Cropper.Blazor
+ - name: Publish NuGet package to GitHub packages
+ run: dotnet nuget push bin/Release/*.nupkg --api-key ${{ secrets.GITHUB_TOKEN }} --source "github" --skip-duplicate
+ working-directory: src/Cropper.Blazor/Cropper.Blazor
diff --git a/NuGet_README.md b/NuGet_README.md
index 59d79fc9..f82d9c85 100644
--- a/NuGet_README.md
+++ b/NuGet_README.md
@@ -1,4 +1,4 @@
-## Cropper.Blazor is a component that wraps around Cropper.js version 1.6.1
+## Cropper.Blazor is a component that wraps around Cropper.js version 1.6.2
[![Build and run test](https://github.com/CropperBlazor/Cropper.Blazor/actions/workflows/ci.yml/badge.svg?event=push)](https://github.com/CropperBlazor/Cropper.Blazor/actions/workflows/ci.yml)
[![Deploy to GitHub Pages](https://github.com/CropperBlazor/Cropper.Blazor/actions/workflows/cd.yml/badge.svg?event=push)](https://github.com/CropperBlazor/Cropper.Blazor/actions/workflows/cd.yml)
diff --git a/README.md b/README.md
index 9a66d16f..dafe1769 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
Cropper.Blazor
- Cropper.Blazor is a component that wraps around Cropper.js version 1.6.1
+ Cropper.Blazor is a component that wraps around Cropper.js version 1.6.2
diff --git a/examples/Cropper.Blazor.MAUI.Net7/Cropper.Blazor.MAUI.Net7.csproj b/examples/Cropper.Blazor.MAUI.Net7/Cropper.Blazor.MAUI.Net7.csproj
index 7c673f4f..c0a175ea 100644
--- a/examples/Cropper.Blazor.MAUI.Net7/Cropper.Blazor.MAUI.Net7.csproj
+++ b/examples/Cropper.Blazor.MAUI.Net7/Cropper.Blazor.MAUI.Net7.csproj
@@ -52,7 +52,7 @@
-
+
diff --git a/examples/Cropper.Blazor.MAUI.Net8/Components/Layout/MainLayout.razor b/examples/Cropper.Blazor.MAUI.Net8/Components/Layout/MainLayout.razor
index ef644faa..f7dbbc34 100644
--- a/examples/Cropper.Blazor.MAUI.Net8/Components/Layout/MainLayout.razor
+++ b/examples/Cropper.Blazor.MAUI.Net8/Components/Layout/MainLayout.razor
@@ -3,6 +3,7 @@
+
diff --git a/src/Cropper.Blazor/Client/Pages/ManualMarkdown/InstallServicesOverrideInternalCode.html b/src/Cropper.Blazor/Client/Pages/ManualMarkdown/InstallServicesOverrideInternalCode.html
index fc50fc6e..56f136c4 100644
--- a/src/Cropper.Blazor/Client/Pages/ManualMarkdown/InstallServicesOverrideInternalCode.html
+++ b/src/Cropper.Blazor/Client/Pages/ManualMarkdown/InstallServicesOverrideInternalCode.html
@@ -4,9 +4,9 @@
using Cropper.Blazor.Extensions;
-
builder.Services.
AddCropper(
new CropperJsInteropOptions()
+
builder.Services.
AddCropper(
new CropperJsInteropOptions()
{
- DefaultInternalPathToCropperModule =
"{YourPath}/_content/Cropper.Blazor/cropperJsInterop.min.js"
+ DefaultInternalPathToCropperModule =
"{YourPath}/_content/Cropper.Blazor/cropperJsInterop.min.js"
});
diff --git a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithNewSizeExample.razor b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithNewSizeExample.razor
index 81e21f9b..c4f6db94 100644
--- a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithNewSizeExample.razor
+++ b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithNewSizeExample.razor
@@ -80,6 +80,13 @@
IsAvailableInitCropper = false;
}
+ // In the .NET 8 with new render modes, SDK parameters components are not updated timely when using 'blazor.web.js'.
+ // We strongly recommend using StateHasChanged() method after changing a component's parameter,
+ // but be careful with this because you're updating the entire component where there may be more than one component,
+ // which can also affect performance a bit when there are too many components on the page or animations.
+ // As an option, make a separate wrapper with minimal functionality in this case.
+ //StateHasChanged();
+
await Task.WhenAll(
CropperComponent!.ReplaceAsync(newSrc, false).AsTask()
// For certain platforms based on WebView in MAUI, Windows Forms and WPF Blazor Hybrids, the 'RevokeObjectUrlAsync(OldSrc)' method does not work correctly in this place.
diff --git a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithSameSizeExample.razor b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithSameSizeExample.razor
index 6203a51a..bb097977 100644
--- a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithSameSizeExample.razor
+++ b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicInputReplaceImageWithSameSizeExample.razor
@@ -80,6 +80,13 @@
IsAvailableInitCropper = false;
}
+ // In the .NET 8 with new render modes, SDK parameters components are not updated timely when using 'blazor.web.js'.
+ // We strongly recommend using StateHasChanged() method after changing a component's parameter,
+ // but be careful with this because you're updating the entire component where there may be more than one component,
+ // which can also affect performance a bit when there are too many components on the page or animations.
+ // As an option, make a separate wrapper with minimal functionality in this case.
+ //StateHasChanged();
+
await Task.WhenAll(
CropperComponent!.ReplaceAsync(newSrc, true).AsTask()
// For certain platforms based on WebView in MAUI, Windows Forms and WPF Blazor Hybrids, the 'RevokeObjectUrlAsync(OldSrc)' method does not work correctly in this place.
diff --git a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithNewSizeExample.razor b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithNewSizeExample.razor
index da52b5e5..d9c46689 100644
--- a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithNewSizeExample.razor
+++ b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithNewSizeExample.razor
@@ -50,6 +50,13 @@
{
IsReplaced = true;
+ // In the .NET 8 with new render modes, SDK parameters components are not updated timely when using 'blazor.web.js'.
+ // We strongly recommend using StateHasChanged() method after changing a component's parameter,
+ // but be careful with this because you're updating the entire component where there may be more than one component,
+ // which can also affect performance a bit when there are too many components on the page or animations.
+ // As an option, make a separate wrapper with minimal functionality in this case.
+ //StateHasChanged();
+
await CropperComponent!.ReplaceAsync("images/raspberry.jpg", false);
// Releases an existing object URL which was previously created by calling URL.
diff --git a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithSameSizeExample.razor b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithSameSizeExample.razor
index af6eaf8c..445f02c3 100644
--- a/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithSameSizeExample.razor
+++ b/src/Cropper.Blazor/Client/Pages/Replace/Examples/BasicReplaceImageWithSameSizeExample.razor
@@ -50,6 +50,13 @@
{
IsReplaced = true;
+ // In the .NET 8 with new render modes, SDK parameters components are not updated timely when using 'blazor.web.js'.
+ // We strongly recommend using StateHasChanged() method after changing a component's parameter,
+ // but be careful with this because you're updating the entire component where there may be more than one component,
+ // which can also affect performance a bit when there are too many components on the page or animations.
+ // As an option, make a separate wrapper with minimal functionality in this case.
+ //StateHasChanged();
+
await CropperComponent!.ReplaceAsync("images/raspberry.jpg", true);
// Releases an existing object URL which was previously created by calling URL.
diff --git a/src/Cropper.Blazor/Client/Program.cs b/src/Cropper.Blazor/Client/Program.cs
index 91998f48..91bd55b7 100644
--- a/src/Cropper.Blazor/Client/Program.cs
+++ b/src/Cropper.Blazor/Client/Program.cs
@@ -23,4 +23,4 @@ static void ConfigureServices(IServiceCollection services, IWebAssemblyHostEnvir
.AddSingleton
()
.AddCropper()
.TryAddDocsViewServices();
-}
\ No newline at end of file
+}
diff --git a/src/Cropper.Blazor/Client/Services/MenuService.cs b/src/Cropper.Blazor/Client/Services/MenuService.cs
index bf60862f..b3190fa8 100644
--- a/src/Cropper.Blazor/Client/Services/MenuService.cs
+++ b/src/Cropper.Blazor/Client/Services/MenuService.cs
@@ -38,6 +38,7 @@ public class MenuService : IMenuService
new() {Title = "CropperComponent", Href = "api"},
new() {Title = "ViewMode", Href = "api/ViewMode"},
new() {Title = "DragMode", Href = "api/DragMode"},
+ new() {Title = "CropperComponentType", Href = "api/CropperComponentType"},
new() {Group = "Options", Title = "Options", Href = "api/Options"},
new() {Group = "Options", Title = "GetCroppedCanvasOptions", Href = "api/GetCroppedCanvasOptions"},
new() {Group = "Options", Title = "SetCropBoxDataOptions", Href = "api/SetCropBoxDataOptions"},
diff --git a/src/Cropper.Blazor/Client/Shared/AppbarButtons.razor.cs b/src/Cropper.Blazor/Client/Shared/AppbarButtons.razor.cs
index 620fa8d9..7542a987 100644
--- a/src/Cropper.Blazor/Client/Shared/AppbarButtons.razor.cs
+++ b/src/Cropper.Blazor/Client/Shared/AppbarButtons.razor.cs
@@ -6,4 +6,4 @@ namespace Cropper.Blazor.Client.Shared;
public partial class AppbarButtons
{
[Inject] private LayoutService LayoutService { get; set; } = null!;
-}
\ No newline at end of file
+}
diff --git a/src/Cropper.Blazor/Client/Shared/CroppedCanvasDialog.razor.cs b/src/Cropper.Blazor/Client/Shared/CroppedCanvasDialog.razor.cs
index f399195d..452525d4 100644
--- a/src/Cropper.Blazor/Client/Shared/CroppedCanvasDialog.razor.cs
+++ b/src/Cropper.Blazor/Client/Shared/CroppedCanvasDialog.razor.cs
@@ -14,8 +14,8 @@ public partial class CroppedCanvasDialog
public async Task DownloadImageSrcAsync()
{
await JSRuntime!.InvokeVoidAsync(
- "downloadFromUrl",
- new { Url = Src, FileName = $"{Guid.NewGuid()}.png" });
+ "downloadFromUrl",
+ new { Url = Src, FileName = $"{Guid.NewGuid()}.png" });
}
public Dictionary CroppedImageInputAttributes { get; set; } =
diff --git a/src/Cropper.Blazor/Client/Shared/DocsLayout.razor.cs b/src/Cropper.Blazor/Client/Shared/DocsLayout.razor.cs
index b9835cd2..0c835876 100644
--- a/src/Cropper.Blazor/Client/Shared/DocsLayout.razor.cs
+++ b/src/Cropper.Blazor/Client/Shared/DocsLayout.razor.cs
@@ -40,4 +40,4 @@ private void OnDrawerOpenChanged(bool value)
_drawerOpen = value;
StateHasChanged();
}
-}
\ No newline at end of file
+}
diff --git a/src/Cropper.Blazor/Client/Shared/SeoHeader.razor.cs b/src/Cropper.Blazor/Client/Shared/SeoHeader.razor.cs
index 9b115d51..9fee1fba 100644
--- a/src/Cropper.Blazor/Client/Shared/SeoHeader.razor.cs
+++ b/src/Cropper.Blazor/Client/Shared/SeoHeader.razor.cs
@@ -40,7 +40,26 @@ private string GetKeywords()
".net core",
"pwa",
"webassembly",
- ..Keywords,
+ "blazor image editor",
+ "image editor",
+ "blazor image",
+ "free image cropper",
+ "online cropper",
+ "photo cropper",
+ "avatar cropper",
+ "photo cropper",
+ "image cropper",
+ "resize image",
+ "photo resizer",
+ "blazor online cropper",
+ "blazor free image cropper",
+ "blazor photo cropper",
+ "blazor avatar cropper",
+ "blazor photo cropper",
+ "blazor image cropper",
+ "blazor resize image",
+ "blazor photo resizer",
+ .. Keywords
];
return string.Join(", ", keywords);
diff --git a/src/Cropper.Blazor/Client/Shared/Utilities/CropperBlazorLogo.razor b/src/Cropper.Blazor/Client/Shared/Utilities/CropperBlazorLogo.razor
index b5eca0ec..1673e1f9 100644
--- a/src/Cropper.Blazor/Client/Shared/Utilities/CropperBlazorLogo.razor
+++ b/src/Cropper.Blazor/Client/Shared/Utilities/CropperBlazorLogo.razor
@@ -10,15 +10,15 @@
+ c0,1.1-0.9,2-2,2H22c-6.9,0-12.5,5.6-12.5,12.5v85c0,6.9,5.6,12.5,12.5,12.5h56.5c1.1,0,2,0.9,2,2V557c0,6.9,5.6,12.5,12.5,12.5
+ h364.5c1.1,0,2,0.9,2,2V628c0,6.9,5.6,12.5,12.5,12.5h85c6.9,0,12.5-5.6,12.5-12.5v-56.5c0-1.1,0.9-2,2-2H628
+ c6.9,0,12.5-5.6,12.5-12.5v-85C640.5,465.1,634.9,459.5,628,459.5z M80.5,163.5c0,1.1-0.9,2-2,2h-42c-1.1,0-2-0.9-2-2v-56
+ c0-1.1,0.9-2,2-2h42c1.1,0,2,0.9,2,2V163.5z M544.5,613.5c0,1.1-0.9,2-2,2h-56c-1.1,0-2-0.9-2-2v-42c0-1.1,0.9-2,2-2h56
+ c1.1,0,2,0.9,2,2V613.5z M615.5,542.5c0,1.1-0.9,2-2,2h-506c-1.1,0-2-0.9-2-2v-506c0-1.1,0.9-2,2-2h56c1.1,0,2,0.9,2,2V472
+ c0,6.9,5.6,12.5,12.5,12.5h435.5c1.1,0,2,0.9,2,2V542.5z M484.5,178v249c0,6.9-5.6,12.5-12.5,12.5s-12.5-5.6-12.5-12.5V192.5
+ c0-1.1-0.9-2-2-2H223c-6.9,0-12.5-5.6-12.5-12.5s5.6-12.5,12.5-12.5h249C478.9,165.5,484.5,171.1,484.5,178z M569.5,93v334
+ c0,6.9-5.6,12.5-12.5,12.5s-12.5-5.6-12.5-12.5V107.5c0-1.1-0.9-2-2-2H223c-6.9,0-12.5-5.6-12.5-12.5s5.6-12.5,12.5-12.5h334
+ C563.9,80.5,569.5,86.1,569.5,93z" />
@@ -28,25 +28,25 @@
+ c0,6.9-5.6,12.5-12.5,12.5h-56.5c-1.1,0-2,0.9-2,2V628c0,6.9-5.6,12.5-12.5,12.5h-85c-6.9,0-12.5-5.6-12.5-12.5v-56.5
+ c0-1.1-0.9-2-2-2H93c-6.9,0-12.5-5.6-12.5-12.5V192.5c0-1.1-0.9-2-2-2H22c-6.9,0-12.5-5.6-12.5-12.5V93c0-6.9,5.6-12.5,12.5-12.5
+ h56.5c1.1,0,2-0.9,2-2V22c0-6.9,5.6-12.5,12.5-12.5H178 M107.5,544.5h506c1.1,0,2-0.9,2-2v-56c0-1.1-0.9-2-2-2H178
+ c-6.9,0-12.5-5.6-12.5-12.5V36.5c0-1.1-0.9-2-2-2h-56c-1.1,0-2,0.9-2,2v506C105.5,543.6,106.4,544.5,107.5,544.5 M36.5,165.5h42
+ c1.1,0,2-0.9,2-2v-56c0-1.1-0.9-2-2-2h-42c-1.1,0-2,0.9-2,2v56C34.5,164.6,35.4,165.5,36.5,165.5 M486.5,615.5h56c1.1,0,2-0.9,2-2
+ v-42c0-1.1-0.9-2-2-2h-56c-1.1,0-2,0.9-2,2v42C484.5,614.6,485.4,615.5,486.5,615.5 M557,80.5c6.9,0,12.5,5.6,12.5,12.5v334
+ c0,6.9-5.6,12.5-12.5,12.5s-12.5-5.6-12.5-12.5V107.5c0-1.1-0.9-2-2-2H223c-6.9,0-12.5-5.6-12.5-12.5s5.6-12.5,12.5-12.5H557
+ M472,165.5c6.9,0,12.5,5.6,12.5,12.5v249c0,6.9-5.6,12.5-12.5,12.5s-12.5-5.6-12.5-12.5V192.5c0-1.1-0.9-2-2-2H223
+ c-6.9,0-12.5-5.6-12.5-12.5s5.6-12.5,12.5-12.5H472 M178,1.5H93c-11.3,0-20.5,9.2-20.5,20.5v50.5H22C10.7,72.5,1.5,81.7,1.5,93v85
+ c0,11.3,9.2,20.5,20.5,20.5h50.5V557c0,11.3,9.2,20.5,20.5,20.5h358.5V628c0,11.3,9.2,20.5,20.5,20.5h85c11.3,0,20.5-9.2,20.5-20.5
+ v-50.5H628c11.3,0,20.5-9.2,20.5-20.5v-85c0-11.3-9.2-20.5-20.5-20.5H198.5V22C198.5,10.7,189.3,1.5,178,1.5L178,1.5z M113.5,42.5
+ h44V472c0,11.3,9.2,20.5,20.5,20.5h429.5v44h-494V42.5L113.5,42.5z M42.5,113.5h30v44h-30V113.5L42.5,113.5z M492.5,577.5h44v30
+ h-44V577.5L492.5,577.5z M557,72.5H223c-11.3,0-20.5,9.2-20.5,20.5s9.2,20.5,20.5,20.5h313.5V427c0,11.3,9.2,20.5,20.5,20.5
+ s20.5-9.2,20.5-20.5V93C577.5,81.7,568.3,72.5,557,72.5L557,72.5z M472,157.5H223c-11.3,0-20.5,9.2-20.5,20.5s9.2,20.5,20.5,20.5
+ h228.5V427c0,11.3,9.2,20.5,20.5,20.5s20.5-9.2,20.5-20.5V178C492.5,166.7,483.3,157.5,472,157.5L472,157.5z" />
@code {
[Parameter] public string Style { get; set; } = null!;
- [Parameter] public string Class { get; set; } = null!;
+ [Parameter] public string Class { get; set; } = null!;
}
diff --git a/src/Cropper.Blazor/Client/Styles/Cropper.Blazor.Client.scss b/src/Cropper.Blazor/Client/Styles/Cropper.Blazor.Client.scss
index 7208256a..5ac344f4 100644
--- a/src/Cropper.Blazor/Client/Styles/Cropper.Blazor.Client.scss
+++ b/src/Cropper.Blazor/Client/Styles/Cropper.Blazor.Client.scss
@@ -1,8 +1,8 @@
-@import 'layout/_mainlayout';
-@import 'layout/_markdown';
-@import 'layout/_updateAvaibleDetector.scss';
-@import 'components/docssection.scss';
-@import 'components/docspage.scss';
+@import 'layout/mainlayout';
+@import 'layout/markdown';
+@import 'layout/updateAvaibleDetector';
+@import 'components/docssection';
+@import 'components/docspage';
.master-loader {
height: 100%;
@@ -47,8 +47,6 @@
padding: 20px;
&:nth-child(1) {
- -moz-filter: grayscale(1);
- -webkit-filter: grayscale(1);
filter: grayscale(1);
z-index: 1;
}
@@ -86,7 +84,7 @@
padding-top: 1.1rem;
}
-.valid.modified:not([type=checkbox]) {
+.valid.modified:not([type="checkbox"]) {
outline: 1px solid #26b050;
}
@@ -101,10 +99,10 @@
#blazor-error-ui {
background: lightyellow;
bottom: 0;
- box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 -1px 2px rgb(0 0 0 / 20%);
display: none;
left: 0;
- padding: 0.6rem 1.25rem 0.7rem 1.25rem;
+ padding: 0.6rem 1.25rem 0.7rem;
position: fixed;
width: 100%;
z-index: 1000;
@@ -118,7 +116,7 @@
}
.blazor-error-boundary {
- background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
+ background: url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=") no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
@@ -150,7 +148,6 @@
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
background-clip: text;
- -webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: 800;
letter-spacing: 1px;
@@ -183,7 +180,7 @@
}
.button-gradient:hover {
- box-shadow: 0.3px 0.5px 0.4px hsla(200, 100%, 38%, 0.62), 0.3px 0.6px 0.5px -0.7px hsla(200, 100%, 38%, 0.54), 0.8px 1.6px 1.3px -1.4px hsla(200, 100%, 38%, 0.46), 2px 4.1px 3.4px -2.1px hsla(200, 100%, 38%, 0.38), 4.5px 9px 7.5px -2.9px hsla(200, 100%, 38%, 0.31), 8.5px 17.1px 14.3px -3.6px hsla(200, 100%, 38%, 0.23), 14.6px 29.2px 24.5px -4.3px hsla(200, 100%, 38%, 0.15), 23px 46px 38.6px -5px hsla(200, 100%, 38%, 0.08);
+ box-shadow: 0.3px 0.5px 0.4px hsl(200deg 100% 38% / 62%), 0.3px 0.6px 0.5px -0.7px hsl(200deg 100% 38% / 54%), 0.8px 1.6px 1.3px -1.4px hsl(200deg 100% 38% / 46%), 2px 4.1px 3.4px -2.1px hsl(200deg 100% 38% / 38%), 4.5px 9px 7.5px -2.9px hsl(200deg 100% 38% / 31%), 8.5px 17.1px 14.3px -3.6px hsl(200deg 100% 38% / 23%), 14.6px 29.2px 24.5px -4.3px hsl(200deg 100% 38% / 15%), 23px 46px 38.6px -5px hsl(200deg 100% 38% / 8%);
}
.cropper-error-load {
@@ -195,7 +192,7 @@
display: flex;
width: 30px;
height: 20px;
- background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAwIDgwMCI+DQo8cGF0aCBmaWxsPSIjM2E3NWM0IiBkPSJtMCwwaDEyMDB2ODAwaC0xMjAweiIvPg0KPHBhdGggZmlsbD0iI2Y5ZGQxNiIgZD0ibTAsNDAwaDEyMDB2NDAwaC0xMjAweiIvPg0KPC9zdmc+DQo=);
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjAwIDgwMCI+DQo8cGF0aCBmaWxsPSIjM2E3NWM0IiBkPSJtMCwwaDEyMDB2ODAwaC0xMjAweiIvPg0KPHBhdGggZmlsbD0iI2Y5ZGQxNiIgZD0ibTAsNDAwaDEyMDB2NDAwaC0xMjAweiIvPg0KPC9zdmc+DQo=");
background-color: initial;
border-radius: 4px;
box-sizing: border-box;
@@ -210,7 +207,7 @@
}
.cropper-face {
- opacity: 10%;
+ opacity: 0.1;
}
.img-container.cropper-face-close .cropper-container .cropper-crop-box .cropper-face {
diff --git a/src/Cropper.Blazor/Client/Styles/components/docspage.scss b/src/Cropper.Blazor/Client/Styles/components/docspage.scss
index eb99cfdf..0a5b10c7 100644
--- a/src/Cropper.Blazor/Client/Styles/components/docspage.scss
+++ b/src/Cropper.Blazor/Client/Styles/components/docspage.scss
@@ -73,6 +73,11 @@
color: var(--mud-palette-tertiary);
background-color: var(--mud-palette-tertiary-hover);
}
+
+ &.docs-code-warning {
+ color: var(--mud-palette-warning);
+ background-color: var(--mud-palette-warning-hover);
+ }
}
.docs-frame {
@@ -82,10 +87,7 @@
& .docs-frame-absolute {
position: absolute;
- bottom: 0;
- left: 0;
- top: 0;
- right: auto;
+ inset: 0 auto 0 0;
width: 100%;
height: 100%;
diff --git a/src/Cropper.Blazor/Client/Styles/components/docssection.scss b/src/Cropper.Blazor/Client/Styles/components/docssection.scss
index d609cad7..94df2129 100644
--- a/src/Cropper.Blazor/Client/Styles/components/docssection.scss
+++ b/src/Cropper.Blazor/Client/Styles/components/docssection.scss
@@ -174,38 +174,6 @@
}
}
}
-
- .docs-code {
- display: inline-block;
- padding: 0 5px;
- direction: ltr;
- font-size: 0.85em;
- font-weight: 900;
- font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
- line-height: 1.4;
- border-radius: 2px;
- -webkit-font-smoothing: subpixel-antialiased;
-
- &.docs-code-primary {
- color: var(--mud-palette-primary);
- background-color: var(--mud-palette-primary-hover);
- }
-
- &.docs-code-secondary {
- color: var(--mud-palette-secondary);
- background-color: var(--mud-palette-secondary-hover);
- }
-
- &.docs-code-tertiary {
- color: var(--mud-palette-tertiary);
- background-color: var(--mud-palette-tertiary-hover);
- }
-
- &.docs-code-warning {
- color: var(--mud-palette-warning);
- background-color: var(--mud-palette-warning-hover);
- }
- }
}
.warning-color {
diff --git a/src/Cropper.Blazor/Client/Styles/layout/_mainlayout.scss b/src/Cropper.Blazor/Client/Styles/layout/mainlayout.scss
similarity index 87%
rename from src/Cropper.Blazor/Client/Styles/layout/_mainlayout.scss
rename to src/Cropper.Blazor/Client/Styles/layout/mainlayout.scss
index 08364e79..6e3acab5 100644
--- a/src/Cropper.Blazor/Client/Styles/layout/_mainlayout.scss
+++ b/src/Cropper.Blazor/Client/Styles/layout/mainlayout.scss
@@ -1,11 +1,11 @@
.docs-title {
- font-family: 'Public Sans', 'Roboto', 'Arial', sans-serif;
+ font-family: 'Public Sans', Roboto, Arial, sans-serif;
font-weight: 600;
font-size: 3.75rem;
}
.docs-title-description {
- font-family: 'Public Sans', 'Roboto', 'Arial', sans-serif;
+ font-family: 'Public Sans', Roboto, Arial, sans-serif;
font-weight: 500;
line-height: 1.75;
font-size: 1.1rem;
@@ -48,10 +48,10 @@
}
.mud-button {
- font-family: 'Public Sans', 'Roboto', 'Arial', sans-serif;
+ font-family: 'Public Sans', Roboto, Arial, sans-serif;
font-weight: 500;
line-height: 1.75;
- letter-spacing: 0.02857em;
+ letter-spacing: 0.0286em;
text-transform: none;
}
}
@@ -75,7 +75,7 @@
.docs-brand-text {
letter-spacing: 0.1rem;
font-weight: 500;
- font-family: 'Roboto', sans-serif;
+ font-family: Roboto, sans-serif;
margin-inline-start: 12px;
user-select: none;
}
diff --git a/src/Cropper.Blazor/Client/Styles/layout/_markdown.scss b/src/Cropper.Blazor/Client/Styles/layout/markdown.scss
similarity index 80%
rename from src/Cropper.Blazor/Client/Styles/layout/_markdown.scss
rename to src/Cropper.Blazor/Client/Styles/layout/markdown.scss
index f0c1446d..04064d4b 100644
--- a/src/Cropper.Blazor/Client/Styles/layout/_markdown.scss
+++ b/src/Cropper.Blazor/Client/Styles/layout/markdown.scss
@@ -1,46 +1,46 @@
.mud-landingpage-editor {
& .html, .codearea {
- & .htmlTagDelimiter {
+ & .html-tag-delimiter {
color: #979797;
}
- & .htmlElementName {
+ & .html-element-name {
color: #988ef1;
}
- & .htmlAttributeName {
+ & .html-attribute-name {
color: #27b5b5;
}
- & .htmlOperator, .quot {
+ & .html-operator, .quot {
color: #c8c8c8;
}
- & .htmlAttributeValue {
+ & .html-attribute-value {
color: #ededed;
}
- & .htmlLink {
+ & .html-link {
color: #61afef;
text-decoration: underline;
}
& .enum {
color: #b4eb8f;
- background-color: rgba(255, 255, 255, 0.15);
+ background-color: rgb(255 255 255 / 15%);
}
- & .enumValue, .sharpVariable {
+ & .enum-value, .sharp-variable {
color: #ededed;
- background-color: rgba(255, 255, 255, 0.15);
+ background-color: rgb(255 255 255 / 15%);
}
& .keyword {
color: #61afef;
- background-color: rgba(255, 255, 255, 0.15);
+ background-color: rgb(255 255 255 / 15%);
}
- & .atSign {
+ & .at-sign {
color: #8323d8;
}
@@ -50,7 +50,7 @@
}
& .csharp {
- & .atSign {
+ & .at-sign {
color: #000;
background-color: #d2d295;
}
@@ -71,7 +71,7 @@
color: #4ec9b0;
}
- & .localVar {
+ & .local-var {
color: #9cdcfe;
}
@@ -110,7 +110,7 @@
& .css {
& .property {
- color: hsl(76, 21%, 52%);
+ color: hsl(76deg 21% 52%);
}
& .comment {
@@ -119,7 +119,7 @@
}
& .csharp {
- & .atSign {
+ & .at-sign {
color: #8323d8;
}
@@ -139,7 +139,7 @@
color: #1ec8a5;
}
- & .localVar {
+ & .local-var {
color: #2196f3;
}
@@ -159,19 +159,19 @@
color: #57a64a;
}
- & .htmlElementName {
+ & .html-element-name {
color: #7e6fffff;
}
- & .htmlAttributeName {
+ & .html-attribute-name {
color: #8323d8;
}
- & .htmlAttributeValue {
+ & .html-attribute-value {
color: #ff4081;
}
- & .htmlOperator {
+ & .html-operator {
color: #737373;
}
@@ -195,28 +195,28 @@
user-select: all;
}
- & .htmlTagDelimiter {
+ & .html-tag-delimiter {
color: #979797;
}
- & .htmlElementName {
+ & .html-element-name {
color: var(--mud-palette-primary);
font-weight: 600;
}
- & .htmlAttributeName {
+ & .html-attribute-name {
color: #8323d8;
}
- & .htmlOperator, .quot {
+ & .html-operator, .quot {
color: #737373;
}
- & .htmlAttributeValue {
+ & .html-attribute-value {
color: #ff4081;
}
- & .htmlLink {
+ & .html-link {
color: #ff4081;
text-decoration: underline;
}
@@ -226,7 +226,7 @@
background-color: var(--mud-palette-grey-light);
}
- & .enumValue, .sharpVariable {
+ & .enum-value, .sharp-variable {
color: var(--mud-palette-text-primary);
background-color: var(--mud-palette-grey-light);
}
@@ -236,7 +236,7 @@
background-color: var(--mud-palette-grey-light);
}
- & .atSign {
+ & .at-sign {
color: #8323d8;
}
diff --git a/src/Cropper.Blazor/Client/Styles/layout/_updateAvaibleDetector.scss b/src/Cropper.Blazor/Client/Styles/layout/updateAvaibleDetector.scss
similarity index 100%
rename from src/Cropper.Blazor/Client/Styles/layout/_updateAvaibleDetector.scss
rename to src/Cropper.Blazor/Client/Styles/layout/updateAvaibleDetector.scss
diff --git a/src/Cropper.Blazor/Client/wwwroot/helper.js b/src/Cropper.Blazor/Client/wwwroot/helper.js
index 1610cffd..acdef48a 100644
--- a/src/Cropper.Blazor/Client/wwwroot/helper.js
+++ b/src/Cropper.Blazor/Client/wwwroot/helper.js
@@ -1,53 +1,53 @@
-window.downloadFromUrl = (options) => {
- const anchorElement = document.createElement('a');
- anchorElement.href = options.url;
- anchorElement.download = options.fileName ?? '';
- anchorElement.click();
- anchorElement.remove();
-};
+window.downloadFromUrl = (options) => {
+ const anchorElement = document.createElement('a')
+ anchorElement.href = options.url
+ anchorElement.download = options.fileName ?? ''
+ anchorElement.click()
+ anchorElement.remove()
+}
window.getPolygonImage = (sourceCanvas, path) => {
- const canvas = document.createElement('canvas');
- const context = canvas.getContext('2d');
- const width = sourceCanvas.width,
- height = sourceCanvas.height;
-
- canvas.width = width;
- canvas.height = height;
- context.imageSmoothingEnabled = true;
-
- context.beginPath();
- context.moveTo(path[0] * width / 100, path[1] * height / 100);
- context.fillStyle = "rgba(255, 255, 255, 0)";
-
- for (let i = 2; i < path.length; i += 2) {
- context.lineTo(path[i] * width / 100, path[i + 1] * height / 100);
- }
-
- context.closePath();
- context.clip();
- context.fill();
- context.globalCompositeOperation = 'lighter';
- context.drawImage(sourceCanvas, 0, 0, width, height);
-
- return canvas.toDataURL("image/png", 1);
+ const canvas = document.createElement('canvas')
+ const context = canvas.getContext('2d')
+ const width = sourceCanvas.width
+ const height = sourceCanvas.height
+
+ canvas.width = width
+ canvas.height = height
+ context.imageSmoothingEnabled = true
+
+ context.beginPath()
+ context.moveTo(path[0] * width / 100, path[1] * height / 100)
+ context.fillStyle = 'rgba(255, 255, 255, 0)'
+
+ for (let i = 2; i < path.length; i += 2) {
+ context.lineTo(path[i] * width / 100, path[i + 1] * height / 100)
+ }
+
+ context.closePath()
+ context.clip()
+ context.fill()
+ context.globalCompositeOperation = 'lighter'
+ context.drawImage(sourceCanvas, 0, 0, width, height)
+
+ return canvas.toDataURL('image/png', 1)
}
window.getEllipseImage = (sourceCanvas) => {
- const createdCanvas = document.createElement('canvas');
- const contextCanvas = createdCanvas.getContext('2d');
- const widthCanvas = sourceCanvas.width,
- heightCanvas = sourceCanvas.height;
-
- createdCanvas.width = widthCanvas;
- createdCanvas.height = heightCanvas;
- contextCanvas.imageSmoothingEnabled = true;
-
- contextCanvas.drawImage(sourceCanvas, 0, 0, widthCanvas, heightCanvas);
- contextCanvas.globalCompositeOperation = 'destination-in';
- contextCanvas.beginPath();
- contextCanvas.ellipse(widthCanvas / 2, heightCanvas / 2, widthCanvas / 2, heightCanvas / 2, 0 * Math.PI, 0, 180 * Math.PI, true);
- contextCanvas.fill();
-
- return createdCanvas.toDataURL("image/png", 1);
+ const createdCanvas = document.createElement('canvas')
+ const contextCanvas = createdCanvas.getContext('2d')
+ const widthCanvas = sourceCanvas.width
+ const heightCanvas = sourceCanvas.height
+
+ createdCanvas.width = widthCanvas
+ createdCanvas.height = heightCanvas
+ contextCanvas.imageSmoothingEnabled = true
+
+ contextCanvas.drawImage(sourceCanvas, 0, 0, widthCanvas, heightCanvas)
+ contextCanvas.globalCompositeOperation = 'destination-in'
+ contextCanvas.beginPath()
+ contextCanvas.ellipse(widthCanvas / 2, heightCanvas / 2, widthCanvas / 2, heightCanvas / 2, 0 * Math.PI, 0, 180 * Math.PI, true)
+ contextCanvas.fill()
+
+ return createdCanvas.toDataURL('image/png', 1)
}
diff --git a/src/Cropper.Blazor/Client/wwwroot/index.html b/src/Cropper.Blazor/Client/wwwroot/index.html
index c28e845c..2cf83604 100644
--- a/src/Cropper.Blazor/Client/wwwroot/index.html
+++ b/src/Cropper.Blazor/Client/wwwroot/index.html
@@ -2,27 +2,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -38,40 +38,40 @@
-
- An unhandled error has occurred.
-
Reload
-
🗙
-
-
-
-
-
-
-
-
-
-
+
+ An unhandled error has occurred.
+
Reload
+
🗙
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Cropper.Blazor/Client/wwwroot/jsObjectModule.js b/src/Cropper.Blazor/Client/wwwroot/jsObjectModule.js
index 34e44839..f2fba990 100644
--- a/src/Cropper.Blazor/Client/wwwroot/jsObjectModule.js
+++ b/src/Cropper.Blazor/Client/wwwroot/jsObjectModule.js
@@ -1,33 +1,32 @@
-class JsObject {
- getPropertyList(path) {
- let res = path.replace('[', '.').replace(']', '').split('.');
+class JsObject {
+ getPropertyList (path) {
+ const res = path.replace('[', '.').replace(']', '').split('.')
- if (res[0] === "") { // if we pass "[0].id" we want to return [0,'id']
- res.shift();
- }
-
- return res;
+ if (res[0] === '') { // if we pass "[0].id" we want to return [0,'id']
+ res.shift()
}
- getInstanceProperty(instance, propertyPath) {
-
- if (propertyPath === '') {
- return instance;
- }
+ return res
+ }
- let currentProperty = instance;
- let splitProperty = this.getPropertyList(propertyPath);
+ getInstanceProperty (instance, propertyPath) {
+ if (propertyPath === '') {
+ return instance
+ }
- for (let i = 0; i < splitProperty.length; i++) {
- if (splitProperty[i] in currentProperty) {
- currentProperty = currentProperty[splitProperty[i]];
- } else {
- return null;
- }
- }
+ let currentProperty = instance
+ const splitProperty = this.getPropertyList(propertyPath)
- return currentProperty;
+ for (let i = 0; i < splitProperty.length; i++) {
+ if (splitProperty[i] in currentProperty) {
+ currentProperty = currentProperty[splitProperty[i]]
+ } else {
+ return null
+ }
}
+
+ return currentProperty
+ }
}
-window.jsObject = new JsObject();
+window.jsObject = new JsObject()
diff --git a/src/Cropper.Blazor/Client/wwwroot/overrideCropperJsInteropModule.js b/src/Cropper.Blazor/Client/wwwroot/overrideCropperJsInteropModule.js
index 087682ac..c3fd2d26 100644
--- a/src/Cropper.Blazor/Client/wwwroot/overrideCropperJsInteropModule.js
+++ b/src/Cropper.Blazor/Client/wwwroot/overrideCropperJsInteropModule.js
@@ -1,15 +1,14 @@
-window.overrideOnZoomCropperEvent = (minZoomRatio, maxZoomRatio) => {
- window.cropper.onZoom = function (imageObject, event, correlationId) {
- const jSEventData = this.getJSEventData(event, correlationId);
-
- const isApplyPreventZoomMinRatio = (minZoomRatio != null) && (minZoomRatio > event.detail.ratio);
- const isApplyPreventZoomMaxRatio = (maxZoomRatio != null) && (event.detail.ratio > maxZoomRatio);
+window.overrideOnZoomCropperEvent = (minZoomRatio, maxZoomRatio) => {
+ window.cropper.onZoom = function (imageObject, event, correlationId) {
+ const jSEventData = this.getJSEventData(event, correlationId)
- if (isApplyPreventZoomMinRatio || isApplyPreventZoomMaxRatio) {
- event.preventDefault();
- }
- else {
- imageObject.invokeMethodAsync('CropperIsZoomed', jSEventData);
- }
- };
-};
\ No newline at end of file
+ const isApplyPreventZoomMinRatio = (minZoomRatio != null) && (minZoomRatio > event.detail.ratio)
+ const isApplyPreventZoomMaxRatio = (maxZoomRatio != null) && (event.detail.ratio > maxZoomRatio)
+
+ if (isApplyPreventZoomMinRatio || isApplyPreventZoomMaxRatio) {
+ event.preventDefault()
+ } else {
+ imageObject.invokeMethodAsync('CropperIsZoomed', jSEventData)
+ }
+ }
+}
diff --git a/src/Cropper.Blazor/Client/wwwroot/resizeWindowEventListener.js b/src/Cropper.Blazor/Client/wwwroot/resizeWindowEventListener.js
index b81ddcd1..5adb49b3 100644
--- a/src/Cropper.Blazor/Client/wwwroot/resizeWindowEventListener.js
+++ b/src/Cropper.Blazor/Client/wwwroot/resizeWindowEventListener.js
@@ -1,19 +1,19 @@
let timer
window.addEventListener('resize', () => {
- if (!Object.hasOwn(this, 'cropper') || cropper == null || cropper.cropperInstances == null) {
- return;
- }
- let keys = Object.keys(cropper.cropperInstances);
- clearTimeout(timer);
- if (keys.length > 0) {
- keys.forEach((key) => {
- cropper.cropperInstances[key].disable();
- });
- timer = setTimeout(() => {
- let keys = Object.keys(cropper.cropperInstances);
- keys.forEach((key) => {
- cropper.cropperInstances[key].enable();
- });
- }, 100);
- }
-})
\ No newline at end of file
+ if (!Object.hasOwn(this, 'cropper') || cropper == null || cropper.cropperInstances == null) { // eslint-disable-line no-undef
+ return
+ }
+ const keys = Object.keys(cropper.cropperInstances) // eslint-disable-line no-undef
+ clearTimeout(timer)
+ if (keys.length > 0) {
+ keys.forEach((key) => {
+ cropper.cropperInstances[key].disable() // eslint-disable-line no-undef
+ })
+ timer = setTimeout(() => {
+ const keys = Object.keys(cropper.cropperInstances) // eslint-disable-line no-undef
+ keys.forEach((key) => {
+ cropper.cropperInstances[key].enable() // eslint-disable-line no-undef
+ })
+ }, 100)
+ }
+})
diff --git a/src/Cropper.Blazor/Client/wwwroot/service-worker.js b/src/Cropper.Blazor/Client/wwwroot/service-worker.js
index 4882765c..68c0fc3a 100644
--- a/src/Cropper.Blazor/Client/wwwroot/service-worker.js
+++ b/src/Cropper.Blazor/Client/wwwroot/service-worker.js
@@ -2,4 +2,4 @@
// This is because caching would make development more difficult (changes would not
// be reflected on the first load after each change).
self.addEventListener('fetch', () => {
-});
+})
diff --git a/src/Cropper.Blazor/Client/wwwroot/service-worker.published.js b/src/Cropper.Blazor/Client/wwwroot/service-worker.published.js
index 241dae9e..ccf70192 100644
--- a/src/Cropper.Blazor/Client/wwwroot/service-worker.published.js
+++ b/src/Cropper.Blazor/Client/wwwroot/service-worker.published.js
@@ -1,75 +1,75 @@
// Caution! Be sure you understand the caveats before publishing an application with
// offline support. See https://aka.ms/blazor-offline-considerations
-self.importScripts('./service-worker-assets.js');
+self.importScripts('./service-worker-assets.js')
self.addEventListener('install', event => {
- event.waitUntil(
- Promise.all([
- onInstall(),
- self.skipWaiting(),
- ])
- );
-});
+ event.waitUntil(
+ Promise.all([
+ onInstall(),
+ self.skipWaiting()
+ ])
+ )
+})
self.addEventListener('activate', event => {
- event.waitUntil(
- Promise.all(
- [
- onActivate(),
- self.clients.claim(),
- self.skipWaiting(),
- ]
- )
- .catch(
- (err) => {
- event.skipWaiting();
- }
- )
- );
-});
-self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
+ event.waitUntil(
+ Promise.all(
+ [
+ onActivate(),
+ self.clients.claim(),
+ self.skipWaiting()
+ ]
+ )
+ .catch(
+ (err) => { // eslint-disable-line
+ event.skipWaiting()
+ }
+ )
+ )
+})
+self.addEventListener('fetch', event => event.respondWith(onFetch(event)))
-const cacheNamePrefix = 'offline-cache-';
-const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
-const offlineAssetsInclude = [/\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/];
-const offlineAssetsExclude = [/^service-worker\.js$/];
+const cacheNamePrefix = 'offline-cache-'
+const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`
+const offlineAssetsInclude = [/\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/]
+const offlineAssetsExclude = [/^service-worker\.js$/]
-async function onInstall(event) {
- console.info('Service worker: Install');
+async function onInstall (event) {
+ console.info('Service worker: Install')
- // Fetch and cache all matching items from the assets manifest
- const assetsRequests = self.assetsManifest.assets
- .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
- .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
- .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' }));
+ // Fetch and cache all matching items from the assets manifest
+ const assetsRequests = self.assetsManifest.assets
+ .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
+ .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
+ .map(asset => new Request(asset.url, { integrity: asset.hash, cache: 'no-cache' }))
- await caches.open(cacheName)
- .then(cache => cache.addAll(assetsRequests))
- .then(() => {
- return self.skipWaiting();
- });
+ await caches.open(cacheName)
+ .then(cache => cache.addAll(assetsRequests))
+ .then(() => {
+ return self.skipWaiting()
+ })
}
-async function onActivate(event) {
- console.info('Service worker: Activate');
+async function onActivate (event) {
+ console.info('Service worker: Activate')
- // Delete unused caches
- const cacheKeys = await caches.keys();
- await Promise.all(cacheKeys
- .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName)
- .map(key => caches.delete(key)));
+ // Delete unused caches
+ const cacheKeys = await caches.keys()
+ await Promise.all(cacheKeys
+ .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName)
+ .map(key => caches.delete(key)))
}
-async function onFetch(event) {
- let cachedResponse = null;
- if (event.request.method === 'GET') {
- // For all navigation requests, try to serve index.html from cache
- // If you need some URLs to be server-rendered, edit the following check to exclude those URLs
- const shouldServeIndexHtml = event.request.mode === 'navigate';
+async function onFetch (event) {
+ let cachedResponse = null
+ if (event.request.method === 'GET') {
+ // For all navigation requests, try to serve index.html from cache
+ // If you need some URLs to be server-rendered, edit the following check to exclude those URLs
+ const shouldServeIndexHtml = event.request.mode === 'navigate'
- const request = shouldServeIndexHtml ? 'index.html' : event.request;
- const cache = await caches.open(cacheName);
- cachedResponse = await cache.match(request);
- }
+ const request = shouldServeIndexHtml ? 'index.html' : event.request
+ const cache = await caches.open(cacheName)
+ cachedResponse = await cache.match(request)
+ }
- return cachedResponse || fetch(event.request);
+ return cachedResponse || fetch(event.request)
}
diff --git a/src/Cropper.Blazor/Client/wwwroot/sw-registrator.js b/src/Cropper.Blazor/Client/wwwroot/sw-registrator.js
index c4ec0c18..7dc64239 100644
--- a/src/Cropper.Blazor/Client/wwwroot/sw-registrator.js
+++ b/src/Cropper.Blazor/Client/wwwroot/sw-registrator.js
@@ -1,30 +1,30 @@
window.updateAvailable = new Promise((resolve, reject) => {
- if (!('serviceWorker' in navigator)) {
- const errorMessage = `This browser doesn't support service workers`;
- console.error(errorMessage);
- reject(errorMessage);
- return;
- }
+ if (!('serviceWorker' in navigator)) {
+ const errorMessage = 'This browser doesn\'t support service workers'
+ console.error(errorMessage)
+ reject(errorMessage)
+ return
+ }
- navigator.serviceWorker.register('/service-worker.min.js')
- .then(registration => {
- console.info(`Service worker registration successful (scope: ${registration.scope})`);
+ navigator.serviceWorker.register('/service-worker.min.js')
+ .then(registration => {
+ console.info(`Service worker registration successful (scope: ${registration.scope})`)
- setInterval(() => {
- registration.update();
- }, 60 * 1000); // 60000ms -> check each minute
+ setInterval(() => {
+ registration.update()
+ }, 60 * 1000) // 60000ms -> check each minute
- registration.onupdatefound = () => {
- const installingServiceWorker = registration.installing;
- installingServiceWorker.onstatechange = () => {
- if (installingServiceWorker.state === 'installed') {
- resolve(!!navigator.serviceWorker.controller);
- }
- }
- };
- })
- .catch(error => {
- console.error('Service worker registration failed with error:', error);
- reject(error);
- });
-});
+ registration.onupdatefound = () => {
+ const installingServiceWorker = registration.installing
+ installingServiceWorker.onstatechange = () => {
+ if (installingServiceWorker.state === 'installed') {
+ resolve(!!navigator.serviceWorker.controller)
+ }
+ }
+ }
+ })
+ .catch(error => {
+ console.error('Service worker registration failed with error:', error)
+ reject(error)
+ })
+})
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/CodeSnippetsCompiler.cs b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/CodeSnippetsCompiler.cs
index ebc63027..df8d8faf 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/CodeSnippetsCompiler.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/CodeSnippetsCompiler.cs
@@ -10,14 +10,14 @@ public static partial class CodeSnippetsCompiler
{
public static bool Execute()
{
- var paths = new Paths();
+
var success = true;
try
{
var currentCode = string.Empty;
- if (File.Exists(paths.SnippetsFilePath))
+ if (File.Exists(Paths.SnippetsFilePath))
{
- currentCode = File.ReadAllText(paths.SnippetsFilePath);
+ currentCode = File.ReadAllText(Paths.SnippetsFilePath);
}
var cb = new CodeBuilder();
@@ -29,7 +29,7 @@ public static bool Execute()
cb.AddLine("{");
cb.IndentLevel++;
- foreach (var entry in Directory.EnumerateFiles(paths.DocsDirPath, "*.razor", SearchOption.AllDirectories)
+ foreach (var entry in Directory.EnumerateFiles(Paths.DocsDirPath, "*.razor", SearchOption.AllDirectories)
.OrderBy(e => e.Replace("\\", "/"), StringComparer.Ordinal))
{
var filename = Path.GetFileName(entry);
@@ -46,12 +46,12 @@ public static bool Execute()
if (currentCode != cb.ToString())
{
- File.WriteAllText(paths.SnippetsFilePath, cb.ToString());
+ File.WriteAllText(Paths.SnippetsFilePath, cb.ToString());
}
}
catch (Exception e)
{
- Console.WriteLine($"Error generating {paths.SnippetsFilePath} : {e.Message}");
+ Console.WriteLine($"Error generating {Paths.SnippetsFilePath} : {e.Message}");
success = false;
}
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Cropper.Blazor.Client.Compiler.csproj b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Cropper.Blazor.Client.Compiler.csproj
index 73941058..df03a916 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Cropper.Blazor.Client.Compiler.csproj
+++ b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Cropper.Blazor.Client.Compiler.csproj
@@ -6,11 +6,12 @@
-
+
+
+
+
+
+
-
-
-
-
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/DocStrings.cs b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/DocStrings.cs
index 4e0accee..e5d57f88 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/DocStrings.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/DocStrings.cs
@@ -15,14 +15,13 @@ public partial class DocStrings
public bool Execute()
{
- var paths = new Paths();
var success = true;
try
{
var currentCode = string.Empty;
- if (File.Exists(paths.DocStringsFilePath))
+ if (File.Exists(Paths.DocStringsFilePath))
{
- currentCode = File.ReadAllText(paths.DocStringsFilePath);
+ currentCode = File.ReadAllText(Paths.DocStringsFilePath);
}
var cb = new CodeBuilder();
@@ -110,12 +109,12 @@ public bool Execute()
if (currentCode != cb.ToString())
{
- File.WriteAllText(paths.DocStringsFilePath, cb.ToString());
+ File.WriteAllText(Paths.DocStringsFilePath, cb.ToString());
}
}
catch (Exception e)
{
- Console.WriteLine($"Error generating {paths.DocStringsFilePath} : {e.Message}");
+ Console.WriteLine($"Error generating {Paths.DocStringsFilePath} : {e.Message}");
success = false;
}
@@ -160,6 +159,16 @@ private static string ConvertCrefToHTML(string markdownText)
{
return $"{value}";
}
+ else if (result.Contains("Cropper.Blazor.Models.CropperComponentType"))
+ {
+ (string enumName, string enumItemName) = result.RemoveNamespaceFromEnumValue();
+
+ return $"{enumName}.{enumItemName}";
+ }
+ else if (result.EndsWith("Cropper.Blazor.Components.CropperComponent.IsErrorLoadImage"))
+ {
+ return value;
+ }
return $"{value}";
});
@@ -177,6 +186,7 @@ private static string ConvertSeeTagsForMethod(string doc, string formattedReturn
.Replace("", "DotNetStreamReference")
.Replace("", "ValueTask")
.Replace("", $"{formattedReturnSignature}")
+ .Replace("", $"{formattedReturnSignature}")
.Replace("", "JSEventData<>")
.Replace("", "CancellationToken");
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/ExamplesMarkup.cs b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/ExamplesMarkup.cs
index ade74122..0fb25302 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/ExamplesMarkup.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/ExamplesMarkup.cs
@@ -3,14 +3,14 @@
using System.Text;
using System.Text.RegularExpressions;
using ColorCode;
+using ColorCode.Styling;
namespace Cropper.Blazor.Client.Compiler
{
- public class ExamplesMarkup
+ public partial class ExamplesMarkup
{
public bool Execute()
{
- var paths = new Paths();
var newFiles = new StringBuilder();
var success = true;
var noOfFilesUpdated = 0;
@@ -18,15 +18,15 @@ public bool Execute()
try
{
- var formatter = new HtmlClassFormatter();
+ var formatter = new HtmlClassFormatter(StyleDictionaryKebabCase.KebabCase);
var lastCheckedTime = new DateTime();
- if (File.Exists(paths.NewFilesToBuildPath))
+ if (File.Exists(Paths.NewFilesToBuildPath))
{
- var lastNewFilesToBuild = new FileInfo(paths.NewFilesToBuildPath);
+ var lastNewFilesToBuild = new FileInfo(Paths.NewFilesToBuildPath);
lastCheckedTime = lastNewFilesToBuild.LastWriteTime;
}
- var directoryInfo = new DirectoryInfo(paths.DocsDirPath);
+ var directoryInfo = new DirectoryInfo(Paths.DocsDirPath);
foreach (var entry in directoryInfo.GetFiles("*.razor", SearchOption.AllDirectories))
{
@@ -50,13 +50,13 @@ public bool Execute()
var src = StripComponentSource(entry.FullName);
var blocks = src.Split("@code");
- var blocks0 = Regex.Replace(blocks[0], @"?DocsFrame>", string.Empty)
+ var blocks0 = DocsFrameEndTagRegularExpression().Replace(blocks[0], string.Empty)
.Replace("@", "PlaceholdeR")
.Trim();
// Note: the @ creates problems and thus we replace it with an unlikely placeholder and in the markup replace back.
var html = formatter.GetHtmlString(blocks0, Languages.Html).Replace("PlaceholdeR", "@");
- html = AttributePostprocessing(html).Replace("@", "@");
+ html = AttributePostprocessing(html).Replace("@", "@");
var currentCode = string.Empty;
if (File.Exists(markupPath))
@@ -73,7 +73,7 @@ public bool Execute()
{
cb.AddLine(
formatter.GetHtmlString("@code" + blocks[1], Languages.CSharp)
- .Replace("@", "@")
+ .Replace("@", "@")
.ToLfLineEndings());
}
@@ -94,7 +94,7 @@ public bool Execute()
}
}
- File.WriteAllText(paths.NewFilesToBuildPath, newFiles.ToString());
+ File.WriteAllText(Paths.NewFilesToBuildPath, newFiles.ToString());
}
catch (Exception e)
{
@@ -110,21 +110,18 @@ public bool Execute()
private static string StripComponentSource(string path)
{
var source = File.ReadAllText(path, Encoding.UTF8);
- source = Regex.Replace(source, "@(namespace|layout|page) .+?\n", string.Empty);
+ source = NamespaceLayoutOrPageRegularExpression().Replace(source, string.Empty);
return source.Trim();
}
public static string AttributePostprocessing(string html)
{
- return Regex.Replace(
- html,
- @""(?'value'.*?)"",
- new MatchEvaluator(m =>
- {
- var value = m.Groups["value"].Value;
- return
- $@""{AttributeValuePostprocessing(value)}"";
- }));
+ return HtmlAttributeValueSpanRegularExpression().Replace(html, new MatchEvaluator(m =>
+ {
+ var value = m.Groups["value"].Value;
+ return
+ $@""{AttributeValuePostprocessing(value)}"";
+ }));
}
private static string AttributeValuePostprocessing(string value)
@@ -133,18 +130,33 @@ private static string AttributeValuePostprocessing(string value)
return value;
if (value is "true" or "false")
return $"{value}";
- if (Regex.IsMatch(value, "^[A-Z][A-Za-z0-9]+[.][A-Za-z][A-Za-z0-9]+$"))
+ if (AlphanumericDotAlphanumericRegularExpression().IsMatch(value))
{
var tokens = value.Split('.');
- return $"{tokens[0]}.{tokens[1]}";
+ return $"{tokens[0]}.{tokens[1]}";
}
- if (Regex.IsMatch(value, "^@[A-Za-z0-9]+$"))
+ if (AlphanumericRegularExpression().IsMatch(value))
{
- return $"{value}";
+ return $"{value}";
}
- return $"{value}";
+ return $"{value}";
}
+
+ [GeneratedRegex(@"?DocsFrame>")]
+ private static partial Regex DocsFrameEndTagRegularExpression();
+
+ [GeneratedRegex("@(namespace|layout|page) .+?\n")]
+ private static partial Regex NamespaceLayoutOrPageRegularExpression();
+
+ [GeneratedRegex(@""(?'value'.*?)"")]
+ private static partial Regex HtmlAttributeValueSpanRegularExpression();
+
+ [GeneratedRegex("^[A-Z][A-Za-z0-9]+[.][A-Za-z][A-Za-z0-9]+$")]
+ private static partial Regex AlphanumericDotAlphanumericRegularExpression();
+
+ [GeneratedRegex("^@[A-Za-z0-9]+$")]
+ private static partial Regex AlphanumericRegularExpression();
}
}
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Paths.cs b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Paths.cs
index 6da8f118..168e6dba 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Paths.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Paths.cs
@@ -3,7 +3,7 @@
namespace Cropper.Blazor.Client.Compiler;
-public class Paths
+public static class Paths
{
private const string DocsDirectory = "Client";
private const string DocStringsFile = "DocStrings.generated.cs";
@@ -27,43 +27,13 @@ public static string SrcDirPath
}
}
- public string DocsDirPath
- {
- get
- {
- return Directory.EnumerateDirectories(SrcDirPath, DocsDirectory).FirstOrDefault();
- }
- }
+ public static string DocsDirPath => Directory.EnumerateDirectories(SrcDirPath, DocsDirectory).FirstOrDefault();
- public string DocsStringSnippetsDirPath
- {
- get
- {
- return Path.Join(DocsDirPath, "Models");
- }
- }
+ public static string DocsStringSnippetsDirPath => Path.Join(DocsDirPath, "Models");
- public string SnippetsFilePath
- {
- get
- {
- return Path.Join(DocsStringSnippetsDirPath, SnippetsFile);
- }
- }
+ public static string SnippetsFilePath => Path.Join(DocsStringSnippetsDirPath, SnippetsFile);
- public string DocStringsFilePath
- {
- get
- {
- return Path.Join(DocsStringSnippetsDirPath, DocStringsFile);
- }
- }
+ public static string DocStringsFilePath => Path.Join(DocsStringSnippetsDirPath, DocStringsFile);
- public string NewFilesToBuildPath
- {
- get
- {
- return Path.Join(DocsDirPath, NewFilesToBuild);
- }
- }
+ public static string NewFilesToBuildPath => Path.Join(DocsDirPath, NewFilesToBuild);
}
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Program.cs b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Program.cs
index 2d20b197..9a6e50ac 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Program.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/Program.cs
@@ -9,9 +9,9 @@ public static int Main()
{
var stopWatch = Stopwatch.StartNew();
var success =
- CodeSnippetsCompiler.Execute()
- && new ExamplesMarkup().Execute()
- && new DocStrings().Execute();
+ CodeSnippetsCompiler.Execute()
+ && new ExamplesMarkup().Execute()
+ && new DocStrings().Execute();
Console.WriteLine($"Docs.Compiler completed in {stopWatch.ElapsedMilliseconds} msecs");
return success ? 0 : 1;
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/StyleDictionary.KebabCase.cs b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/StyleDictionary.KebabCase.cs
new file mode 100644
index 00000000..72dbbfae
--- /dev/null
+++ b/src/Cropper.Blazor/Cropper.Blazor.Client.Compiler/StyleDictionary.KebabCase.cs
@@ -0,0 +1,53 @@
+using ColorCode.Common;
+using ColorCode.Styling;
+
+namespace Cropper.Blazor.Client.Compiler
+{
+ public class StyleDictionaryKebabCase
+ {
+ ///
+ /// A theme with reference names in kebab-case style.
+ ///
+ public static StyleDictionary KebabCase
+ {
+ get
+ {
+ return new StyleDictionary
+ {
+ new Style(ScopeName.String)
+ {
+ ReferenceName = "string"
+ },
+ new Style(ScopeName.Keyword)
+ {
+ ReferenceName = "keyword"
+ },
+ new Style(ScopeName.HtmlElementName)
+ {
+ ReferenceName = "html-element-name"
+ },
+ new Style(ScopeName.HtmlAttributeName)
+ {
+ ReferenceName = "html-attribute-name"
+ },
+ new Style(ScopeName.HtmlAttributeValue)
+ {
+ ReferenceName = "html-attribute-value"
+ },
+ new Style(ScopeName.HtmlOperator)
+ {
+ ReferenceName = "html-operator"
+ },
+ new Style(ScopeName.Comment)
+ {
+ ReferenceName = "comment"
+ },
+ new Style(ScopeName.HtmlTagDelimiter)
+ {
+ ReferenceName = "html-tag-delimiter"
+ }
+ };
+ }
+ }
+ }
+}
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Shared/Cropper.Blazor.Shared.csproj b/src/Cropper.Blazor/Cropper.Blazor.Shared/Cropper.Blazor.Shared.csproj
index 77fe107c..2d0af417 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Shared/Cropper.Blazor.Shared.csproj
+++ b/src/Cropper.Blazor/Cropper.Blazor.Shared/Cropper.Blazor.Shared.csproj
@@ -1,13 +1,13 @@
-
- net8.0
- enable
- enable
-
+
+ net8.0
+ enable
+ enable
+
-
-
-
+
+
+
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/MethodInfoExtensions.cs b/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/MethodInfoExtensions.cs
index 2cf4fba3..efbe0cfa 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/MethodInfoExtensions.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/MethodInfoExtensions.cs
@@ -262,12 +262,21 @@ public static string TypeName(this Type type, Func? GenericArgum
stringBuilder.Append('>');
// Return result
- return stringBuilder.ToString().RemoveNamespace();
+ return stringBuilder.ToString();
}
public static string RemoveNamespace(this string value)
{
- return value.Split('.')[value.Split('.').Length - 1];
+ var splittedValue = value.Split('.');
+ return splittedValue[splittedValue.Length - 1];
+ }
+
+ public static (string enumName, string enumItemName) RemoveNamespaceFromEnumValue(this string value)
+ {
+ var splittedValue = value.Split('.');
+ var lengthValue = splittedValue.Length;
+
+ return (splittedValue[lengthValue - 2], splittedValue[lengthValue - 1]);
}
public static string GetFormattedReturnSignature(this MethodInfo method, bool callable = false)
@@ -285,7 +294,7 @@ public static string GetFormattedReturnSignature(this Type type, bool callable =
if (callable == false)
{
// Append return type
- stringBuilder.Append(type.TypeName(CreateLink).RemoveNamespace());
+ stringBuilder.Append(type.TypeName(CreateLink));
stringBuilder.Append(' ');
}
@@ -305,7 +314,15 @@ public static string CreateLink(this string name)
}
else if (name == "ErrorEventArgs")
{
- return $"{name}";
+ return $"{name}";
+ }
+ else if (name == "RenderFragment")
+ {
+ return $"{name}";
+ }
+ else if (name == "IJSObjectReference")
+ {
+ return $"{name}";
}
else
{
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/TypeNameHelper.cs b/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/TypeNameHelper.cs
index fd62fd37..1477b9bd 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/TypeNameHelper.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/TypeNameHelper.cs
@@ -100,7 +100,7 @@ private static void ProcessType(StringBuilder builder, Type type, DisplayNameOpt
builder.Append(type.Name);
}
else if (type.Assembly.ManifestModule.Name == "FSharp.Core.dll"
- && FSharpTypeNames.TryGetValue(type.Name, out builtInName))
+ && FSharpTypeNames.TryGetValue(type.Name, out builtInName))
{
builder.Append(builtInName);
}
@@ -173,7 +173,7 @@ private static void ProcessGenericType(StringBuilder builder, Type type, Type[]
}
if (type.Assembly.ManifestModule.Name == "FSharp.Core.dll"
- && FSharpTypeNames.TryGetValue(type.Name, out var builtInName))
+ && FSharpTypeNames.TryGetValue(type.Name, out var builtInName))
{
builder.Append(builtInName);
}
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/XmlDocumentationExtension.cs b/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/XmlDocumentationExtension.cs
index 80c9bd03..43834027 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/XmlDocumentationExtension.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.Shared/Extensions/XmlDocumentationExtension.cs
@@ -67,9 +67,9 @@ string ConvertToCsharpSource(Type type)
}
var correctGeneric = genericParameters.Dequeue();
result += (firstIteration ? string.Empty : ",") +
- (correctGeneric.IsGenericParameter
- ? showGenericParameters ? (firstIteration ? string.Empty : " ") + correctGeneric.Name : string.Empty
- : (firstIteration ? string.Empty : " ") + correctGeneric.ConvertToCSharpSource());
+ (correctGeneric.IsGenericParameter
+ ? showGenericParameters ? (firstIteration ? string.Empty : " ") + correctGeneric.Name : string.Empty
+ : (firstIteration ? string.Empty : " ") + correctGeneric.ConvertToCSharpSource());
firstIteration = false;
}
result += ">";
diff --git a/src/Cropper.Blazor/Cropper.Blazor.Sitemap.Generator/Cropper.Blazor.Sitemap.Generator.csproj b/src/Cropper.Blazor/Cropper.Blazor.Sitemap.Generator/Cropper.Blazor.Sitemap.Generator.csproj
index 7b5b20bc..1cc87412 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.Sitemap.Generator/Cropper.Blazor.Sitemap.Generator.csproj
+++ b/src/Cropper.Blazor/Cropper.Blazor.Sitemap.Generator/Cropper.Blazor.Sitemap.Generator.csproj
@@ -1,14 +1,14 @@
-
- net8.0
- enable
- enable
- Exe
-
+
+ net8.0
+ enable
+ enable
+ Exe
+
-
-
-
+
+
+
diff --git a/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Components/CropperComponent_Should.cs b/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Components/CropperComponent_Should.cs
index ce10fbb0..ad019808 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Components/CropperComponent_Should.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Components/CropperComponent_Should.cs
@@ -28,6 +28,7 @@
using Moq;
using Xunit;
using ErrorEventArgs = Microsoft.AspNetCore.Components.Web.ErrorEventArgs;
+using Options = Cropper.Blazor.Models.Options;
namespace Cropper.Blazor.UnitTests.Components
{
@@ -129,7 +130,7 @@ private async Task Should_DisposeAsync_CropperComponent_After_Render_Async()
}
[Fact]
- public async Task Should_Render_CropperComponent_SuccessfulAsync()
+ public async Task Should_Render_CropperComponent_From_Image_SuccessfulAsync()
{
// arrange
string errorLoadImageClass = "cropper-error-load";
@@ -363,24 +364,24 @@ public async Task Should_Render_CropperComponent_SuccessfulAsync()
// assert
IElement expectedElement = cropperComponent.Find($"img.{imageClass}");
- ElementReference elementReference = (ElementReference)cropperComponent.Instance
- .GetInstanceField("ImageReference");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
Guid cropperComponentId = (Guid)cropperComponent.Instance
.GetInstanceField("CropperComponentId");
_mockCropperJsInterop.Verify(c => c.LoadModuleAsync(cancellationToken), Times.Once());
- elementReference.Id.Should().NotBeNullOrEmpty();
+ elementReference!.Value.Id.Should().NotBeNullOrEmpty();
expectedElement.ClassName.Should().Be(imageClass);
expectedElement.GetAttribute("loading").Should().Be(lazyAttributeValue);
expectedElement.GetAttribute("src").Should().Be(imageSrcAttributeValue);
- expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference.Id);
+ expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference!.Value.Id);
countCallsOnLoadImageHandler.Should().Be(0);
expectedElement.TriggerEvent("onload", progressEventArgs);
countCallsOnLoadImageHandler.Should().Be(1);
_mockCropperJsInterop.Verify(c => c.InitCropperAsync(
cropperComponentId,
- elementReference,
+ elementReference!.Value,
options,
It.IsAny>(),
cancellationToken), Times.Once());
@@ -518,6 +519,369 @@ await cropperComponent.InvokeAsync(async () =>
});
}
+ [Fact]
+ public async Task Should_Render_CropperComponent_From_Canvas_SuccessfulAsync()
+ {
+ // arrange
+ string errorLoadImageClass = "cropper-error-load";
+ string imageClass = "cropper";
+ string lazyAttributeValue = "lazy";
+ Dictionary inputAttributes = new()
+ {
+ { "loading", lazyAttributeValue }
+ };
+ string imageSrcAttributeValue = "https://.../image.jpg";
+ string errorLoadImageSrcAttributeValue = "https://.../not-found-image.jpg";
+ int countCallsOnCropEventHandler = 0;
+ int countCallsOnCropEndEventHandler = 0;
+ int countCallsOnCropMoveEventHandler = 0;
+ int countCallsOnCropStartEventHandler = 0;
+ int countCallsOnZoomEventHandler = 0;
+ int countCallsOnCropReadyEventHandler = 0;
+
+ IBrowserFile imageFile = new Mock().Object;
+ CancellationToken cancellationToken = new();
+ JSEventData cropReadyEvent = new Faker>()
+ .Generate();
+ JSEventData zoomEvent = new Faker>()
+ .Generate();
+ JSEventData cropStartEvent = new Faker>()
+ .Generate();
+ JSEventData cropMoveEvent = new Faker>()
+ .Generate();
+ JSEventData cropEndEvent = new Faker>()
+ .Generate();
+ JSEventData cropEvent = new Faker>()
+ .Generate();
+ Options options = new Faker()
+ .Generate();
+ CanvasData expectedCanvasData = new Faker()
+ .Generate();
+ ContainerData expectedContainerData = new Faker()
+ .Generate();
+ CropBoxData expectedCropBoxData = new Faker()
+ .Generate();
+ GetCroppedCanvasOptions getCroppedCanvasOptions = new Faker()
+ .Generate();
+ Mock mockIJSObjectReference = new();
+ CroppedCanvas expectedCroppedCanvas = new Faker()
+ .CustomInstantiator(c => new CroppedCanvas(mockIJSObjectReference.Object));
+ CropperData expectedCropperData = new Faker()
+ .Generate();
+ ImageData expectedImageData = new Faker()
+ .Generate();
+ SetCanvasDataOptions setCanvasDataOptions = new Faker()
+ .Generate();
+ SetCropBoxDataOptions setCropBoxDataOptions = new Faker()
+ .Generate();
+ SetDataOptions setDataOptions = new Faker()
+ .Generate();
+
+ Faker faker = new();
+ string expectedCroppedCanvasDataURL = faker.Random.Word();
+ bool isRounded = faker.Random.Bool();
+ decimal degree = faker.Random.Decimal();
+ long maxAllowedSize = faker.Random.Long();
+ string expectedImage = faker.Random.Word();
+ decimal offsetX = faker.Random.Decimal();
+ decimal? offsetY = faker.Random.Decimal();
+ decimal x = faker.Random.Decimal();
+ decimal? y = faker.Random.Decimal();
+ string url = faker.Random.Word();
+ decimal scaleX = faker.Random.Decimal();
+ decimal scaleY = faker.Random.Decimal();
+ decimal aspectRatio = faker.Random.Decimal();
+ DragMode dragMode = faker.Random.Enum();
+ decimal ratio = faker.Random.Decimal();
+ decimal pivotX = faker.Random.Decimal();
+ decimal pivotY = faker.Random.Decimal();
+ string newUrlImage = faker.Random.Word();
+ bool hasSameSize = faker.Random.Bool();
+ string imageFormatType = faker.Random.Word();
+ float numberImageQuality = faker.Random.Float(0, 1);
+
+ Action>? onCropEventHandler = (JSEventData c) =>
+ {
+ countCallsOnCropEventHandler++;
+ cropEvent.Should().BeEquivalentTo(c);
+ };
+ Action>? onCropEndEventHandler = (JSEventData c) =>
+ {
+ countCallsOnCropEndEventHandler++;
+ cropEndEvent.Should().BeEquivalentTo(c);
+ };
+ Action>? onCropMoveEventHandler = (JSEventData c) =>
+ {
+ countCallsOnCropMoveEventHandler++;
+ cropMoveEvent.Should().BeEquivalentTo(c);
+ };
+ Action>? onCropStartEventHandler = (JSEventData c) =>
+ {
+ countCallsOnCropStartEventHandler++;
+ cropStartEvent.Should().BeEquivalentTo(c);
+ };
+ Action>? onZoomEventHandler = (JSEventData z) =>
+ {
+ countCallsOnZoomEventHandler++;
+ zoomEvent.Should().BeEquivalentTo(z);
+ };
+ Action>? onCropReadyEventHandler = (JSEventData c) =>
+ {
+ countCallsOnCropReadyEventHandler++;
+ cropReadyEvent.Should().BeEquivalentTo(c);
+ };
+
+ ComponentParameter imageClassParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.Class),
+ imageClass);
+ ComponentParameter errorLoadImageClassParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.ErrorLoadImageClass),
+ errorLoadImageClass);
+ ComponentParameter loadingParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.InputAttributes),
+ inputAttributes);
+ ComponentParameter errorLoadImageSrcParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.ErrorLoadImageSrc),
+ errorLoadImageSrcAttributeValue);
+ ComponentParameter srcParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.Src),
+ imageSrcAttributeValue);
+ ComponentParameter isErrorLoadImageParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.IsErrorLoadImage),
+ false);
+ ComponentParameter isAvailableInitCropperParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.IsAvailableInitCropper),
+ true);
+ ComponentParameter optionsParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.Options),
+ options);
+ ComponentParameter onCropEventParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.OnCropEvent),
+ onCropEventHandler);
+ ComponentParameter onCropEndEventParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.OnCropEndEvent),
+ onCropEndEventHandler);
+ ComponentParameter onCropMoveEventParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.OnCropMoveEvent),
+ onCropMoveEventHandler);
+ ComponentParameter onCropStartEventParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.OnCropStartEvent),
+ onCropStartEventHandler);
+ ComponentParameter onZoomEventParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.OnZoomEvent),
+ onZoomEventHandler);
+ ComponentParameter onReadyEventParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.OnReadyEvent),
+ onCropReadyEventHandler);
+ ComponentParameter cropperComponentTypeParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.CropperComponentType),
+ CropperComponentType.Canvas);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetCanvasDataAsync(It.IsAny(), cancellationToken))
+ .ReturnsAsync(expectedCanvasData);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetContainerDataAsync(It.IsAny(), cancellationToken))
+ .ReturnsAsync(expectedContainerData);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetCropBoxDataAsync(It.IsAny(), cancellationToken))
+ .ReturnsAsync(expectedCropBoxData);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetCroppedCanvasAsync(It.IsAny(), getCroppedCanvasOptions, cancellationToken))
+ .ReturnsAsync(expectedCroppedCanvas);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetCroppedCanvasDataURLAsync(
+ It.IsAny(),
+ getCroppedCanvasOptions,
+ imageFormatType,
+ numberImageQuality,
+ cancellationToken))
+ .ReturnsAsync(expectedCroppedCanvasDataURL);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetDataAsync(It.IsAny(), isRounded, cancellationToken))
+ .ReturnsAsync(expectedCropperData);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetImageDataAsync(It.IsAny(), cancellationToken))
+ .ReturnsAsync(expectedImageData);
+
+ _mockCropperJsInterop
+ .Setup(c => c.GetImageUsingStreamingAsync(imageFile, maxAllowedSize, cancellationToken))
+ .ReturnsAsync(expectedImage);
+
+ // act
+ IRenderedComponent cropperComponent = _testContext
+ .RenderComponent(
+ errorLoadImageClassParameter,
+ loadingParameter,
+ errorLoadImageSrcParameter,
+ isErrorLoadImageParameter,
+ isAvailableInitCropperParameter,
+ srcParameter,
+ imageClassParameter,
+ optionsParameter,
+ onCropEventParameter,
+ onCropEndEventParameter,
+ onCropMoveEventParameter,
+ onCropStartEventParameter,
+ onZoomEventParameter,
+ onReadyEventParameter,
+ cropperComponentTypeParameter);
+
+ // assert
+ IElement expectedElement = cropperComponent.Find($"canvas.{imageClass}");
+ ElementReference? elementReference = cropperComponent.Instance.GetCropperElementReference();
+ Guid cropperComponentId = (Guid)cropperComponent.Instance
+ .GetInstanceField("CropperComponentId");
+
+ _mockCropperJsInterop.Verify(c => c.LoadModuleAsync(cancellationToken), Times.Once());
+ elementReference!.Value.Id.Should().NotBeNullOrEmpty();
+ expectedElement.ClassName.Should().Be(imageClass);
+ expectedElement.GetAttribute("loading").Should().Be(lazyAttributeValue);
+ expectedElement.GetAttribute("src").Should().Be(null);
+ expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference!.Value.Id);
+
+ _mockCropperJsInterop.Verify(c => c.InitCropperAsync(
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny>(),
+ It.IsAny()), Times.Never());
+
+ expectedElement.HasAttribute("onload").Should().BeFalse();
+ expectedElement.HasAttribute("onerror").Should().BeFalse();
+
+ await cropperComponent.InvokeAsync(async () =>
+ {
+ cropperComponent.Instance.Clear();
+ _mockCropperJsInterop.Verify(c => c.ClearAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.Crop();
+ _mockCropperJsInterop.Verify(c => c.CropAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.CropperIsCroped(cropEvent);
+ countCallsOnCropEventHandler.Should().Be(1);
+
+ cropperComponent.Instance.CropperIsEnded(cropEndEvent);
+ countCallsOnCropEndEventHandler.Should().Be(1);
+
+ cropperComponent.Instance.CropperIsMoved(cropMoveEvent);
+ countCallsOnCropMoveEventHandler.Should().Be(1);
+
+ cropperComponent.Instance.CropperIsStarted(cropStartEvent);
+ countCallsOnCropStartEventHandler.Should().Be(1);
+
+ cropperComponent.Instance.CropperIsZoomed(zoomEvent);
+ countCallsOnZoomEventHandler.Should().Be(1);
+
+ cropperComponent.Instance.Destroy();
+ _mockCropperJsInterop.Verify(c => c.DestroyAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.Disable();
+ _mockCropperJsInterop.Verify(c => c.DisableAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.Enable();
+ _mockCropperJsInterop.Verify(c => c.EnableAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ CanvasData canvasData = await cropperComponent.Instance.GetCanvasDataAsync();
+ expectedCanvasData.Should().BeEquivalentTo(canvasData);
+ _mockCropperJsInterop.Verify(c => c.GetCanvasDataAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ ContainerData containerData = await cropperComponent.Instance.GetContainerDataAsync();
+ expectedContainerData.Should().BeEquivalentTo(containerData);
+ _mockCropperJsInterop.Verify(c => c.GetContainerDataAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ CropBoxData cropBoxData = await cropperComponent.Instance.GetCropBoxDataAsync();
+ expectedCropBoxData.Should().BeEquivalentTo(cropBoxData);
+ _mockCropperJsInterop.Verify(c => c.GetCropBoxDataAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ object croppedCanvas = await cropperComponent.Instance.GetCroppedCanvasAsync(getCroppedCanvasOptions);
+ expectedCroppedCanvas.Should().BeEquivalentTo(croppedCanvas);
+ _mockCropperJsInterop.Verify(c => c.GetCroppedCanvasAsync(cropperComponentId, getCroppedCanvasOptions, cancellationToken), Times.Once());
+
+ string croppedCanvasDataURL = await cropperComponent.Instance.GetCroppedCanvasDataURLAsync(getCroppedCanvasOptions, imageFormatType, numberImageQuality);
+ expectedCroppedCanvasDataURL.Should().BeEquivalentTo(croppedCanvasDataURL);
+ _mockCropperJsInterop.Verify(c => c.GetCroppedCanvasDataURLAsync(cropperComponentId, getCroppedCanvasOptions, imageFormatType, numberImageQuality, cancellationToken), Times.Once());
+
+ CropperData cropperData = await cropperComponent.Instance.GetDataAsync(isRounded);
+ expectedCropperData.Should().BeEquivalentTo(cropperData);
+ _mockCropperJsInterop.Verify(c => c.GetDataAsync(cropperComponentId, isRounded, cancellationToken), Times.Once());
+
+ ImageData imageData = await cropperComponent.Instance.GetImageDataAsync();
+ expectedImageData.Should().Be(imageData);
+ _mockCropperJsInterop.Verify(c => c.GetImageDataAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ await cropperComponent.Instance.ReplaceAsync(newUrlImage, hasSameSize);
+ _mockCropperJsInterop.Verify(c => c.ReplaceAsync(cropperComponentId, newUrlImage, hasSameSize, cancellationToken), Times.Once());
+ cropperComponent.Instance.Src.Should().BeEquivalentTo(newUrlImage);
+
+ string image = await cropperComponent.Instance.GetImageUsingStreamingAsync(imageFile, maxAllowedSize, cancellationToken);
+ expectedImage.Should().Be(image);
+ _mockCropperJsInterop.Verify(c => c.GetImageUsingStreamingAsync(imageFile, maxAllowedSize, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.IsReady(cropReadyEvent);
+ countCallsOnCropReadyEventHandler.Should().Be(1);
+
+ cropperComponent.Instance.Move(offsetX, offsetY);
+ _mockCropperJsInterop.Verify(c => c.MoveAsync(cropperComponentId, offsetX, offsetY, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.MoveTo(x, y);
+ _mockCropperJsInterop.Verify(c => c.MoveToAsync(cropperComponentId, x, y, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.Reset();
+ _mockCropperJsInterop.Verify(c => c.ResetAsync(cropperComponentId, cancellationToken), Times.Once());
+
+ await cropperComponent.Instance.RevokeObjectUrlAsync(url);
+ _mockCropperJsInterop.Verify(c => c.RevokeObjectUrlAsync(url, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.Rotate(degree);
+ _mockCropperJsInterop.Verify(c => c.RotateAsync(cropperComponentId, degree, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.Scale(scaleX, scaleY);
+ _mockCropperJsInterop.Verify(c => c.ScaleAsync(cropperComponentId, scaleX, scaleY, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.ScaleX(scaleX);
+ _mockCropperJsInterop.Verify(c => c.ScaleXAsync(cropperComponentId, scaleX, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.ScaleY(scaleY);
+ _mockCropperJsInterop.Verify(c => c.ScaleYAsync(cropperComponentId, scaleY, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.SetAspectRatio(aspectRatio);
+ _mockCropperJsInterop.Verify(c => c.SetAspectRatioAsync(cropperComponentId, aspectRatio, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.SetCanvasData(setCanvasDataOptions);
+ _mockCropperJsInterop.Verify(c => c.SetCanvasDataAsync(cropperComponentId, setCanvasDataOptions, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.SetCropBoxData(setCropBoxDataOptions);
+ _mockCropperJsInterop.Verify(c => c.SetCropBoxDataAsync(cropperComponentId, setCropBoxDataOptions, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.SetData(setDataOptions);
+ _mockCropperJsInterop.Verify(c => c.SetDataAsync(cropperComponentId, setDataOptions, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.SetDragMode(dragMode);
+ _mockCropperJsInterop.Verify(c => c.SetDragModeAsync(cropperComponentId, dragMode, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.Zoom(ratio);
+ _mockCropperJsInterop.Verify(c => c.ZoomAsync(cropperComponentId, ratio, cancellationToken), Times.Once());
+
+ cropperComponent.Instance.ZoomTo(ratio, pivotX, pivotY);
+ _mockCropperJsInterop.Verify(c => c.ZoomToAsync(cropperComponentId, ratio, pivotX, pivotY, cancellationToken), Times.Once());
+
+ await cropperComponent.Instance.DisposeAsync();
+ _mockCropperJsInterop.Verify(c => c.DisposeAsync(), Times.Once());
+ _mockCropperJsInterop.Verify(c => c.DestroyAsync(cropperComponentId, cancellationToken), Times.Exactly(2));
+
+ cropperComponent.Instance.Dispose();
+ _mockCropperJsInterop.Verify(c => c.DisposeAsync(), Times.Exactly(2));
+ _mockCropperJsInterop.Verify(c => c.DestroyAsync(cropperComponentId, cancellationToken), Times.Exactly(3));
+ });
+ }
+
[Fact]
public void Should_Render_CropperComponent_With_ErrorLoadImage_Parameter()
{
@@ -555,10 +919,10 @@ public void Should_Render_CropperComponent_With_ErrorLoadImage_Parameter()
// assert
IElement expectedElement = cropperComponent.Find($"img.{errorLoadImageClass}");
- ElementReference elementReference = (ElementReference)cropperComponent.Instance
- .GetInstanceField("ImageReference");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
- elementReference.Id.Should().BeNullOrEmpty();
+ elementReference.Should().BeNull();
expectedElement.ClassName.Should().Be(errorLoadImageClass);
expectedElement.GetAttribute("loading").Should().Be(lazyAttributeValue);
expectedElement.GetAttribute("src").Should().Be(errorLoadImageSrcAttributeValue);
@@ -573,6 +937,56 @@ public void Should_Render_CropperComponent_With_ErrorLoadImage_Parameter()
It.IsAny()), Times.Never());
}
+ [Fact]
+ public void Should_Render_CropperComponent_With_ErrorLoadImageContent_Parameter()
+ {
+ // arrange
+ RenderFragment errorLoadImageContent = builder =>
+ {
+ builder.OpenElement(0, "div");
+ builder.AddAttribute(1, "class", "error-img");
+ builder.CloseElement();
+ };
+ Dictionary inputAttributes = new()
+ {
+ { "loading", "lazy" },
+ { "Attribute_TEST", "TEST_VALUE" },
+ { "src", "new_src" }
+ };
+
+ ComponentParameter errorLoadImageContentParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.ErrorLoadImageContent),
+ errorLoadImageContent);
+ ComponentParameter loadingParameter = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.InputAttributes),
+ inputAttributes);
+ ComponentParameter isErrorLoadImage = ComponentParameter.CreateParameter(
+ nameof(CropperComponent.IsErrorLoadImage),
+ true);
+
+ // act
+ IRenderedComponent cropperComponent = _testContext
+ .RenderComponent(
+ errorLoadImageContentParameter,
+ loadingParameter,
+ isErrorLoadImage);
+
+ // assert
+ IElement expectedElement = cropperComponent.Find("div.error-img");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
+
+ elementReference.Should().BeNull();
+ expectedElement.ClassName.Should().Be("error-img");
+
+ _mockCropperJsInterop.Verify(c => c.InitCropperAsync(
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny(),
+ It.IsAny>(),
+ It.IsAny()), Times.Never());
+ }
+
[Fact]
public void Should_Not_Render_CropperComponent_With_IsNotAvaibleInitCropper_Parameter()
{
@@ -614,10 +1028,10 @@ public void Should_Not_Render_CropperComponent_With_IsNotAvaibleInitCropper_Para
// assert
IElement expectedElement = cropperComponent.Find($"img.{errorLoadImageClass}");
- ElementReference elementReference = (ElementReference)cropperComponent.Instance
- .GetInstanceField("ImageReference");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
- elementReference.Id.Should().BeNullOrEmpty();
+ elementReference.Should().BeNull();
expectedElement.ClassName.Should().Be(errorLoadImageClass);
expectedElement.GetAttribute("loading").Should().Be(lazyAttributeValue);
expectedElement.GetAttribute("src").Should().Be(errorLoadImageSrcAttributeValue);
@@ -681,16 +1095,16 @@ public void Should_Render_CropperComponent_With_IsNotAvaibleInitCropper_Paramete
// assert
IElement expectedElement = cropperComponent.Find($"img");
- ElementReference elementReference = (ElementReference)cropperComponent.Instance
- .GetInstanceField("ImageReference");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
Guid cropperComponentId = (Guid)cropperComponent.Instance
.GetInstanceField("CropperComponentId");
_mockCropperJsInterop.Verify(c => c.LoadModuleAsync(cancellationToken), Times.Once());
- elementReference.Id.Should().NotBeNullOrEmpty();
+ elementReference!.Value.Id.Should().NotBeNullOrEmpty();
expectedElement.ClassName.Should().BeNull();
expectedElement.GetAttribute("src").Should().BeNull();
- expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference.Id);
+ expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference!.Value.Id);
countCallsOnLoadImageHandler.Should().Be(0);
expectedElement.TriggerEvent("onload", progressEventArgs);
@@ -746,16 +1160,16 @@ public void Should_Render_CropperComponent_With_IsNotAvaibleInitCropper_Paramete
// assert
IElement expectedElement = cropperComponent.Find($"img");
- ElementReference elementReference = (ElementReference)cropperComponent.Instance
- .GetInstanceField("ImageReference");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
Guid cropperComponentId = (Guid)cropperComponent.Instance
.GetInstanceField("CropperComponentId");
_mockCropperJsInterop.Verify(c => c.LoadModuleAsync(cancellationToken), Times.Once());
- elementReference.Id.Should().NotBeNullOrEmpty();
+ elementReference!.Value.Id.Should().NotBeNullOrEmpty();
expectedElement.ClassName.Should().BeNull();
expectedElement.GetAttribute("src").Should().BeNull();
- expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference.Id);
+ expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference!.Value.Id);
countCallsOnLoadImageHandler.Should().Be(0);
expectedElement.TriggerEvent("onload", progressEventArgs);
@@ -825,21 +1239,21 @@ public async Task Should_Render_CropperComponent_Without_Action_Parameters_Succe
// assert
IElement expectedElement = cropperComponent.Find($"img");
- ElementReference elementReference = (ElementReference)cropperComponent.Instance
- .GetInstanceField("ImageReference");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
Guid cropperComponentId = (Guid)cropperComponent.Instance
.GetInstanceField("CropperComponentId");
_mockCropperJsInterop.Verify(c => c.LoadModuleAsync(cancellationToken), Times.Once());
- elementReference.Id.Should().NotBeNullOrEmpty();
+ elementReference!.Value.Id.Should().NotBeNullOrEmpty();
expectedElement.ClassName.Should().BeNull();
expectedElement.GetAttribute("src").Should().BeNull();
- expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference.Id);
+ expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference!.Value.Id);
expectedElement.TriggerEvent("onload", progressEventArgs);
_mockCropperJsInterop.Verify(c => c.InitCropperAsync(
cropperComponentId,
- elementReference,
+ elementReference!.Value,
options,
It.IsAny>(),
cancellationToken), Times.Once());
@@ -876,21 +1290,21 @@ public async Task Should_Render_CropperComponent_Without_Options_Parameter_Succe
// assert
IElement expectedElement = cropperComponent.Find($"img");
- ElementReference elementReference = (ElementReference)cropperComponent.Instance
- .GetInstanceField("ImageReference");
+ ElementReference? elementReference = cropperComponent.Instance
+ .GetCropperElementReference();
Guid cropperComponentId = (Guid)cropperComponent.Instance
.GetInstanceField("CropperComponentId");
_mockCropperJsInterop.Verify(c => c.LoadModuleAsync(cancellationToken), Times.Once());
- elementReference.Id.Should().NotBeNullOrEmpty();
+ elementReference!.Value.Id.Should().NotBeNullOrEmpty();
expectedElement.ClassName.Should().BeNull();
expectedElement.GetAttribute("src").Should().BeNull();
- expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference.Id);
+ expectedElement.GetAttribute("blazor:elementreference").Should().Be(elementReference!.Value.Id);
expectedElement.TriggerEvent("onload", progressEventArgs);
_mockCropperJsInterop.Verify(c => c.InitCropperAsync(
cropperComponentId,
- elementReference,
+ elementReference!.Value,
It.Is(o => VerifyOptions(o)),
It.IsAny>(),
cancellationToken), Times.Once());
diff --git a/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Cropper.Blazor.UnitTests.csproj b/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Cropper.Blazor.UnitTests.csproj
index 055070af..21f88d45 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Cropper.Blazor.UnitTests.csproj
+++ b/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Cropper.Blazor.UnitTests.csproj
@@ -8,17 +8,17 @@
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -26,18 +26,18 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
-
+
-
+
-
+
@@ -45,16 +45,16 @@
-
-
-
- true
- cobertura
- ExcludeFromCodeCoverageAttribute
- [Cropper.Blazor]*
- **/*.g.cs
- true
- ./
-
+
+
+
+ true
+ cobertura
+ ExcludeFromCodeCoverageAttribute
+ [Cropper.Blazor]*
+ **/*.g.cs
+ true
+ ./
+
diff --git a/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Services/CropperJsInterop_Should.cs b/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Services/CropperJsInterop_Should.cs
index a9c6f235..7c515484 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Services/CropperJsInterop_Should.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor.UnitTests/Services/CropperJsInterop_Should.cs
@@ -335,7 +335,7 @@ public async Task Verify_GetImageUsingStreamingAsync()
using DotNetStreamReference dotnetImageStream = new(jsImageStream);
_testContext.JSInterop
.Setup("cropper.getImageUsingStreaming",
- jSRuntimeInvocation => jSRuntimeInvocation.Arguments.Count == 1 && VerifyStreamArgument(jSRuntimeInvocation))
+ jSRuntimeInvocation => jSRuntimeInvocation.Arguments.Count == 1 && VerifyStreamArgument(jSRuntimeInvocation))
.SetResult(expectedImageData);
bool VerifyStreamArgument(JSRuntimeInvocation jSRuntimeInvocation)
diff --git a/src/Cropper.Blazor/Cropper.Blazor.sln b/src/Cropper.Blazor/Cropper.Blazor.sln
index 157f7c8b..1e70a019 100644
--- a/src/Cropper.Blazor/Cropper.Blazor.sln
+++ b/src/Cropper.Blazor/Cropper.Blazor.sln
@@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cropper.Blazor.Testing", "C
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{624968C7-925A-4896-8405-4174FD48B9BC}"
ProjectSection(SolutionItems) = preProject
+ ..\..\.editorconfig = ..\..\.editorconfig
+ ..\..\.gitattributes = ..\..\.gitattributes
..\..\.github\CODE_OF_CONDUCT.md = ..\..\.github\CODE_OF_CONDUCT.md
..\..\.github\PULL_REQUEST_TEMPLATE.md = ..\..\.github\PULL_REQUEST_TEMPLATE.md
..\..\README.md = ..\..\README.md
@@ -24,6 +26,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "linters", "linters", "{42196427-7CE7-4B56-BAA3-717B1CB6C245}"
ProjectSection(SolutionItems) = preProject
+ ..\..\.github\linters\.checkov.yaml = ..\..\.github\linters\.checkov.yaml
..\..\.github\linters\.htmlhintrc = ..\..\.github\linters\.htmlhintrc
..\..\.github\linters\.jscpd.json = ..\..\.github\linters\.jscpd.json
..\..\.github\linters\.stylelintrc.json = ..\..\.github\linters\.stylelintrc.json
@@ -31,8 +34,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "linters", "linters", "{4219
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{378A2956-8E21-434D-9480-9D4E0732098B}"
ProjectSection(SolutionItems) = preProject
+ ..\..\.github\workflows\build-test-template.yml = ..\..\.github\workflows\build-test-template.yml
..\..\.github\workflows\cd.yml = ..\..\.github\workflows\cd.yml
..\..\.github\workflows\ci.yml = ..\..\.github\workflows\ci.yml
+ ..\..\.github\workflows\dependabot-ci.yml = ..\..\.github\workflows\dependabot-ci.yml
..\..\.github\dependabot.yml = ..\..\.github\dependabot.yml
..\..\.github\workflows\release.yml = ..\..\.github\workflows\release.yml
EndProjectSection
diff --git a/src/Cropper.Blazor/Cropper.Blazor/.config/dotnet-tools.json b/src/Cropper.Blazor/Cropper.Blazor/.config/dotnet-tools.json
index bf2cbcf3..ccc65f95 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/.config/dotnet-tools.json
+++ b/src/Cropper.Blazor/Cropper.Blazor/.config/dotnet-tools.json
@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"excubo.webcompiler": {
- "version": "3.5.79",
+ "version": "3.9.0",
"commands": [
"webcompiler"
]
diff --git a/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor b/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor
index 4e7a93ae..d32c875c 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor
+++ b/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor
@@ -1,16 +1,33 @@
-@if (IsErrorLoadImage == true)
+@using Models;
+
+@if (IsErrorLoadImage == true)
{
-
+ @if (ErrorLoadImageContent is null)
+ {
+
+ }
+ else
+ {
+ @ErrorLoadImageContent
+ }
}
else
{
-
+ if (CropperComponentType == Models.CropperComponentType.Canvas)
+ {
+
+ }
+ else
+ {
+
+ }
}
diff --git a/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor.cs b/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor.cs
index 92de5e27..277b2eb8 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor/Components/CropperComponent.razor.cs
@@ -30,7 +30,12 @@ public partial class CropperComponent : ICropperComponentBase, IAsyncDisposable,
///
/// Gets a reference to the img HTML element rendered by the component.
///
- private ElementReference ImageReference;
+ private ElementReference? ImageReference;
+
+ ///
+ /// Gets a reference to the canvas HTML element rendered by the component.
+ ///
+ private ElementReference? CanvasReference;
///
/// The unique identifier of the cropper component.
@@ -49,6 +54,13 @@ public partial class CropperComponent : ICropperComponentBase, IAsyncDisposable,
[Parameter]
public string Src { get; set; } = null!;
+ ///
+ /// Specifies the target element for cropping, the default value is .
+ /// In addition, for type requires manual uploading of images into canvas HTMl element, including error handling.
+ ///
+ [Parameter]
+ public CropperComponentType CropperComponentType { get; set; } = CropperComponentType.Image;
+
///
/// Specifies the path to the image when loading from src fails.
///
@@ -67,6 +79,12 @@ public partial class CropperComponent : ICropperComponentBase, IAsyncDisposable,
[Parameter]
public bool IsErrorLoadImage { get; set; }
+ ///
+ /// Content is shown instead of the default error image.
+ ///
+ [Parameter]
+ public RenderFragment? ErrorLoadImageContent { get; set; }
+
///
/// Responsible for allowing the initialization of the cropper after a successful image download, the default is always allowed (true).
/// In addition, it should be used to disable re-initialization (replace image) of cropper after successful image load when set to false.
@@ -169,7 +187,29 @@ protected override void OnInitialized()
}
///
- /// This event is fired when the image is loaded.
+ /// Returns the reference to the cropper element, which can be either a canvas or an image, depending on the .
+ /// If an error occurs while loading the image (when equal to true), null is returned.
+ ///
+ /// A representing reference to the cropper element.
+ public ElementReference? GetCropperElementReference()
+ {
+ if (IsErrorLoadImage)
+ {
+ return null;
+ }
+
+ if (CropperComponentType == CropperComponentType.Canvas)
+ {
+ return CanvasReference;
+ }
+ else
+ {
+ return ImageReference;
+ }
+ }
+
+ ///
+ /// This event is fired when an image is loaded or called manually.
///
///
/// If successful, outputs a which is
@@ -203,8 +243,19 @@ public void OnErrorLoadImage(ErrorEventArgs errorEventArgs)
public void InitCropper(CancellationToken cancellationToken = default)
{
ICropperComponentBase cropperComponentBase = this;
- CropperJsIntertop!.InitCropperAsync(CropperComponentId, ImageReference, Options!, DotNetObjectReference.Create(cropperComponentBase), cancellationToken);
- OnLoadImageEvent?.Invoke();
+ ElementReference? cropperElementReference = GetCropperElementReference();
+
+ if (cropperElementReference.HasValue)
+ {
+ CropperJsIntertop!.InitCropperAsync(
+ CropperComponentId,
+ cropperElementReference.Value,
+ Options!,
+ DotNetObjectReference.Create(cropperComponentBase),
+ cancellationToken);
+
+ OnLoadImageEvent?.Invoke();
+ }
}
///
diff --git a/src/Cropper.Blazor/Cropper.Blazor/Cropper.Blazor.csproj b/src/Cropper.Blazor/Cropper.Blazor/Cropper.Blazor.csproj
index 72c6e392..f72aaf69 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/Cropper.Blazor.csproj
+++ b/src/Cropper.Blazor/Cropper.Blazor/Cropper.Blazor.csproj
@@ -14,7 +14,7 @@
- 1.3.2
+ 1.3.3
LICENSE
NuGet.png
Cropper.Blazor
@@ -114,15 +114,15 @@
-
+
-
+
-
+
diff --git a/src/Cropper.Blazor/Cropper.Blazor/Models/CropperComponentType.cs b/src/Cropper.Blazor/Cropper.Blazor/Models/CropperComponentType.cs
new file mode 100644
index 00000000..5c669b17
--- /dev/null
+++ b/src/Cropper.Blazor/Cropper.Blazor/Models/CropperComponentType.cs
@@ -0,0 +1,22 @@
+using System.Runtime.Serialization;
+
+namespace Cropper.Blazor.Models
+{
+ ///
+ /// Enumeration of cropper component types.
+ ///
+ public enum CropperComponentType
+ {
+ ///
+ /// Specifies the target image element for cropping.
+ ///
+ [EnumMember(Value = "image")]
+ Image,
+
+ ///
+ /// Specifies the target canvas element for cropping.
+ ///
+ [EnumMember(Value = "canvas")]
+ Canvas
+ }
+}
diff --git a/src/Cropper.Blazor/Cropper.Blazor/Models/GetCroppedCanvasOptions.cs b/src/Cropper.Blazor/Cropper.Blazor/Models/GetCroppedCanvasOptions.cs
index ff1b3a5a..b5970e0b 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/Models/GetCroppedCanvasOptions.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor/Models/GetCroppedCanvasOptions.cs
@@ -61,4 +61,4 @@ public class GetCroppedCanvasOptions
///
public bool? Rounded { get; set; } = false;
}
-}
\ No newline at end of file
+}
diff --git a/src/Cropper.Blazor/Cropper.Blazor/Services/CropperJsInterop.cs b/src/Cropper.Blazor/Cropper.Blazor/Services/CropperJsInterop.cs
index 6a179b31..48f29a17 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/Services/CropperJsInterop.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor/Services/CropperJsInterop.cs
@@ -884,4 +884,4 @@ protected virtual async ValueTask DisposeAsyncCore()
Module = null;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Cropper.Blazor/Cropper.Blazor/Services/ICropperJsInterop.cs b/src/Cropper.Blazor/Cropper.Blazor/Services/ICropperJsInterop.cs
index 4cb47894..72a578de 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/Services/ICropperJsInterop.cs
+++ b/src/Cropper.Blazor/Cropper.Blazor/Services/ICropperJsInterop.cs
@@ -419,4 +419,4 @@ ValueTask RevokeObjectUrlAsync(
/// A representing any asynchronous operation.
ValueTask DisposeAsync();
}
-}
\ No newline at end of file
+}
diff --git a/src/Cropper.Blazor/Cropper.Blazor/wwwroot/cropper.min.js b/src/Cropper.Blazor/Cropper.Blazor/wwwroot/cropper.min.js
index 959d89fe..3102cb54 100644
--- a/src/Cropper.Blazor/Cropper.Blazor/wwwroot/cropper.min.js
+++ b/src/Cropper.Blazor/Cropper.Blazor/wwwroot/cropper.min.js
@@ -1,10 +1,10 @@
/*!
- * Cropper.js v1.6.1
+ * Cropper.js v1.6.2
* https://fengyuanchen.github.io/cropperjs
*
* Copyright 2015-present Chen Fengyuan
* Released under the MIT license
*
- * Date: 2023-09-17T03:44:19.860Z
+ * Date: 2024-04-21T07:43:05.335Z
*/
-!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Cropper=e()}(this,function(){"use strict";function C(e,t){var i,a=Object.keys(e);return Object.getOwnPropertySymbols&&(i=Object.getOwnPropertySymbols(e),t&&(i=i.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),a.push.apply(a,i)),a}function S(a){for(var t=1;tt.length)&&(e=t.length);for(var i=0,a=new Array(e);it.width?3===i?o=t.height*e:h=t.width/e:3===i?h=t.width/e:o=t.height*e,{aspectRatio:e,naturalWidth:n,naturalHeight:a,width:o,height:h});this.canvasData=e,this.limited=1===i||2===i,this.limitCanvas(!0,!0),e.width=Math.min(Math.max(e.width,e.minWidth),e.maxWidth),e.height=Math.min(Math.max(e.height,e.minHeight),e.maxHeight),e.left=(t.width-e.width)/2,e.top=(t.height-e.height)/2,e.oldLeft=e.left,e.oldTop=e.top,this.initialCanvasData=g({},e)},limitCanvas:function(t,e){var i=this.options,a=this.containerData,n=this.canvasData,o=this.cropBoxData,h=i.viewMode,r=n.aspectRatio,s=this.cropped&&o;t&&(t=Number(i.minCanvasWidth)||0,i=Number(i.minCanvasHeight)||0,1=a.width&&(n.minLeft=Math.min(0,r),n.maxLeft=Math.max(0,r)),n.height>=a.height)&&(n.minTop=Math.min(0,t),n.maxTop=Math.max(0,t))):(n.minLeft=-n.width,n.minTop=-n.height,n.maxLeft=a.width,n.maxTop=a.height))},renderCanvas:function(t,e){var i,a,n,o,h=this.canvasData,r=this.imageData;e&&(e={width:r.naturalWidth*Math.abs(r.scaleX||1),height:r.naturalHeight*Math.abs(r.scaleY||1),degree:r.rotate||0},r=e.width,o=e.height,e=e.degree,i=90==(e=Math.abs(e)%180)?{width:o,height:r}:(a=e%90*Math.PI/180,i=Math.sin(a),n=r*(a=Math.cos(a))+o*i,r=r*i+o*a,90h.maxWidth||h.widthh.maxHeight||h.heighte.width?a.height=a.width/i:a.width=a.height*i),this.cropBoxData=a,this.limitCropBox(!0,!0),a.width=Math.min(Math.max(a.width,a.minWidth),a.maxWidth),a.height=Math.min(Math.max(a.height,a.minHeight),a.maxHeight),a.width=Math.max(a.minWidth,a.width*t),a.height=Math.max(a.minHeight,a.height*t),a.left=e.left+(e.width-a.width)/2,a.top=e.top+(e.height-a.height)/2,a.oldLeft=a.left,a.oldTop=a.top,this.initialCropBoxData=g({},a)},limitCropBox:function(t,e){var i,a,n=this.options,o=this.containerData,h=this.canvasData,r=this.cropBoxData,s=this.limited,c=n.aspectRatio;t&&(t=Number(n.minCropBoxWidth)||0,n=Number(n.minCropBoxHeight)||0,i=s?Math.min(o.width,h.width,h.width+h.left,o.width-h.left):o.width,a=s?Math.min(o.height,h.height,h.height+h.top,o.height-h.top):o.height,t=Math.min(t,o.width),n=Math.min(n,o.height),c&&(t&&n?ti.maxWidth||i.widthi.maxHeight||i.height=e.width&&i.height>=e.height?q:I),f(this.cropBox,g({width:i.width,height:i.height},x({translateX:i.left,translateY:i.top}))),this.cropped&&this.limited&&this.limitCanvas(!0,!0),this.disabled||this.output()},output:function(){this.preview(),y(this.element,tt,this.getData())}},i={initPreview:function(){var t=this.element,i=this.crossOrigin,e=this.options.preview,a=i?this.crossOriginUrl:this.url,n=t.alt||"The image to preview",o=document.createElement("img");i&&(o.crossOrigin=i),o.src=a,o.alt=n,this.viewBox.appendChild(o),this.viewBoxImage=o,e&&("string"==typeof(o=e)?o=t.ownerDocument.querySelectorAll(e):e.querySelector&&(o=[e]),z(this.previews=o,function(t){var e=document.createElement("img");w(t,m,{width:t.offsetWidth,height:t.offsetHeight,html:t.innerHTML}),i&&(e.crossOrigin=i),e.src=a,e.alt=n,e.style.cssText='display:block;width:100%;height:auto;min-width:0!important;min-height:0!important;max-width:none!important;max-height:none!important;image-orientation:0deg!important;"',t.innerHTML="",t.appendChild(e)}))},resetPreview:function(){z(this.previews,function(e){var i=Bt(e,m),i=(f(e,{width:i.width,height:i.height}),e.innerHTML=i.html,e),e=m;if(o(i[e]))try{delete i[e]}catch(t){i[e]=void 0}else if(i.dataset)try{delete i.dataset[e]}catch(t){i.dataset[e]=void 0}else i.removeAttribute("data-".concat(Dt(e)))})},preview:function(){var h=this.imageData,t=this.canvasData,e=this.cropBoxData,r=e.width,s=e.height,c=h.width,d=h.height,l=e.left-t.left-h.left,p=e.top-t.top-h.top;this.cropped&&!this.disabled&&(f(this.viewBoxImage,g({width:c,height:d},x(g({translateX:-l,translateY:-p},h)))),z(this.previews,function(t){var e=Bt(t,m),i=e.width,e=e.height,a=i,n=e,o=1;r&&(n=s*(o=i/r)),s&&eMath.abs(a-1)?i:a)&&(t.restore&&(o=this.getCanvasData(),h=this.getCropBoxData()),this.render(),t.restore)&&(this.setCanvasData(z(o,function(t,e){o[e]=t*n})),this.setCropBoxData(z(h,function(t,e){h[e]=t*n}))))},dblclick:function(){var t,e;this.disabled||this.options.dragMode===_||this.setDragMode((t=this.dragBox,e=Q,(t.classList?t.classList.contains(e):-1y&&(D.x=y-f);break;case k:p+D.xx&&(D.y=x-v)}}var i,a,o,n=this.options,h=this.canvasData,r=this.containerData,s=this.cropBoxData,c=this.pointers,d=this.action,l=n.aspectRatio,p=s.left,m=s.top,u=s.width,g=s.height,f=p+u,v=m+g,w=0,b=0,y=r.width,x=r.height,M=!0,C=(!l&&t.shiftKey&&(l=u&&g?u/g:1),this.limited&&(w=s.minLeft,b=s.minTop,y=w+Math.min(r.width,h.width,h.left+h.width),x=b+Math.min(r.height,h.height,h.top+h.height)),c[Object.keys(c)[0]]),D={x:C.endX-C.startX,y:C.endY-C.startY};switch(d){case I:p+=D.x,m+=D.y;break;case B:0<=D.x&&(y<=f||l&&(m<=b||x<=v))?M=!1:(e(B),(u+=D.x)<0&&(d=k,p-=u=-u),l&&(m+=(s.height-(g=u/l))/2));break;case T:D.y<=0&&(m<=b||l&&(p<=w||y<=f))?M=!1:(e(T),g-=D.y,m+=D.y,g<0&&(d=O,m-=g=-g),l&&(p+=(s.width-(u=g*l))/2));break;case k:D.x<=0&&(p<=w||l&&(m<=b||x<=v))?M=!1:(e(k),u-=D.x,p+=D.x,u<0&&(d=B,p-=u=-u),l&&(m+=(s.height-(g=u/l))/2));break;case O:0<=D.y&&(x<=v||l&&(p<=w||y<=f))?M=!1:(e(O),(g+=D.y)<0&&(d=T,m-=g=-g),l&&(p+=(s.width-(u=g*l))/2));break;case E:if(l){if(D.y<=0&&(m<=b||y<=f)){M=!1;break}e(T),g-=D.y,m+=D.y,u=g*l}else e(T),e(B),!(0<=D.x)||fMath.abs(o)&&(o=i)})}),o),t),M=!1;break;case U:D.x&&D.y?(i=Wt(this.cropper),p=C.startX-i.left,m=C.startY-i.top,u=s.minWidth,g=s.minHeight,0 or