├── src ├── SvgBlazor │ ├── _Imports.razor │ ├── wwwroot │ │ └── SvgBlazor.js │ ├── Interfaces │ │ ├── ISvgAttribute.cs │ │ ├── ISvgContainer.cs │ │ ├── ISvgElement.cs │ │ └── ISvgEventHandler.cs │ ├── Enums │ │ ├── FillRule.cs │ │ ├── TextLengthAdjust.cs │ │ ├── TextAnchor.cs │ │ ├── StrokeLineCapStyle.cs │ │ ├── StrokeLineJoinStyle.cs │ │ ├── ValueUnit.cs │ │ └── TextDominantBaseline.cs │ ├── Elements │ │ ├── SvgG.cs │ │ ├── SvgPath.cs │ │ ├── SvgUse.cs │ │ ├── SvgCircle.cs │ │ ├── SvgLine.cs │ │ ├── SvgRect.cs │ │ ├── SvgEllipse.cs │ │ ├── SvgPolygon.cs │ │ ├── Svg.cs │ │ └── SvgText.cs │ ├── Extensions │ │ └── EnumExtension.cs │ ├── SvgBlazor.csproj │ ├── Interop │ │ └── SvgElementConnector.cs │ ├── Attributes │ │ ├── SvgFill.cs │ │ └── SvgStroke.cs │ └── Base │ │ └── SvgEventHandler.cs ├── SvgBlazor.Docs │ ├── .gitignore │ ├── wwwroot │ │ ├── favicon.ico │ │ ├── css │ │ │ ├── open-iconic │ │ │ │ ├── font │ │ │ │ │ └── fonts │ │ │ │ │ │ ├── open-iconic.eot │ │ │ │ │ │ ├── open-iconic.otf │ │ │ │ │ │ ├── open-iconic.ttf │ │ │ │ │ │ └── open-iconic.woff │ │ │ │ ├── ICON-LICENSE │ │ │ │ ├── README.md │ │ │ │ └── FONT-LICENSE │ │ │ ├── atom-one-dark.min.css │ │ │ ├── github.min.css │ │ │ └── app.css │ │ ├── js │ │ │ ├── SvgBlazor.Docs.js │ │ │ └── csharp.min.js │ │ ├── index.html │ │ └── img │ │ │ └── svgblazor_logo.svg │ ├── Components │ │ ├── ExampleTitle.razor │ │ ├── ElementDescription.razor │ │ ├── ExampleComponent.razor │ │ ├── ExampleCode.razor │ │ └── ElementApiDocs.razor │ ├── Pages │ │ ├── Elements │ │ │ ├── SvgComponent │ │ │ │ ├── Examples │ │ │ │ │ ├── SvgComponentBasicInit.razor │ │ │ │ │ ├── SvgComponentSimpleAddExample.cs │ │ │ │ │ ├── SvgComponentRemoveExample.cs │ │ │ │ │ └── SvgComponentGetBoundingBoxExample.razor │ │ │ │ └── SvgComponentPage.razor │ │ │ ├── Use │ │ │ │ ├── SvgUsePage.razor │ │ │ │ └── Examples │ │ │ │ │ └── SvgUseExample.cs │ │ │ ├── G │ │ │ │ ├── GPage.razor │ │ │ │ └── Examples │ │ │ │ │ └── GExample.cs │ │ │ ├── Line │ │ │ │ ├── LinePage.razor │ │ │ │ └── Examples │ │ │ │ │ └── LineExample.cs │ │ │ ├── Path │ │ │ │ ├── PathPage.razor │ │ │ │ └── Examples │ │ │ │ │ └── PathExample.cs │ │ │ ├── Rect │ │ │ │ ├── RectPage.razor │ │ │ │ └── Examples │ │ │ │ │ └── RectExample.cs │ │ │ ├── Ellipse │ │ │ │ ├── EllipsePage.razor │ │ │ │ └── Examples │ │ │ │ │ └── EllipseExample.cs │ │ │ ├── Polygon │ │ │ │ ├── PolygonPage.razor │ │ │ │ └── Examples │ │ │ │ │ └── PolygonExample.cs │ │ │ ├── Circle │ │ │ │ ├── CirclePage.razor │ │ │ │ └── Examples │ │ │ │ │ └── CircleExample.cs │ │ │ ├── Svg │ │ │ │ ├── SvgPage.razor │ │ │ │ └── Examples │ │ │ │ │ └── SvgExample.razor │ │ │ └── Text │ │ │ │ ├── Examples │ │ │ │ ├── TextBasicExample.cs │ │ │ │ ├── TextRotateExample.cs │ │ │ │ ├── TextShiftXYExample.cs │ │ │ │ ├── TextLengthAdjustSpacingExample.cs │ │ │ │ ├── TextLengthAdjustSpacingAndGlyphsExample.cs │ │ │ │ ├── TexDominantBaselineExample.cs │ │ │ │ └── TextTextAnchorExample.cs │ │ │ │ └── TextPage.razor │ │ ├── SvgValue │ │ │ ├── Examples │ │ │ │ ├── SvgValueImplicitOperatorsExample.cs │ │ │ │ └── SvgValueUnitTypeExample.cs │ │ │ └── SvgValuePage.razor │ │ ├── Attributes │ │ │ ├── Stroke │ │ │ │ ├── Examples │ │ │ │ │ ├── StrokeBasicExample.cs │ │ │ │ │ ├── StrokeOpacityExample.cs │ │ │ │ │ ├── Dash │ │ │ │ │ │ ├── StrokeDashArrayExample.cs │ │ │ │ │ │ └── StrokeDashOffsetExample.cs │ │ │ │ │ ├── StrokeLineCapExamples.cs │ │ │ │ │ ├── StrokeMiterLimitExamples.cs │ │ │ │ │ └── StrokeLineJoinExamples.cs │ │ │ │ └── StrokePage.razor │ │ │ └── Fill │ │ │ │ ├── FillPage.razor │ │ │ │ └── Examples │ │ │ │ ├── FillRuleEvenOddExample.cs │ │ │ │ ├── FillRuleNonZeroExample.cs │ │ │ │ ├── FillColorExample.cs │ │ │ │ └── FillOpacityExample.cs │ │ └── Index.razor │ ├── Interfaces │ │ └── IExampleCode.cs │ ├── Models │ │ ├── IElementApiElement.cs │ │ ├── ElementApiProperty.cs │ │ └── ElementApiMethod.cs │ ├── App.razor │ ├── Shared │ │ ├── MainLayout.razor │ │ ├── SurveyPrompt.razor │ │ ├── NavMenu.razor.css │ │ ├── MainLayout.razor.css │ │ └── NavMenu.razor │ ├── _Imports.razor │ ├── Properties │ │ └── launchSettings.json │ ├── Program.cs │ ├── Extensions │ │ └── ReflectionTypesExtensions.cs │ ├── SvgBlazor.Docs.csproj │ └── Extractors │ │ └── ElementApiExtractor.cs └── SvgBlazor.Docs.Generator │ ├── SvgBlazor.Docs.Generator.csproj │ ├── ProjectPaths.cs │ ├── Program.cs │ └── ExamplesCode.cs ├── .github └── workflows │ ├── push-ci.yml │ ├── push-docs-deploy.yml │ ├── manual-deploy.yml │ ├── push-tag-release.yml │ └── base-workflow.yml ├── .stylecop.json ├── tests ├── SvgBlazor.Tests │ ├── Elements │ │ ├── SvgUseTest.cs │ │ ├── SvgGTest.cs │ │ ├── SvgPathTest.cs │ │ ├── CircleTest.cs │ │ ├── LineTest.cs │ │ ├── EllipseTest.cs │ │ ├── RectTests.cs │ │ ├── SvgPolygonTest.cs │ │ └── SvgComponent.cs │ ├── Base │ │ └── TestContextWithSvgBlazorJsModule.cs │ ├── Extensions │ │ └── EnumExtensionTests.cs │ ├── Components │ │ └── SvgComponentTests.cs │ ├── SvgBlazor.Tests.csproj │ ├── Attributes │ │ ├── FillAttributeTest.cs │ │ └── StrokeAttributeTest.cs │ └── ValueUnitTest.cs ├── SvgBlazor.Docs.Tests │ ├── SvgBlazor.Docs.Tests.csproj │ └── ReflectionTypesExtensionsTest.cs └── SvgBlazor.Docs.Generator.Tests │ ├── SvgBlazor.Docs.Generator.Tests.csproj │ └── CodeFromExampleTest.cs ├── .editorconfig ├── LICENSE ├── .gitignore ├── README.md └── SvgBlazor.sln /src/SvgBlazor/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Web 2 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Autogenerated example HTML files 2 | Pages/**/Examples/**/*.html 3 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Approxoft/SvgBlazor/HEAD/src/SvgBlazor.Docs/wwwroot/favicon.ico -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Components/ExampleTitle.razor: -------------------------------------------------------------------------------- 1 |

@ChildContent

2 | @code { 3 | [Parameter] 4 | public RenderFragment ChildContent { get; set; } 5 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Approxoft/SvgBlazor/HEAD/src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.eot -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Approxoft/SvgBlazor/HEAD/src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.otf -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Approxoft/SvgBlazor/HEAD/src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/SvgComponent/Examples/SvgComponentBasicInit.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | @code 4 | { 5 | private SvgComponent svg; 6 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Approxoft/SvgBlazor/HEAD/src/SvgBlazor.Docs/wwwroot/css/open-iconic/font/fonts/open-iconic.woff -------------------------------------------------------------------------------- /src/SvgBlazor/wwwroot/SvgBlazor.js: -------------------------------------------------------------------------------- 1 | export function BBox(element) { 2 | const bbox = element.getBBox(); 3 | 4 | return { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height } 5 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Components/ElementDescription.razor: -------------------------------------------------------------------------------- 1 | @using SvgBlazor.Docs.Extensions 2 | 3 |

@(ElementType.GetDocumentation())

4 | 5 | @code { 6 | [Parameter] 7 | public Type ElementType { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Use/SvgUsePage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/svguse" 2 | 3 | Use 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/push-ci.yml: -------------------------------------------------------------------------------- 1 | name: Push CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | uses: Approxoft/SvgBlazor/.github/workflows/base-workflow.yml@main 12 | -------------------------------------------------------------------------------- /.github/workflows/push-docs-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Push Docs CI/CD 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | jobs: 8 | main: 9 | uses: Approxoft/SvgBlazor/.github/workflows/base-workflow.yml@main 10 | with: 11 | publish-docs: true 12 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/G/GPage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/g" 2 | 3 | G 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Line/LinePage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/line" 2 | 3 | Line 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Path/PathPage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/path" 2 | 3 | Path 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Rect/RectPage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/rect" 2 | 3 | Rect 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Ellipse/EllipsePage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/ellipse" 2 | 3 | Ellipse 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Polygon/PolygonPage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/polygon" 2 | 3 | Polygon 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Circle/CirclePage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/circle" 2 | 3 | Circle 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Svg/SvgPage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/svg" 2 | @using SvgBlazor.Docs.Pages.Elements.Svg.Examples 3 | 4 | Svg 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Interfaces/IExampleCode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace SvgBlazor.Docs.Interfaces 7 | { 8 | public interface IExampleCode 9 | { 10 | void Example(SvgComponent svg); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Models/IElementApiElement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | namespace SvgBlazor.Docs.Models 5 | { 6 | public interface IElementApiElement 7 | { 8 | public string Name { get; set; } 9 | 10 | public string Description { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |

Sorry, there's nothing at this address.

8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs.Generator/SvgBlazor.Docs.Generator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 |
9 |
10 | About 11 |
12 | 13 |
14 | @Body 15 |
16 |
17 |
18 | -------------------------------------------------------------------------------- /.github/workflows/manual-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Manual deploy 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: 'Provide version number (e.g.: 1.0.0)' 8 | required: true 9 | jobs: 10 | main: 11 | uses: Approxoft/SvgBlazor/.github/workflows/base-workflow.yml@main 12 | with: 13 | publish-nuget: true 14 | version: ${{ github.event.inputs.version }} 15 | secrets: 16 | nuget-api-key: ${{ secrets.NUGET_API_KEY }} 17 | -------------------------------------------------------------------------------- /.stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 3 | "settings": { 4 | "documentationRules": { 5 | "companyName": "Approxoft", 6 | "copyrightText": "Copyright (c) {companyName}. All rights reserved.\nLicensed under the MIT License. See LICENSE in the project root for license information.", 7 | "xmlHeader": false, 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Models/ElementApiProperty.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | namespace SvgBlazor.Docs.Models 5 | { 6 | public class ElementApiProperty : IElementApiElement 7 | { 8 | public string Name { get; set; } 9 | 10 | public string Type { get; set; } 11 | 12 | public string DeclaringType { get; set; } 13 | 14 | public string Description { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.Web.Virtualization 7 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 8 | @using Microsoft.JSInterop 9 | @using SvgBlazor 10 | @using SvgBlazor.Docs 11 | @using SvgBlazor.Docs.Examples 12 | @using SvgBlazor.Docs.Shared 13 | @using SvgBlazor.Docs.Components 14 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/js/SvgBlazor.Docs.js: -------------------------------------------------------------------------------- 1 | window.highlightCodeElement = (element) => { 2 | if (element && element.children.length > 0) { 3 | var firstChild = element.firstElementChild; 4 | 5 | if (firstChild.children.length > 0) { 6 | var firstGrandchild = firstChild.firstElementChild; 7 | hljs.highlightElement(firstGrandchild); 8 | } else { 9 | hljs.highlightElement(firstChild); 10 | } 11 | } 12 | }; 13 | 14 | window.highlightAllCode = () => { 15 | hljs.highlightAll(); 16 | }; -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Shared/SurveyPrompt.razor: -------------------------------------------------------------------------------- 1 | 11 | 12 | @code { 13 | // Demonstrates how a parent component can supply parameters 14 | [Parameter] 15 | public string Title { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Models/ElementApiMethod.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | 9 | namespace SvgBlazor.Docs.Models 10 | { 11 | public class ElementApiMethod : IElementApiElement 12 | { 13 | public string Name { get; set; } 14 | 15 | public string ReturnValue { get; set; } 16 | 17 | public IEnumerable Parameters { get; set; } 18 | 19 | public string Description { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/SvgValue/Examples/SvgValueImplicitOperatorsExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class SvgValueImplicitOperatorsExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | SvgValue svgValueInt = 10; 15 | SvgValue svgValueFloat = 10F; 16 | SvgValue svgValueString = "10"; 17 | /* #example-code-end */ 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/SvgBlazor/Interfaces/ISvgAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Components.Rendering; 5 | 6 | namespace SvgBlazor.Interfaces 7 | { 8 | /// 9 | /// The interface that represents the SvgAttribute. 10 | /// 11 | public interface ISvgAttribute 12 | { 13 | /// 14 | /// Adds attributes to the RenderTreeBuilder. 15 | /// 16 | /// The RenderTreeBuilder used to build this attibute. 17 | public void RenderAttributes(RenderTreeBuilder builder); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/SvgBlazor/Enums/FillRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.ComponentModel; 5 | 6 | namespace SvgBlazor 7 | { 8 | /// 9 | /// The rule that determines which parts of the canvas are contained within the shape. 10 | /// 11 | public enum FillRule 12 | { 13 | /// 14 | /// Non zero fill rule. 15 | /// 16 | [Description("nonzero")] 17 | NonZero, 18 | 19 | /// 20 | /// Even odd fill rule. 21 | /// 22 | [Description("evenodd")] 23 | EvenOdd, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Components/ExampleComponent.razor: -------------------------------------------------------------------------------- 1 | @using SvgBlazor.Docs.Interfaces 2 | 3 | 4 | 5 | 6 | 7 | @code { 8 | [Parameter] 9 | public IExampleCode ExampleCode { get; set; } 10 | 11 | [Parameter] 12 | public int Width { get; set; } = 200; 13 | 14 | [Parameter] 15 | public int Height { get; set; } = 200; 16 | 17 | private SvgComponent svg; 18 | 19 | protected override void OnAfterRender(bool firstRender) 20 | { 21 | if (firstRender) 22 | { 23 | ExampleCode?.Example(svg); 24 | } 25 | } 26 | 27 | private string GetItemName() => ExampleCode?.GetType().Name; 28 | } 29 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/Examples/TextBasicExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class TextBasicExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var text = new SvgText 15 | { 16 | X = 10, 17 | Y = 20, 18 | Text = "This is just awesome!", 19 | }; 20 | /* #example-code-end */ 21 | svg.Add(text); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/SvgValue/SvgValuePage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/svgvalue" 2 | @using SvgBlazor.Docs.Components 3 | @using SvgBlazor.Docs.Extensions 4 | 5 | SvgValue 6 |

@( typeof(SvgValue).GetDocumentation() )

7 |

The simplest way to create a SvgValue is to use the provided implicit operators:

8 | 9 |

In the above example a SvgValue from int, float and string will be created respectively.

10 |

Please note that when using implicit operator initialization, no unit type will be added. If you wish to provide a unit type, use one of the dedicated constructors:

11 | 12 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/SvgComponent/Examples/SvgComponentSimpleAddExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class SvgComponentSimpleAddExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var circle = new SvgCircle 15 | { 16 | CenterX = 50, 17 | CenterY = 50, 18 | Radius = 25, 19 | }; 20 | 21 | svg.Add(circle); 22 | /* #example-code-end */ 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/Examples/TextRotateExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class TextRotateExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var text = new SvgText 15 | { 16 | X = 10, 17 | Y = 20, 18 | Text = "Whoa! Nice rotation!", 19 | Rotate = "20 0 20", 20 | }; 21 | /* #example-code-end */ 22 | svg.Add(text); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Circle/Examples/CircleExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class CircleExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var circle = new SvgCircle 14 | { 15 | CenterX = 50, 16 | CenterY = 50, 17 | Radius = 50, 18 | Fill = new SvgFill { Color = "#27ba0d" }, 19 | }; 20 | /* #example-code-end */ 21 | 22 | svg.Add(circle); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Line/Examples/LineExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class LineExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var line = new SvgLine 15 | { 16 | X1 = 0, 17 | Y1 = 0, 18 | X2 = 200, 19 | Y2 = 200, 20 | Stroke = new SvgStroke { Color = "red" }, 21 | }; 22 | /* #example-code-end */ 23 | 24 | svg.Add(line); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/Examples/TextShiftXYExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class TextShiftXYExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var text = new SvgText 15 | { 16 | X = 10, 17 | Y = 20, 18 | Text = "That's a nice shift!", 19 | ShiftX = 20, 20 | ShiftY = 10, 21 | }; 22 | /* #example-code-end */ 23 | svg.Add(text); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/SvgBlazor/Enums/TextLengthAdjust.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.ComponentModel; 5 | 6 | namespace SvgBlazor 7 | { 8 | /// 9 | /// The lengthAdjust attribute sets how the text is stretched to the length specified by the textLength attribute. 10 | /// 11 | public enum TextLengthAdjust 12 | { 13 | /// 14 | /// Adjusts only the spacing between the glyphs. 15 | /// 16 | [Description("spacing")] 17 | Spacing, 18 | 19 | /// 20 | /// Adjust spacing and glyph size. 21 | /// 22 | [Description("spacingAndGlyphs")] 23 | SpacingAndGlyphs, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Rect/Examples/RectExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class RectExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var rect = new SvgRect 15 | { 16 | X = 10, 17 | Y = 20, 18 | Width = 180, 19 | Height = 180, 20 | Fill = new SvgFill { Color = "purple" }, 21 | }; 22 | /* #example-code-end */ 23 | 24 | svg.Add(rect); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/atom-one-dark.min.css: -------------------------------------------------------------------------------- 1 | pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline} -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Ellipse/Examples/EllipseExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class EllipseExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var ellipse = new SvgEllipse 15 | { 16 | CenterX = 100, 17 | CenterY = 100, 18 | RadiusX = 40, 19 | RadiusY = 20, 20 | Fill = new SvgFill { Color = "orange" }, 21 | }; 22 | /* #example-code-end */ 23 | 24 | svg.Add(ellipse); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/push-tag-release.yml: -------------------------------------------------------------------------------- 1 | name: Push tag release 2 | 3 | on: 4 | push: 5 | tags: 6 | - v[0-9].[0-9]+.[0-9]+ 7 | 8 | jobs: 9 | get-version-from-tag: 10 | runs-on: ubuntu-latest 11 | outputs: 12 | version: ${{ steps.get_version.outputs.VERSION }} 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Get the version 16 | id: get_version 17 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\/v/} 18 | - name: Print info about the version 19 | run: echo Version ${{ steps.get_version.outputs.VERSION }} 20 | 21 | cd: 22 | needs: get-version-from-tag 23 | uses: Approxoft/SvgBlazor/.github/workflows/base-workflow.yml@main 24 | with: 25 | publish-nuget: true 26 | version: ${{ needs.get-version-from-tag.outputs.version }} 27 | secrets: 28 | nuget-api-key: ${{ secrets.NUGET_API_KEY }} 29 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/Examples/TextLengthAdjustSpacingExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class TextLengthAdjustSpacingExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var text = new SvgText 15 | { 16 | X = 10, 17 | Y = 20, 18 | Text = "I wish there was more space here...", 19 | LengthAdjust = TextLengthAdjust.Spacing, 20 | TextLength = 200, 21 | }; 22 | /* #example-code-end */ 23 | svg.Add(text); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs.Generator/ProjectPaths.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace SvgBlazor.Docs.Generator 12 | { 13 | public class ProjectPaths 14 | { 15 | public const string ExampleIdentifier = "Example"; 16 | 17 | private const string DocsDirectory = "SvgBlazor.Docs"; 18 | 19 | private const string DocsPagesDirectory = "Pages"; 20 | 21 | public static string SourcePath { get; set; } 22 | 23 | public static string DocsDirectoryPath => Path.Combine(SourcePath, DocsDirectory); 24 | 25 | public static string PagesDirectoryPath => Path.Combine(DocsDirectoryPath, DocsPagesDirectory); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/Examples/TextLengthAdjustSpacingAndGlyphsExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class TextLengthAdjustSpacingAndGlyphsExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var text = new SvgText 15 | { 16 | X = 10, 17 | Y = 20, 18 | Text = "I wish there was more space here...", 19 | LengthAdjust = TextLengthAdjust.SpacingAndGlyphs, 20 | TextLength = 200, 21 | }; 22 | /* #example-code-end */ 23 | svg.Add(text); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/Examples/StrokeBasicExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class StrokeBasicExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var stroke = new SvgStroke 14 | { 15 | Color = "pink", 16 | Width = 15, 17 | }; 18 | /* #example-code-end */ 19 | 20 | var circle = new SvgCircle 21 | { 22 | CenterX = 100, 23 | CenterY = 100, 24 | Radius = 75, 25 | Stroke = stroke, 26 | }; 27 | 28 | svg.Add(circle); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/SvgUseTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Bunit; 3 | using Xunit; 4 | 5 | namespace SvgBlazor.Tests.Elements 6 | { 7 | public class SvgUseTest : TestContextWithSvgBlazorJsModule 8 | { 9 | [Fact] 10 | public void RendersSvgWithDuplicatedElement() 11 | { 12 | var comp = RenderComponent(); 13 | 14 | comp.InvokeAsync(() => comp.Instance.Add(new SvgUse 15 | { 16 | X = 20, 17 | Y = 30, 18 | Element = new SvgCircle { Id = "circleId", CenterX = 10, CenterY = 10 }, 19 | Fill = new SvgFill { Color = "blue" }, 20 | })); 21 | 22 | var element = comp.Find("use"); 23 | Assert.Contains("#circleId", element.GetAttribute("href")); 24 | Assert.Contains("20", element.GetAttribute("x")); 25 | Assert.Contains("30", element.GetAttribute("y")); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/SvgBlazor/Enums/TextAnchor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.ComponentModel; 5 | 6 | namespace SvgBlazor 7 | { 8 | /// 9 | /// The anchor of the text. 10 | /// 11 | public enum TextAnchor 12 | { 13 | /// 14 | /// The given x and y coordinates will become the start location of the text. 15 | /// 16 | [Description("start")] 17 | Start, 18 | 19 | /// 20 | /// The given x and y coordinates will become the middle location of the text. 21 | /// 22 | [Description("middle")] 23 | Middle, 24 | 25 | /// 26 | /// The given x and y coordinates will become the end location of the text. 27 | /// 28 | [Description("end")] 29 | End, 30 | } 31 | } -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Base/TestContextWithSvgBlazorJsModule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Bunit; 7 | 8 | namespace SvgBlazor.Tests 9 | { 10 | public class TestContextWithSvgBlazorJsModule : TestContext 11 | { 12 | public TestContextWithSvgBlazorJsModule() 13 | { 14 | SetupJSInterop(); 15 | } 16 | 17 | private void SetupJSInterop() 18 | { 19 | JSInterop 20 | .SetupModule("./_content/SvgBlazor/SvgBlazor.js") 21 | .Setup("BBox", _ => true) 22 | .SetResult(new RectangleF 23 | { 24 | X = 0, 25 | Y = 0, 26 | Width = 10, 27 | Height = 10, 28 | }); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Extensions/EnumExtensionTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.ComponentModel; 6 | using Bunit; 7 | using SvgBlazor.Extensions; 8 | using Xunit; 9 | 10 | namespace SvgBlazor.Tests.Extensions 11 | { 12 | public class EnumExtensionTests 13 | { 14 | [Fact] 15 | public void ReturnsString() 16 | { 17 | Assert.Equal("dumb", Dummy.Dumb.ToDescriptionString()); 18 | Assert.Equal("dumber", Dummy.Dumber.ToDescriptionString()); 19 | Assert.Equal("EvenMoreDumber", Dummy.EvenMoreDumber.ToDescriptionString()); 20 | } 21 | 22 | private enum Dummy 23 | { 24 | [Description("dumb")] 25 | Dumb, 26 | 27 | [Description("dumber")] 28 | Dumber, 29 | EvenMoreDumber, 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # SA1600: Elements should be documented 4 | dotnet_diagnostic.SA1600.severity = silent 5 | 6 | # SA1200: Using directives should be placed correctly 7 | dotnet_diagnostic.SA1200.severity = silent 8 | 9 | # SA1101: Prefix local calls with this 10 | dotnet_diagnostic.SA1101.severity = silent 11 | 12 | # SA1309: Field names should not begin with underscore 13 | dotnet_diagnostic.SA1309.severity = silent 14 | 15 | [*.cshtml.cs] 16 | 17 | # SA1649: File name should match first type name 18 | dotnet_diagnostic.SA1649.severity = silent 19 | 20 | [**/Migrations/**.cs] 21 | 22 | # Default severity for analyzer diagnostics with category 'StyleCop.CSharp.ReadabilityRules' 23 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.ReadabilityRules.severity = silent 24 | 25 | # Default severity for analyzer diagnostics with category 'StyleCop.CSharp.DocumentationRules' 26 | dotnet_analyzer_diagnostic.category-StyleCop.CSharp.DocumentationRules.severity = silent -------------------------------------------------------------------------------- /src/SvgBlazor/Enums/StrokeLineCapStyle.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.ComponentModel; 6 | 7 | namespace SvgBlazor 8 | { 9 | /// 10 | /// The stroke's line cap styles. 11 | /// 12 | public enum StrokeLineCapStyle 13 | { 14 | /// 15 | /// The end of each subpath will not be extended beyond its two endpoints. 16 | /// 17 | [Description("butt")] 18 | Butt, 19 | 20 | /// 21 | /// The end of each subpath will be extended by a rectangle. 22 | /// 23 | [Description("square")] 24 | Square, 25 | 26 | /// 27 | /// The end of each subpath will be extended by a half circle. 28 | /// 29 | [Description("round")] 30 | Round, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/SvgGTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Drawing; 5 | using Xunit; 6 | using Bunit; 7 | 8 | namespace SvgBlazor.Tests 9 | { 10 | public class SvgGTest : TestContextWithSvgBlazorJsModule 11 | { 12 | [Fact] 13 | public void RendersSvgGWithChildContent() 14 | { 15 | var comp = RenderComponent(); 16 | 17 | var group = new SvgG(); 18 | group.Add(new ChildElement()); 19 | comp.InvokeAsync(() => comp.Instance.Add(group)); 20 | 21 | comp.Render(); 22 | 23 | var element = comp.Find("g"); 24 | Assert.Equal("tester", element.Children[0].TagName); 25 | } 26 | 27 | private class ChildElement : SvgElement 28 | { 29 | public override string Tag() => "tester"; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Fill/FillPage.razor: -------------------------------------------------------------------------------- 1 | @page "/attributes/fill" 2 | @using SvgBlazor.Docs.Extensions 3 | 4 | Fill 5 | 6 | 7 |

Color property

8 |

@( typeof(SvgFill).GetProperty("Color").GetDocumentation() )

9 |
10 | 11 |

Opacity property

12 |

@( typeof(SvgFill).GetProperty("Opacity").GetDocumentation() )

13 |
14 | 15 |

Fill rule property

16 |

@( typeof(SvgFill).GetProperty("Rule").GetDocumentation() )

17 |

NonZero

18 |
19 |

EvenOdd

20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/Examples/StrokeOpacityExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class StrokeOpacityExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var stroke = new SvgStroke 14 | { 15 | Color = "yellow", 16 | Width = 15, 17 | Opacity = 0.5f, 18 | }; 19 | /* #example-code-end */ 20 | 21 | var circle = new SvgCircle 22 | { 23 | CenterX = 100, 24 | CenterY = 100, 25 | Radius = 75, 26 | Stroke = stroke, 27 | }; 28 | 29 | svg.Add(circle); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Path/Examples/PathExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class PathExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var line = new SvgPath() 15 | { 16 | Path = "M 10, 30 " + 17 | "A 20, 20 0, 0, 1 50, 30 " + 18 | "A 20, 20 0, 0, 1 90, 30 " + 19 | "Q 90, 60 50, 90 " + 20 | "Q 10, 60 10, 30 z", 21 | Fill = new SvgFill { Color = "pink" }, 22 | Stroke = new SvgStroke { Color = "red" }, 23 | }; 24 | /* #example-code-end */ 25 | 26 | svg.Add(line); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:36489", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "SvgBlazor.Docs": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 23 | "applicationUrl": "http://localhost:51383", 24 | "environmentVariables": { 25 | "ASPNETCORE_ENVIRONMENT": "Development" 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/Examples/Dash/StrokeDashArrayExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class StrokeDashArrayExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var dashArrayStroke = new SvgStroke 14 | { 15 | Color = "green", 16 | Width = 15, 17 | DashArray = "1 2", 18 | }; 19 | /* #example-code-end */ 20 | 21 | var circle = new SvgCircle 22 | { 23 | CenterX = 100, 24 | CenterY = 100, 25 | Radius = 75, 26 | Stroke = dashArrayStroke, 27 | }; 28 | 29 | svg.Add(circle); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Components/SvgComponentTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Bunit; 7 | using Xunit; 8 | 9 | namespace SvgBlazor.Tests.Components 10 | { 11 | public class SvgComponentTests : TestContextWithSvgBlazorJsModule 12 | { 13 | [Fact] 14 | public async void CalculatesBoudingBox() 15 | { 16 | var comp = RenderComponent(); 17 | var circle = new SvgCircle 18 | { 19 | CenterX = 1, 20 | CenterY = 2, 21 | Radius = 3, 22 | }; 23 | 24 | await comp.InvokeAsync(() => comp.Instance.Add(circle)); 25 | 26 | comp.Render(); 27 | 28 | var bbox = await comp.Instance.GetBoundingBox(circle); 29 | Assert.Equal(new RectangleF(0, 0, 10, 10), bbox); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/Examples/Dash/StrokeDashOffsetExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class StrokeDashOffsetExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var dashOffsetStroke = new SvgStroke 14 | { 15 | Color = "blue", 16 | Width = 10, 17 | DashArray = "50", 18 | DashOffset = 50, 19 | }; 20 | /* #example-code-end */ 21 | var line = new SvgLine 22 | { 23 | X1 = 20, 24 | Y1 = 20, 25 | X2 = 175, 26 | Y2 = 20, 27 | Stroke = dashOffsetStroke, 28 | }; 29 | 30 | svg.Add(line); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/G/Examples/GExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class GExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var group = new SvgG 15 | { 16 | Fill = new SvgFill { Color = "red" }, 17 | }; 18 | 19 | group.Add(new SvgCircle 20 | { 21 | CenterX = 50, 22 | CenterY = 50, 23 | Radius = 50, 24 | }); 25 | 26 | group.Add(new SvgCircle 27 | { 28 | CenterX = 150, 29 | CenterY = 150, 30 | Radius = 50, 31 | }); 32 | /* #example-code-end */ 33 | 34 | svg.Add(group); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Net.Http; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 11 | using Microsoft.Extensions.Configuration; 12 | using Microsoft.Extensions.DependencyInjection; 13 | using Microsoft.Extensions.Logging; 14 | using SvgBlazor.Docs.Extensions; 15 | 16 | namespace SvgBlazor.Docs 17 | { 18 | public class Program 19 | { 20 | public static async Task Main(string[] args) 21 | { 22 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 23 | builder.RootComponents.Add("#app"); 24 | 25 | builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); 26 | 27 | await builder.Build().RunAsync(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Svg/Examples/SvgExample.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | @code { 4 | SvgComponent svgref; 5 | 6 | protected override void OnAfterRender(bool firstRender) 7 | { 8 | if (firstRender) 9 | { 10 | var svg1 = new Svg 11 | { 12 | X = 0, 13 | Y = 0, 14 | Width = 400, 15 | Height = 400, 16 | Fill = new SvgFill { Color = "red" }, 17 | }; 18 | 19 | svg1.Add(new SvgCircle { CenterX = 200, CenterY = 200, Radius = 100, }); 20 | 21 | svgref.Add(svg1); 22 | 23 | var svg2 = new Svg 24 | { 25 | X = 0, 26 | Y = 0, 27 | Width = 400, 28 | Height = 400, 29 | Fill = new SvgFill { Color = "blue" }, 30 | }; 31 | 32 | svg2.Add(new SvgRect { X = 50, Y = 50, Width = 100, Height = 100, }); 33 | 34 | svgref.Add(svg2); 35 | } 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/SvgComponent/SvgComponentPage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/svgcomponent" 2 | @using SvgBlazor.Docs.Pages.Elements.SvgComponent.Examples 3 | 4 | SvgComponent 5 | 6 |

SvgComponent can be created as follows:

7 | 8 | 9 |

Adding elements

10 |

Adding an element is done by creating one of the available elements and then passing it to the Add method on an existing SvgComponent reference:

11 | 12 | 13 |

Removing elements

14 |

Removing an element is done by passing its reference to the Remove method on an existing SvgComponent reference:

15 | 16 | 17 |

BoudingBox calculation

18 | 19 | 20 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Polygon/Examples/PolygonExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Drawing; 7 | using SvgBlazor.Docs.Interfaces; 8 | 9 | namespace SvgBlazor.Docs.Examples 10 | { 11 | public class PolygonExample : IExampleCode 12 | { 13 | public void Example(SvgComponent svg) 14 | { 15 | /* #example-code-start */ 16 | var polygon = new SvgPolygon 17 | { 18 | Points = new List 19 | { 20 | new PointF(160, 200), 21 | new PointF(40, 200), 22 | new PointF(0, 80), 23 | new PointF(100, 0), 24 | new PointF(200, 80), 25 | }, 26 | Fill = new SvgFill { Color = "#aabbcc" }, 27 | }; 28 | /* #example-code-end */ 29 | 30 | svg.Add(polygon); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/SvgComponent/Examples/SvgComponentRemoveExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Components; 6 | using Microsoft.AspNetCore.Components.Web; 7 | using SvgBlazor.Docs.Interfaces; 8 | 9 | namespace SvgBlazor.Docs.Examples 10 | { 11 | public class SvgComponentRemoveExample : IExampleCode 12 | { 13 | public void Example(SvgComponent svg) 14 | { 15 | /* #example-code-start */ 16 | var text = new SvgText 17 | { 18 | X = 35, 19 | Y = 50, 20 | Text = "Click me to remove", 21 | Stroke = new SvgStroke { Color = "red", }, 22 | }; 23 | 24 | text.OnClick = EventCallback.Factory.Create(text, (args) => 25 | { 26 | svg.Remove(text); 27 | }); 28 | 29 | svg.Add(text); 30 | /* #example-code-end */ 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgG.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Components.Rendering; 8 | 9 | namespace SvgBlazor 10 | { 11 | /// 12 | /// The SvgG class is responsible for providing the SVG group element. 13 | /// 14 | public partial class SvgG : SvgContainer 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | public SvgG() 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class with provided SvgG. 25 | /// 26 | /// Initial SvgG. 27 | public SvgG(SvgG svgg) 28 | : base(svgg) 29 | { 30 | } 31 | 32 | /// 33 | public override string Tag() => "g"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/SvgBlazor/Extensions/EnumExtension.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.ComponentModel; 6 | 7 | namespace SvgBlazor.Extensions 8 | { 9 | /// 10 | /// Extensions for enum. 11 | /// 12 | public static class EnumExtension 13 | { 14 | /// 15 | /// Gets the DescriptionAttribute of the enum. 16 | /// 17 | /// The enum to get the description. 18 | /// The DescriptionAttribute of the enum. 19 | public static string ToDescriptionString(this Enum en) 20 | { 21 | var attributes = (DescriptionAttribute[])en 22 | .GetType() 23 | .GetField(en.ToString()) 24 | .GetCustomAttributes(typeof(DescriptionAttribute), false); 25 | 26 | return attributes.Length > 0 27 | ? attributes[0].Description 28 | : en.ToString(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Cosmopolex 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Docs.Tests/SvgBlazor.Docs.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/SvgPathTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using Bunit; 6 | using Xunit; 7 | 8 | namespace SvgBlazor.Tests.Elements 9 | { 10 | public class SvgPathTest : TestContextWithSvgBlazorJsModule 11 | { 12 | [Fact] 13 | public void RendersAttributes() 14 | { 15 | var comp = RenderComponent(); 16 | 17 | comp.InvokeAsync(() => comp.Instance.Add(new SvgPath 18 | { 19 | Path = "M10 10", 20 | })); 21 | 22 | comp.Render(); 23 | 24 | var element = comp.Find("path"); 25 | Assert.Contains("M10 10", element.GetAttribute("d")); 26 | } 27 | 28 | [Fact] 29 | public void CopyConstructor() 30 | { 31 | var e1 = new SvgPath() 32 | { 33 | Path = "M10 10", 34 | }; 35 | 36 | var e2 = new SvgPath(e1); 37 | 38 | Assert.Equal("M10 10", e2.Path); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/SvgBlazor/Interfaces/ISvgContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Components.Rendering; 6 | using Microsoft.AspNetCore.Components.Web; 7 | 8 | namespace SvgBlazor.Interfaces 9 | { 10 | /// 11 | /// Provides methods to manage container elements. 12 | /// 13 | public interface ISvgContainer : ISvgElement 14 | { 15 | /// 16 | /// Adds the given element to the container. 17 | /// 18 | /// Element to be added. 19 | /// The container to which the element was added. 20 | ISvgContainer Add(ISvgElement element); 21 | 22 | /// 23 | /// Removes the given element from the container. 24 | /// 25 | /// Element to be removed. 26 | /// The container from which the element was removed. 27 | ISvgContainer Remove(ISvgElement element); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/SvgComponent/Examples/SvgComponentGetBoundingBoxExample.razor: -------------------------------------------------------------------------------- 1 | @using System.Drawing 2 | 3 |
4 | 5 |
6 |
7 | 12 |

Bounding box: @(boundingBox.IsEmpty ? "Click the button to calculate" : boundingBox)

13 |
14 | 15 | @code 16 | { 17 | private RectangleF boundingBox; 18 | 19 | private SvgComponent svg; 20 | private SvgCircle circle; 21 | 22 | protected override void OnAfterRender(bool firstRender) 23 | { 24 | if (firstRender) 25 | { 26 | circle = new SvgCircle 27 | { 28 | CenterX = 50, 29 | CenterY = 50, 30 | Radius = 25, 31 | }; 32 | 33 | svg.Add(circle); 34 | } 35 | } 36 | 37 | private async Task OnButtonClickedCalculateBoundingBox() 38 | { 39 | boundingBox = await svg.GetBoundingBox(circle); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/open-iconic/ICON-LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Docs.Generator.Tests/SvgBlazor.Docs.Generator.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/SvgBlazor.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Fill/Examples/FillRuleEvenOddExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class FillRuleEvenOddExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var shape1 = new SvgPath 14 | { 15 | Path = "M 20 180 H 180 L 100 20 Z M 80 148 H 120 L 100 108 Z", 16 | Fill = new SvgFill { Rule = FillRule.EvenOdd }, 17 | Stroke = new SvgStroke { Color = "grey" }, 18 | }; 19 | 20 | var shape2 = new SvgPath 21 | { 22 | Path = "M 220 180 H 380 L 300 20 z M 320 147 H 280 L 300 108 Z", 23 | Fill = new SvgFill { Rule = FillRule.EvenOdd }, 24 | Stroke = new SvgStroke { Color = "grey" }, 25 | }; 26 | /* #example-code-end */ 27 | 28 | svg.Add(shape1); 29 | svg.Add(shape2); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Fill/Examples/FillRuleNonZeroExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class FillRuleNonZeroExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var shape1 = new SvgPath 14 | { 15 | Path = "M 20 180 H 180 L 100 20 Z M 80 148 H 120 L 100 108 Z", 16 | Fill = new SvgFill { Rule = FillRule.NonZero }, 17 | Stroke = new SvgStroke { Color = "grey" }, 18 | }; 19 | 20 | var shape2 = new SvgPath 21 | { 22 | Path = "M 220 180 H 380 L 300 20 z M 320 147 H 280 L 300 108 Z", 23 | Fill = new SvgFill { Rule = FillRule.NonZero }, 24 | Stroke = new SvgStroke { Color = "grey" }, 25 | }; 26 | /* #example-code-end */ 27 | 28 | svg.Add(shape1); 29 | svg.Add(shape2); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/SvgValue/Examples/SvgValueUnitTypeExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class SvgValueUnitTypeExample : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var rectPercentage = new SvgRect 15 | { 16 | X = 0, 17 | Y = 0, 18 | Height = 50, 19 | Width = new SvgValue(50F, ValueUnit.Percentage), 20 | Fill = new SvgFill { Color = "blue" }, 21 | }; 22 | 23 | var rectPixels = new SvgRect 24 | { 25 | X = 0, 26 | Y = 100, 27 | Height = 50, 28 | Width = new SvgValue(50F, ValueUnit.Px), 29 | Fill = new SvgFill { Color = "red" }, 30 | }; 31 | /* #example-code-end */ 32 | 33 | svg.Add(rectPercentage); 34 | svg.Add(rectPixels); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # These are some examples of commonly ignored file patterns. 2 | # You should customize this list as applicable to your project. 3 | # Learn more about .gitignore: 4 | # https://www.atlassian.com/git/tutorials/saving-changes/gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | *.userprefs 13 | 14 | # Node artifact files 15 | node_modules/ 16 | dist/ 17 | 18 | # Compiled Java class files 19 | *.class 20 | 21 | # Compiled Python bytecode 22 | *.py[cod] 23 | 24 | # Log files 25 | *.log 26 | 27 | # Package files 28 | *.jar 29 | 30 | # Maven 31 | target/ 32 | dist/ 33 | 34 | # JetBrains IDE 35 | .idea/ 36 | 37 | # Unit test reports 38 | TEST*.xml 39 | 40 | # Generated by MacOS 41 | .DS_Store 42 | 43 | # Generated by Windows 44 | Thumbs.db 45 | 46 | # Applications 47 | *.app 48 | *.exe 49 | *.war 50 | 51 | # Large media files 52 | *.mp4 53 | *.tiff 54 | *.avi 55 | *.flv 56 | *.mov 57 | *.wmv 58 | 59 | # Visual Studio files and outputs 60 | .vs/ 61 | bin/ 62 | obj/ 63 | 64 | # Visual Studio Code 65 | .vscode/* 66 | !.vscode/settings.json 67 | !.vscode/tasks.json 68 | !.vscode/launch.json 69 | !.vscode/extensions.json 70 | *.code-workspace 71 | 72 | # Local History for Visual Studio Code 73 | .history/ 74 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Index.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @inject IJSRuntime JS 3 | @using Markdig 4 | @using System.IO; 5 | @((MarkupString)_htmlReadme) 6 | 7 | @code { 8 | string _htmlReadme; 9 | 10 | protected override void OnInitialized() 11 | { 12 | var readmeContent = loadFromResources("README.md"); 13 | 14 | if (!String.IsNullOrEmpty(readmeContent)) 15 | { 16 | _htmlReadme = Markdown.ToHtml(readmeContent); 17 | } 18 | } 19 | 20 | private string loadFromResources(string name) 21 | { 22 | var assembly = typeof(Index).Assembly; 23 | var resourceName = assembly 24 | .GetManifestResourceNames() 25 | .FirstOrDefault(x => x.Contains(name)); 26 | 27 | if (resourceName is null) 28 | { 29 | return String.Empty; 30 | } 31 | 32 | using var resourceStream = assembly.GetManifestResourceStream(resourceName); 33 | using var reader = new StreamReader(resourceStream); 34 | 35 | return reader.ReadToEnd(); 36 | } 37 | 38 | protected override async Task OnAfterRenderAsync(bool firstRender) 39 | { 40 | if (firstRender) 41 | { 42 | await JS.InvokeVoidAsync("highlightAllCode"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs.Generator/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Diagnostics; 6 | using System.IO; 7 | 8 | namespace SvgBlazor.Docs.Generator 9 | { 10 | public class Program 11 | { 12 | public static int Main(string[] args) 13 | { 14 | if (args.Length == 1) 15 | { 16 | ProjectPaths.SourcePath = Path.Combine(args[0], "src"); 17 | } 18 | else 19 | { 20 | Console.WriteLine($"SvgBlazor.Docs.Generator failed: no solution path provided!"); 21 | return 1; 22 | } 23 | 24 | try 25 | { 26 | var stopWatch = Stopwatch.StartNew(); 27 | 28 | new ExamplesCode().Generate(); 29 | 30 | Console.WriteLine($"SvgBlazor.Docs.Generator completed in {stopWatch.ElapsedMilliseconds} msecs"); 31 | 32 | return 0; 33 | } 34 | catch (Exception ex) 35 | { 36 | Console.WriteLine($"SvgBlazor.Docs.Generator failed: {ex}"); 37 | return 1; 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Extensions/ReflectionTypesExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Reflection; 9 | using System.Text.RegularExpressions; 10 | using System.Xml; 11 | using SvgBlazor.Docs.Models; 12 | 13 | namespace SvgBlazor.Docs.Extensions 14 | { 15 | public static class ReflectionTypesExtensions 16 | { 17 | private static readonly XmlDoc XmlDocumentation = new (Assembly.GetExecutingAssembly()); 18 | 19 | public static string GetDocumentation(this Type type) => 20 | XmlDocumentation.GetDocumentation(type); 21 | 22 | public static string GetDocumentation(this PropertyInfo propertyInfo) => 23 | XmlDocumentation.GetDocumentation(propertyInfo); 24 | 25 | public static string GetSignature(this MethodInfo methodInfo) => 26 | XmlDocumentation.GetSignature(methodInfo); 27 | 28 | public static string GetDocumentation(this MethodInfo methodInfo) => 29 | XmlDocumentation.GetDocumentation(methodInfo); 30 | 31 | public static XmlDoc GetXmlDoc() => XmlDocumentation; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/TextPage.razor: -------------------------------------------------------------------------------- 1 | @page "/elements/text" 2 | 3 | Text 4 | 5 | 6 | 7 |

Shift

8 |

To shift the position of the text assign values to ShiftX and ShiftY properties:

9 | 10 | 11 |

Rotate

12 |

Text rotation can be achieved by assigning properly formatted string to Rotate property:

13 | 14 | 15 |

LengthAdjust

16 |

The following examples show how to control the text stretch based on its length:

17 |

Spacing

18 | 19 | 20 |

SpacingAndGlyphs

21 | 22 |

TextAnchor

23 | 24 |

DominantBaseline

25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/SvgBlazor/SvgBlazor.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | SvgBlazor 6 | Approxoft 7 | Approxoft 8 | The .NET Blazor SVG library. 9 | https://github.com/Approxoft/SvgBlazor 10 | 11 | 12 | 13 | true 14 | 15 | 16 | 17 | 4 18 | 4 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | runtime; build; native; contentfiles; analyzers; buildtransitive 29 | all 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | SvgBlazor.Docs 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 |
20 | 21 |
22 | An unhandled error has occurred. 23 | Reload 24 | 🗙 25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/SvgBlazor/Enums/StrokeLineJoinStyle.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.ComponentModel; 6 | 7 | namespace SvgBlazor 8 | { 9 | /// 10 | /// The stroke's line join styles. 11 | /// 12 | public enum StrokeLineJoinStyle 13 | { 14 | /// 15 | /// The arcs shape will be used to join path segments. 16 | /// 17 | [Description("arcs")] 18 | Arcs, 19 | 20 | /// 21 | /// The sharp corner will be used to join path segments. 22 | /// 23 | [Description("miter")] 24 | Miter, 25 | 26 | /// 27 | /// The sharp corner will be used to join path segments. 28 | /// 29 | [Description("miter-clip")] 30 | MiterClip, 31 | 32 | /// 33 | /// The bevelled corner will be used to join path segments. 34 | /// 35 | [Description("bevel")] 36 | Bevel, 37 | 38 | /// 39 | /// The round corner will be used to join path segments. 40 | /// 41 | [Description("round")] 42 | Round, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Components/ExampleCode.razor: -------------------------------------------------------------------------------- 1 | @using System.IO 2 | @using System.Text.RegularExpressions 3 | @inject IJSRuntime JS 4 | 5 |
Code:
6 |
@((MarkupString)codeMarkup)
7 | 8 | @code { 9 | private string codeMarkup; 10 | 11 | [Parameter] 12 | public string ItemName { get; set; } 13 | 14 | ElementReference elementReference; 15 | 16 | protected override void OnInitialized() 17 | { 18 | var resourceName = typeof(ExampleCode) 19 | .Assembly 20 | .GetManifestResourceNames() 21 | .FirstOrDefault(x => x.Contains($"{ItemName}.html")); 22 | 23 | if (resourceName is null) 24 | { 25 | codeMarkup = "

No code

"; 26 | return; 27 | } 28 | 29 | using (var resourceStream = typeof(ExampleCode).Assembly.GetManifestResourceStream(resourceName)) 30 | { 31 | using (var reader = new StreamReader(resourceStream)) 32 | { 33 | codeMarkup = reader.ReadToEnd(); 34 | } 35 | } 36 | } 37 | 38 | protected override async Task OnAfterRenderAsync(bool firstRender) 39 | { 40 | if (firstRender) 41 | { 42 | await JS.InvokeVoidAsync("highlightCodeElement", elementReference); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/github.min.css: -------------------------------------------------------------------------------- 1 | pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}/*! 2 | Theme: GitHub 3 | Description: Light theme as seen on github.com 4 | Author: github.com 5 | Maintainer: @Hirse 6 | Updated: 2021-05-15 7 | 8 | Outdated base version: https://github.com/primer/github-syntax-light 9 | Current colors taken from GitHub's CSS 10 | */.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0} -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Shared/NavMenu.razor.css: -------------------------------------------------------------------------------- 1 | .navbar-toggler { 2 | background-color: rgba(255, 255, 255, 0.1); 3 | margin-right: 1rem; 4 | } 5 | 6 | .top-row { 7 | height: 3.5rem; 8 | background-color: rgba(0,0,0,0.4); 9 | } 10 | 11 | .navbar-brand { 12 | padding-left: 1rem; 13 | font-size: 1.1rem; 14 | } 15 | 16 | .oi { 17 | width: 2rem; 18 | font-size: 1.1rem; 19 | vertical-align: text-top; 20 | top: -2px; 21 | } 22 | 23 | .nav-item { 24 | font-size: 0.9rem; 25 | padding-bottom: 0.5rem; 26 | } 27 | 28 | .nav-item:first-of-type { 29 | padding-top: 1rem; 30 | } 31 | 32 | .nav-item:last-of-type { 33 | padding-bottom: 1rem; 34 | } 35 | 36 | .nav-item ::deep a { 37 | color: #333; 38 | border-radius: 4px; 39 | height: 3rem; 40 | display: flex; 41 | align-items: center; 42 | line-height: 3rem; 43 | } 44 | 45 | .nav-item ::deep a.active { 46 | background-color: rgba(0,0,0,0.25); 47 | color: black; 48 | } 49 | 50 | .nav-item ::deep a:hover { 51 | background-color: rgba(0,0,0,0.1); 52 | color: black; 53 | } 54 | 55 | @media (min-width: 641px) { 56 | .navbar-toggler { 57 | display: none; 58 | } 59 | 60 | .collapse { 61 | /* Never collapse the sidebar for wide screens */ 62 | display: block; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/SvgBlazor/Enums/ValueUnit.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | namespace SvgBlazor 5 | { 6 | /// 7 | /// The unit types for SvgValue. 8 | /// 9 | public enum ValueUnit 10 | { 11 | /// 12 | /// No unit specified. 13 | /// 14 | NoUnit, 15 | 16 | /// 17 | /// Percentage unit '%'. 18 | /// 19 | Percentage, 20 | 21 | /// 22 | /// The unit 'em'. 23 | /// 24 | Em, 25 | 26 | /// 27 | /// The unit 'ex'. 28 | /// 29 | Ex, 30 | 31 | /// 32 | /// The unit 'px'. 33 | /// 34 | Px, 35 | 36 | /// 37 | /// The unit 'in'. 38 | /// 39 | In, 40 | 41 | /// 42 | /// The unit 'cm'. 43 | /// 44 | Cm, 45 | 46 | /// 47 | /// The unit 'mm'. 48 | /// 49 | Mm, 50 | 51 | /// 52 | /// The unit 'pt'. 53 | /// 54 | Pt, 55 | 56 | /// 57 | /// The unit 'pc'. 58 | /// 59 | Pc, 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Shared/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | .main { 8 | flex: 1; 9 | } 10 | 11 | .sidebar { 12 | background-color: #f7f7f7; 13 | } 14 | 15 | .top-row { 16 | background-color: #f7f7f7; 17 | border-bottom: 1px solid #d6d5d5; 18 | justify-content: flex-end; 19 | height: 3.5rem; 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .top-row ::deep a, .top-row .btn-link { 25 | white-space: nowrap; 26 | margin-left: 1.5rem; 27 | } 28 | 29 | .top-row a:first-child { 30 | overflow: hidden; 31 | text-overflow: ellipsis; 32 | } 33 | 34 | @media (max-width: 640.98px) { 35 | .top-row:not(.auth) { 36 | display: none; 37 | } 38 | 39 | .top-row.auth { 40 | justify-content: space-between; 41 | } 42 | 43 | .top-row a, .top-row .btn-link { 44 | margin-left: 0; 45 | } 46 | } 47 | 48 | @media (min-width: 641px) { 49 | .page { 50 | flex-direction: row; 51 | } 52 | 53 | .sidebar { 54 | width: 250px; 55 | height: 100vh; 56 | position: sticky; 57 | top: 0; 58 | } 59 | 60 | .top-row { 61 | position: sticky; 62 | top: 0; 63 | z-index: 1; 64 | } 65 | 66 | .main > div { 67 | padding-left: 2rem !important; 68 | padding-right: 1.5rem !important; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Use/Examples/SvgUseExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class SvgUseExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var circle = new SvgCircle 14 | { 15 | Id = "circleId", 16 | CenterX = 40, 17 | CenterY = 40, 18 | Radius = 40, 19 | Fill = new SvgFill { Color = "blue" }, 20 | }; 21 | 22 | var svgUse1 = new SvgUse 23 | { 24 | X = 120, 25 | Y = 0, 26 | Element = circle, 27 | }; 28 | 29 | var svgUse2 = new SvgUse 30 | { 31 | X = 0, 32 | Y = 120, 33 | Element = circle, 34 | }; 35 | 36 | var svgUse3 = new SvgUse 37 | { 38 | X = 120, 39 | Y = 120, 40 | Element = circle, 41 | }; 42 | 43 | /* #example-code-end */ 44 | svg.Add(circle); 45 | svg.Add(svgUse1); 46 | svg.Add(svgUse2); 47 | svg.Add(svgUse3); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Fill/Examples/FillColorExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class FillColorExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var fill1 = new SvgFill { Color = "red" }; 14 | 15 | var fill2 = new SvgFill { Color = "green" }; 16 | 17 | var fill3 = new SvgFill { Color = "blue" }; 18 | /* #example-code-end */ 19 | 20 | var circle1 = new SvgCircle 21 | { 22 | CenterX = 100, 23 | CenterY = 100, 24 | Radius = 75, 25 | Fill = fill1, 26 | }; 27 | 28 | var circle2 = new SvgCircle 29 | { 30 | CenterX = 200, 31 | CenterY = 100, 32 | Radius = 75, 33 | Fill = fill2, 34 | }; 35 | 36 | var circle3 = new SvgCircle 37 | { 38 | CenterX = 300, 39 | CenterY = 100, 40 | Radius = 75, 41 | Fill = fill3, 42 | }; 43 | 44 | svg.Add(circle1); 45 | svg.Add(circle2); 46 | svg.Add(circle3); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SvgBlazor 2 | ========= 3 | 4 | ## About 5 | SvgBlazor is a simple library that allows you to write C# code that is transformed directly into svg elements. Thanks to its simple, yet powerful API, you can easily compose beautiful svg drawings. 6 | 7 | ## Getting started 8 | ### 1. Package installation 9 | 10 | To install SvgBlazor use NuGet Package Manager or install it with the following command: 11 | ``` 12 | dotnet add package SvgBlazor 13 | ``` 14 | 15 | ### 2. Imports 16 | Once the installation is complete, add SvgBlazor in _Imports.razor: 17 | ```razor 18 | @using SvgBlazor 19 | ``` 20 | 21 | ### 3. Create a SVG component 22 | Add a SvgComponent tag in your .razor file and capture it's reference by using @ref property: 23 | 24 | ```razor 25 | 26 | 27 | @code { 28 | private SvgComponent svgComponent; 29 | 30 | protected override void OnAfterRender(bool firstRender) 31 | { 32 | if (firstRender) 33 | { 34 | var circle = new SvgCircle 35 | { 36 | CenterX = 100, 37 | CenterY = 100, 38 | Radius = 100, 39 | Fill = new SvgFill 40 | { 41 | Color = "#FF2800", 42 | }, 43 | }; 44 | 45 | svgComponent.Add(circle); 46 | } 47 | } 48 | } 49 | ``` 50 | 51 | ### 4. Enjoy the library! 52 | 53 | ## License 54 | This software is released under the MIT license. 55 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgPath.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Microsoft.AspNetCore.Components.Rendering; 7 | 8 | namespace SvgBlazor 9 | { 10 | /// 11 | /// The SvgPath class is responsible for providing the SVG path element. 12 | /// 13 | public class SvgPath : SvgElement 14 | { 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | public SvgPath() 19 | { 20 | } 21 | 22 | /// 23 | /// Initializes a new instance of the class with provided SvgPath. 24 | /// 25 | /// Initial SvgPath. 26 | public SvgPath(SvgPath svgpath) 27 | : base(svgpath) 28 | { 29 | Path = svgpath.Path; 30 | } 31 | 32 | /// 33 | /// Gets or sets the d string representing the actual path. 34 | /// 35 | public string Path { get; set; } 36 | 37 | /// 38 | public override string Tag() => "path"; 39 | 40 | /// 41 | public override void AddAttributes(RenderTreeBuilder builder) 42 | { 43 | base.AddAttributes(builder); 44 | 45 | builder.AddAttribute(0, "d", Path); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/StrokePage.razor: -------------------------------------------------------------------------------- 1 | @page "/attributes/stroke" 2 | @using SvgBlazor.Docs.Extensions 3 | 4 | Stroke 5 | 6 | 7 |

Basic example

8 |
9 | 10 |

DashArray property

11 |

@( typeof(SvgStroke).GetProperty("DashArray").GetDocumentation() )

12 |
13 | 14 |

DashOffset property

15 |

@( typeof(SvgStroke).GetProperty("DashOffset").GetDocumentation() )

16 |
17 | 18 |

LineCap property

19 |

@( typeof(SvgStroke).GetProperty("LineCap").GetDocumentation() )

20 |
21 | 22 |

LineJoin property

23 |

@( typeof(SvgStroke).GetProperty("LineJoin").GetDocumentation() )

24 |
25 | 26 |

Opacity property

27 |

@( typeof(SvgStroke).GetProperty("Opacity").GetDocumentation() )

28 |
29 | 30 |

MiterLimit property

31 |

@( typeof(SvgStroke).GetProperty("MiterLimit").GetDocumentation() )

32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/CircleTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Drawing; 5 | using Xunit; 6 | using Bunit; 7 | using Microsoft.JSInterop; 8 | using Microsoft.AspNetCore.Components; 9 | 10 | namespace SvgBlazor.Tests 11 | { 12 | public class CircleTest : TestContextWithSvgBlazorJsModule 13 | { 14 | [Fact] 15 | public void RendersSvgCircleWithParameters() 16 | { 17 | var comp = RenderComponent(); 18 | 19 | comp.InvokeAsync(() => comp.Instance.Add(new SvgCircle { 20 | CenterX = 1, 21 | CenterY = 2, 22 | Radius = 3, 23 | })); 24 | 25 | comp.Render(); 26 | 27 | var element = comp.Find("circle"); 28 | Assert.Contains("1", element.GetAttribute("cx")); 29 | Assert.Contains("2", element.GetAttribute("cy")); 30 | Assert.Contains("3", element.GetAttribute("r")); 31 | } 32 | 33 | [Fact] 34 | public void CopyConstructor() 35 | { 36 | var e1 = new SvgCircle() 37 | { 38 | CenterX = 1f, 39 | CenterY = 2f, 40 | Radius = 3f, 41 | }; 42 | 43 | var e2 = new SvgCircle(e1); 44 | 45 | Assert.Equal(1f, e2.CenterX.ToFloat()); 46 | Assert.Equal(2f, e2.CenterY.ToFloat()); 47 | Assert.Equal(3f, e2.Radius.ToFloat()); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/LineTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Drawing; 5 | using Xunit; 6 | using Bunit; 7 | 8 | namespace SvgBlazor.Tests 9 | { 10 | public class LineTest : TestContextWithSvgBlazorJsModule 11 | { 12 | [Fact] 13 | public void RendersSvgLineWithParameters() 14 | { 15 | var comp = RenderComponent(); 16 | 17 | comp.InvokeAsync(() => comp.Instance.Add(new SvgLine() 18 | { 19 | X1 = 1, 20 | Y1 = 2, 21 | X2 = 3, 22 | Y2 = 4, 23 | })); 24 | 25 | comp.Render(); 26 | 27 | var element = comp.Find("line"); 28 | Assert.Contains("1", element.GetAttribute("x1")); 29 | Assert.Contains("2", element.GetAttribute("y1")); 30 | Assert.Contains("3", element.GetAttribute("x2")); 31 | Assert.Contains("4", element.GetAttribute("y2")); 32 | } 33 | 34 | [Fact] 35 | public void CopyConstructor() 36 | { 37 | var e1 = new SvgLine() 38 | { 39 | X1 = 1f, 40 | Y1 = 2f, 41 | X2 = 3f, 42 | Y2 = 4f, 43 | }; 44 | 45 | var e2 = new SvgLine(e1); 46 | 47 | Assert.Equal(1f, e2.X1.ToFloat()); 48 | Assert.Equal(2f, e2.Y1.ToFloat()); 49 | Assert.Equal(3f, e2.X2.ToFloat()); 50 | Assert.Equal(4f, e2.Y2.ToFloat()); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/EllipseTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Drawing; 5 | using Xunit; 6 | using Bunit; 7 | 8 | namespace SvgBlazor.Tests 9 | { 10 | public class EllipseTest : TestContextWithSvgBlazorJsModule 11 | { 12 | [Fact] 13 | public void RendersSvgEllipseWithParameters() 14 | { 15 | var comp = RenderComponent(); 16 | 17 | comp.InvokeAsync(() => comp.Instance.Add(new SvgEllipse() { 18 | CenterX = 1, 19 | CenterY = 2, 20 | RadiusX = 3, 21 | RadiusY = 4, 22 | })); 23 | 24 | comp.Render(); 25 | 26 | var element = comp.Find("ellipse"); 27 | Assert.Contains("1", element.GetAttribute("cx")); 28 | Assert.Contains("2", element.GetAttribute("cy")); 29 | Assert.Contains("3", element.GetAttribute("rx")); 30 | Assert.Contains("4", element.GetAttribute("ry")); 31 | } 32 | 33 | [Fact] 34 | public void CopyConstructor() 35 | { 36 | var e1 = new SvgEllipse() 37 | { 38 | CenterX = 1f, 39 | CenterY = 2f, 40 | RadiusX = 3f, 41 | RadiusY = 4f, 42 | }; 43 | 44 | var e2 = new SvgEllipse(e1); 45 | 46 | Assert.Equal(1f, e2.CenterX.ToFloat()); 47 | Assert.Equal(2f, e2.CenterY.ToFloat()); 48 | Assert.Equal(3f, e2.RadiusX.ToFloat()); 49 | Assert.Equal(4f, e2.RadiusY.ToFloat()); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Fill/Examples/FillOpacityExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class FillOpacityExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | /* #example-code-start */ 13 | var fill1 = new SvgFill 14 | { 15 | Color = "black", 16 | Opacity = 0.3f, 17 | }; 18 | 19 | var fill2 = new SvgFill 20 | { 21 | Color = "black", 22 | Opacity = 0.6f, 23 | }; 24 | 25 | var fill3 = new SvgFill 26 | { 27 | Color = "black", 28 | Opacity = 1f, 29 | }; 30 | /* #example-code-end */ 31 | 32 | var circle1 = new SvgCircle 33 | { 34 | CenterX = 100, 35 | CenterY = 100, 36 | Radius = 75, 37 | Fill = fill1, 38 | }; 39 | 40 | var circle2 = new SvgCircle 41 | { 42 | CenterX = 200, 43 | CenterY = 100, 44 | Radius = 75, 45 | Fill = fill2, 46 | }; 47 | 48 | var circle3 = new SvgCircle 49 | { 50 | CenterX = 300, 51 | CenterY = 100, 52 | Radius = 75, 53 | Fill = fill3, 54 | }; 55 | 56 | svg.Add(circle1); 57 | svg.Add(circle2); 58 | svg.Add(circle3); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/SvgBlazor/Enums/TextDominantBaseline.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.ComponentModel; 5 | 6 | namespace SvgBlazor 7 | { 8 | /// 9 | /// Specifies the baseline used to align the text. 10 | /// 11 | public enum TextDominantBaseline 12 | { 13 | /// 14 | /// Auto alignment. 15 | /// 16 | [Description("auto")] 17 | Auto, 18 | 19 | /// 20 | /// Text bottom alignment. 21 | /// 22 | [Description("text-bottom")] 23 | TextBottom, 24 | 25 | /// 26 | /// Alphabetic alignment. 27 | /// 28 | [Description("alphabetic")] 29 | Alphabetic, 30 | 31 | /// 32 | /// Ideographic alignment. 33 | /// 34 | [Description("ideographic")] 35 | Ideographic, 36 | 37 | /// 38 | /// Middle alignment. 39 | /// 40 | [Description("middle")] 41 | Middle, 42 | 43 | /// 44 | /// Central alignment. 45 | /// 46 | [Description("central")] 47 | Central, 48 | 49 | /// 50 | /// Mathematical alignment. 51 | /// 52 | [Description("mathematical")] 53 | Mathematical, 54 | 55 | /// 56 | /// Hanging alignment. 57 | /// 58 | [Description("hanging")] 59 | Hanging, 60 | 61 | /// 62 | /// Text top alignment. 63 | /// 64 | [Description("text-top")] 65 | TextTop, 66 | } 67 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/app.css: -------------------------------------------------------------------------------- 1 | @import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); 2 | 3 | :root { 4 | --bs-font-sans-serif: Poppins, 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | } 6 | 7 | .content > h2:not(:first-child) { 8 | margin-top: 3rem; 9 | } 10 | 11 | .content > h3 { 12 | margin-top: 2rem; 13 | } 14 | 15 | .content > h4 { 16 | margin-top: 1.5rem; 17 | } 18 | 19 | .content > h5 { 20 | margin-top: 1rem; 21 | } 22 | 23 | a, .btn-link { 24 | color: #0366d6; 25 | } 26 | 27 | .btn-primary { 28 | color: #fff; 29 | background-color: #1b6ec2; 30 | border-color: #1861ac; 31 | } 32 | 33 | .content { 34 | padding-top: 1.1rem; 35 | } 36 | 37 | .valid.modified:not([type=checkbox]) { 38 | outline: 1px solid #26b050; 39 | } 40 | 41 | .invalid { 42 | outline: 1px solid red; 43 | } 44 | 45 | .validation-message { 46 | color: red; 47 | } 48 | 49 | #blazor-error-ui { 50 | background: lightyellow; 51 | bottom: 0; 52 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 53 | display: none; 54 | left: 0; 55 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 56 | position: fixed; 57 | width: 100%; 58 | z-index: 1000; 59 | } 60 | 61 | #blazor-error-ui .dismiss { 62 | cursor: pointer; 63 | position: absolute; 64 | right: 0.75rem; 65 | top: 0.5rem; 66 | } 67 | 68 | #loading-icon { 69 | width: auto; 70 | height: 12%; 71 | position: absolute; 72 | top: 0; 73 | bottom: 0; 74 | left: 0; 75 | right: 0; 76 | margin: auto; 77 | animation: pulse 1.0s alternate infinite ease-in-out; 78 | -webkit-filter: drop-shadow(0px 0px 7px rgba(0, 0, 0, .5)); 79 | filter: drop-shadow(0px 0px 7px rgba(0, 0, 0, .5)); 80 | } 81 | 82 | @keyframes pulse { 83 | 0% { transform: scale(1.0); } 84 | 100% { transform: scale(1.1); } 85 | } 86 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgUse.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Components.Rendering; 6 | 7 | namespace SvgBlazor 8 | { 9 | /// 10 | /// The SvgUse class is responsible for providing the SVG use element. 11 | /// 12 | public class SvgUse : SvgElement 13 | { 14 | /// 15 | /// Gets or sets the element to duplicate. 16 | /// 17 | public SvgElement Element { get; set; } 18 | 19 | /// 20 | /// Gets or sets the width of the duplicated element. 21 | /// 22 | public SvgValue Width { get; set; } 23 | 24 | /// 25 | /// Gets or sets the height of the duplicated element. 26 | /// 27 | public SvgValue Height { get; set; } 28 | 29 | /// 30 | public override string Tag() => "use"; 31 | 32 | /// 33 | public override void AddAttributes(RenderTreeBuilder builder) 34 | { 35 | if (Element is null) 36 | { 37 | throw new Exception("Element to duplicate is not provided"); 38 | } 39 | 40 | var elementId = Element.Id; 41 | 42 | if (string.IsNullOrWhiteSpace(elementId)) 43 | { 44 | throw new Exception("When using use element an id of the element to duplicate must be provided"); 45 | } 46 | 47 | builder.AddAttribute(1, "href", $"#{elementId}"); 48 | builder.AddAttribute(2, "x", X); 49 | builder.AddAttribute(3, "y", Y); 50 | builder.AddAttribute(4, "width", Width); 51 | builder.AddAttribute(5, "height", Height); 52 | 53 | base.AddAttributes(builder); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/Examples/StrokeLineCapExamples.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class StrokeLineCapExamples : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var lineButt = new SvgLine 15 | { 16 | X1 = 15, 17 | Y1 = 15, 18 | X2 = 185, 19 | Y2 = 15, 20 | Stroke = new SvgStroke 21 | { 22 | Color = "black", 23 | Width = 30, 24 | LineCap = StrokeLineCapStyle.Butt, 25 | }, 26 | }; 27 | 28 | var lineRound = new SvgLine 29 | { 30 | X1 = 15, 31 | Y1 = 75, 32 | X2 = 185, 33 | Y2 = 75, 34 | Stroke = new SvgStroke 35 | { 36 | Color = "black", 37 | Width = 30, 38 | LineCap = StrokeLineCapStyle.Round, 39 | }, 40 | }; 41 | 42 | var lineSquare = new SvgLine 43 | { 44 | X1 = 15, 45 | Y1 = 135, 46 | X2 = 185, 47 | Y2 = 135, 48 | Stroke = new SvgStroke 49 | { 50 | Color = "black", 51 | Width = 30, 52 | LineCap = StrokeLineCapStyle.Square, 53 | }, 54 | }; 55 | /* #example-code-end */ 56 | 57 | svg.Add(lineButt); 58 | svg.Add(lineRound); 59 | svg.Add(lineSquare); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Attributes/FillAttributeTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Drawing; 5 | using Microsoft.AspNetCore.Components.Rendering; 6 | using Xunit; 7 | using Bunit; 8 | using SvgBlazor.Interfaces; 9 | 10 | namespace SvgBlazor.Tests 11 | { 12 | public class FillAttributeTest : TestContextWithSvgBlazorJsModule 13 | { 14 | [Fact] 15 | public void RendersAttributes() 16 | { 17 | var comp = RenderComponent(); 18 | 19 | comp.InvokeAsync(() => comp.Instance.Add(new DummyFillAttributesElement { 20 | Fill = new SvgFill 21 | { 22 | Color = "green", 23 | Opacity = 0.5f, 24 | Rule = FillRule.EvenOdd, 25 | }, 26 | })); 27 | 28 | comp.Render(); 29 | 30 | var element = comp.Find("elementwithfill"); 31 | Assert.Contains("green", element.GetAttribute("fill")); 32 | Assert.Contains("0.5", element.GetAttribute("fill-opacity")); 33 | Assert.Contains("evenodd", element.GetAttribute("fill-rule")); 34 | } 35 | 36 | [Fact] 37 | public void CopyConstructor() 38 | { 39 | var e1 = new SvgFill() 40 | { 41 | Color = "green", 42 | Opacity = 0.5f, 43 | Rule = FillRule.EvenOdd, 44 | }; 45 | 46 | var e2 = new SvgFill(e1); 47 | 48 | Assert.Equal("green", e2.Color); 49 | Assert.Equal(0.5f, e2.Opacity.ToFloat()); 50 | Assert.Equal(FillRule.EvenOdd, e2.Rule); 51 | } 52 | 53 | private class DummyFillAttributesElement : SvgElement 54 | { 55 | public override string Tag() => "elementwithfill"; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/RectTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Xunit; 7 | using Bunit; 8 | 9 | namespace SvgBlazor.Tests 10 | { 11 | public class RectTest : TestContextWithSvgBlazorJsModule 12 | { 13 | [Fact] 14 | public void RendersSvgRectWithParameters() 15 | { 16 | var comp = RenderComponent(); 17 | 18 | comp.InvokeAsync(() => comp.Instance.Add(new SvgRect() 19 | { 20 | X = 1, 21 | Y = 2, 22 | Width = 3, 23 | Height = 4, 24 | Rx = 5, 25 | Ry = 6, 26 | })); 27 | 28 | comp.Render(); 29 | 30 | var element = comp.Find("rect"); 31 | Assert.Contains("1", element.GetAttribute("x")); 32 | Assert.Contains("2", element.GetAttribute("y")); 33 | Assert.Contains("3", element.GetAttribute("width")); 34 | Assert.Contains("4", element.GetAttribute("height")); 35 | Assert.Contains("5", element.GetAttribute("rx")); 36 | Assert.Contains("6", element.GetAttribute("ry")); 37 | } 38 | 39 | [Fact] 40 | public void CopyConstructor() 41 | { 42 | var e1 = new SvgRect() 43 | { 44 | X = 1f, 45 | Y = 2f, 46 | Width = 3f, 47 | Height = 4f, 48 | Rx = 5f, 49 | Ry = 6f, 50 | }; 51 | 52 | var e2 = new SvgRect(e1); 53 | 54 | Assert.Equal(1f, e2.X.ToFloat()); 55 | Assert.Equal(2f, e2.Y.ToFloat()); 56 | Assert.Equal(3f, e2.Width.ToFloat()); 57 | Assert.Equal(4f, e2.Height.ToFloat()); 58 | Assert.Equal(5f, e2.Rx.ToFloat()); 59 | Assert.Equal(6f, e2.Ry.ToFloat()); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/SvgBlazor/Interop/SvgElementConnector.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Components.Web; 6 | 7 | namespace SvgBlazor.Interop 8 | { 9 | /// 10 | /// The class that represents the connection between SvgComponent and SvgElement. 11 | /// 12 | public class SvgElementConnector : Svg 13 | { 14 | private readonly SvgComponent _svgComponent; 15 | 16 | /// 17 | /// Initializes a new instance of the class with provided SvgComponent. 18 | /// 19 | /// Initial SvgComponent. 20 | public SvgElementConnector(SvgComponent component) 21 | { 22 | _svgComponent = component; 23 | } 24 | 25 | /// 26 | public override void Refresh() => _svgComponent.Refresh(); 27 | 28 | /// 29 | public override async Task OnClickHandler(MouseEventArgs args) 30 | { 31 | await base.OnClickHandler(args); 32 | await _svgComponent.OnClick.InvokeAsync(); 33 | } 34 | 35 | /// 36 | public override async Task OnMouseDownHandler(MouseEventArgs args) 37 | { 38 | await base.OnMouseDownHandler(args); 39 | await _svgComponent.OnMouseDown.InvokeAsync(); 40 | } 41 | 42 | /// 43 | public override async Task OnMouseMoveHandler(MouseEventArgs args) 44 | { 45 | await base.OnMouseMoveHandler(args); 46 | await _svgComponent.OnMouseMove.InvokeAsync(); 47 | } 48 | 49 | /// 50 | public override async Task OnMouseUpHandler(MouseEventArgs args) 51 | { 52 | await base.OnMouseUpHandler(args); 53 | await _svgComponent.OnMouseUp.InvokeAsync(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/SvgBlazor/Attributes/SvgFill.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Components.Rendering; 5 | using SvgBlazor.Extensions; 6 | using SvgBlazor.Interfaces; 7 | 8 | namespace SvgBlazor 9 | { 10 | /// 11 | /// The SvgFill determines how the interior of a given SVG element is painted. 12 | /// 13 | public class SvgFill : ISvgAttribute 14 | { 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | public SvgFill() 19 | { 20 | } 21 | 22 | /// 23 | /// Initializes a new instance of the class with provided Fill. 24 | /// 25 | /// Initial SVG fill. 26 | public SvgFill(SvgFill svgFill) 27 | { 28 | Color = svgFill.Color; 29 | Opacity = svgFill.Opacity; 30 | Rule = svgFill.Rule; 31 | } 32 | 33 | /// 34 | /// Gets or sets the paint used to render the interior of shapes. This can be a color, pattern or gradient (e.g. url(#pattern)). 35 | /// 36 | public string Color { get; set; } 37 | 38 | /// 39 | /// Gets or sets the opacity of the painting operation. 40 | /// 41 | public SvgValue Opacity { get; set; } 42 | 43 | /// 44 | /// Gets or sets the rule that determines which parts of the canvas are contained within the shape. 45 | /// 46 | public FillRule? Rule { get; set; } 47 | 48 | /// 49 | public void RenderAttributes(RenderTreeBuilder builder) 50 | { 51 | builder.AddAttribute(0, "fill", Color); 52 | builder.AddAttribute(1, "fill-opacity", Opacity); 53 | builder.AddAttribute(2, "fill-rule", Rule?.ToDescriptionString()); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/SvgPolygonTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Xunit; 7 | using Bunit; 8 | using System.Collections.Generic; 9 | 10 | namespace SvgBlazor.Tests 11 | { 12 | public class SvgPolygonTest : TestContextWithSvgBlazorJsModule 13 | { 14 | [Fact] 15 | public void RendersSvgPolygonWithParameters() 16 | { 17 | var comp = RenderComponent(); 18 | 19 | var polygon = new SvgPolygon(); 20 | polygon.AddPoint(new PointF(0, 0.1f)); 21 | polygon.AddPoint(new PointF(200, 200.01f)); 22 | 23 | comp.InvokeAsync(() => comp.Instance.Add(polygon)); 24 | 25 | comp.Render(); 26 | 27 | var element = comp.Find("polygon"); 28 | Assert.Equal("0 0.1 200 200.01", element.GetAttribute("points")); 29 | } 30 | 31 | [Fact] 32 | public void RendersSvgPolygonWithSetPoints() 33 | { 34 | var comp = RenderComponent(); 35 | 36 | var polygon = new SvgPolygon 37 | { 38 | Points = new List 39 | { 40 | new PointF(0, 0), 41 | new PointF(200, 200), 42 | }, 43 | }; 44 | 45 | comp.InvokeAsync(() => comp.Instance.Add(polygon)); 46 | comp.Render(); 47 | 48 | var element = comp.Find("polygon"); 49 | Assert.Equal("0 0 200 200", element.GetAttribute("points")); 50 | } 51 | 52 | [Fact] 53 | public void CopyConstructor() 54 | { 55 | var e1 = new SvgPolygon() 56 | { 57 | Points = new List 58 | { 59 | new PointF(0, 0), 60 | new PointF(200, 200), 61 | }, 62 | }; 63 | 64 | var e2 = new SvgPolygon(e1); 65 | 66 | Assert.Equal(e1.Points, e2.Points); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/Examples/TexDominantBaselineExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class TexDominantBaselineExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | DrawLines(svg); 13 | { 14 | /* #example-code-start */ 15 | var text = new SvgText 16 | { 17 | X = 10, 18 | Y = 30, 19 | Text = "Auto", 20 | DominantBaseline = TextDominantBaseline.Auto, 21 | }; 22 | /* #example-code-end */ 23 | svg.Add(text); 24 | } 25 | 26 | { 27 | /* #example-code-start */ 28 | var text = new SvgText 29 | { 30 | X = 10, 31 | Y = 60, 32 | Text = "Middle", 33 | DominantBaseline = TextDominantBaseline.Middle, 34 | }; 35 | /* #example-code-end */ 36 | svg.Add(text); 37 | } 38 | 39 | { 40 | /* #example-code-start */ 41 | var text = new SvgText 42 | { 43 | X = 10, 44 | Y = 90, 45 | Text = "Hanging", 46 | DominantBaseline = TextDominantBaseline.Hanging, 47 | }; 48 | /* #example-code-end */ 49 | svg.Add(text); 50 | } 51 | } 52 | 53 | private void DrawLines(SvgComponent svg) 54 | { 55 | var path = new SvgPath(); 56 | path.Path = "M0,30 L200,30 M0,60 L200,60 M0,90 L200,90"; 57 | path.Stroke = new SvgStroke 58 | { 59 | Color = "lightgray", 60 | DashArray = "4", 61 | }; 62 | 63 | svg.Add(path); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Components/ElementApiDocs.razor: -------------------------------------------------------------------------------- 1 | @using System 2 | @using System.Reflection 3 | @using SvgBlazor.Docs.Models 4 | @using SvgBlazor.Docs.Extensions 5 | @using SvgBlazor.Docs.Extractors 6 | 7 |

@ElementType.Name API

8 |

Properties

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | @foreach (var property in GetElementApiProperties()) 19 | { 20 | 21 | 22 | 23 | 24 | 25 | } 26 | 27 |
NameTypeDescription
@property.Name@property.Type@property.Description
28 | 29 |

Methods

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | @foreach (var method in GetElementApiMethods()) 41 | { 42 | 43 | 44 | 50 | 51 | 52 | 53 | } 54 | 55 |
NameParametersReturn valueDescription
@method.Name 45 | @foreach (var p in method.Parameters) 46 | { 47 |

@p

48 | } 49 |
@method.ReturnValue@method.Description
56 | 57 | @code { 58 | [Parameter] 59 | public Type ElementType { get; set; } 60 | 61 | private ElementApiExtractor _extractor = new (ReflectionTypesExtensions.GetXmlDoc()); 62 | 63 | private IEnumerable GetElementApiMethods() => 64 | _extractor.ExtractApiMethods(ElementType); 65 | 66 | private IEnumerable GetElementApiProperties() => 67 | _extractor.ExtractApiProperties(ElementType); 68 | 69 | private IEnumerable ParametersToString(ParameterInfo[] parameters) => 70 | parameters.Select(x => (x.ParameterType.FullName + " " + x.Name)).ToArray(); 71 | } 72 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/Examples/StrokeMiterLimitExamples.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class StrokeMiterLimitExamples : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var noMiterLimitPath = new SvgPath 15 | { 16 | Path = "m 15 70 l 85 -49 l 85 50", 17 | Stroke = new SvgStroke 18 | { 19 | Color = "black", 20 | LineJoin = StrokeLineJoinStyle.Miter, 21 | Width = 30, 22 | }, 23 | Fill = new SvgFill 24 | { 25 | Color = "none", 26 | }, 27 | }; 28 | 29 | var miterLimit1Path = new SvgPath 30 | { 31 | Path = "m 15 130 l 85 -49 l 85 50", 32 | Stroke = new SvgStroke 33 | { 34 | Color = "black", 35 | LineJoin = StrokeLineJoinStyle.Miter, 36 | Width = 30, 37 | MiterLimit = 1, 38 | }, 39 | Fill = new SvgFill 40 | { 41 | Color = "none", 42 | }, 43 | }; 44 | 45 | var miterLimit2Path = new SvgPath 46 | { 47 | Path = "m 15 200 l 85 -49 l 85 50", 48 | Stroke = new SvgStroke 49 | { 50 | Color = "black", 51 | LineJoin = StrokeLineJoinStyle.Miter, 52 | Width = 30, 53 | MiterLimit = 2, 54 | }, 55 | Fill = new SvgFill 56 | { 57 | Color = "none", 58 | }, 59 | }; 60 | 61 | /* #example-code-end */ 62 | svg.Add(noMiterLimitPath); 63 | svg.Add(miterLimit1Path); 64 | svg.Add(miterLimit2Path); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgCircle.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Components.Rendering; 8 | 9 | namespace SvgBlazor 10 | { 11 | /// 12 | /// The SvgCircle class is responsible for providing the SVG circle element. 13 | /// 14 | public class SvgCircle : SvgElement 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | public SvgCircle() 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class with provided SvgCircle. 25 | /// 26 | /// Initial SvgCircle. 27 | public SvgCircle(SvgCircle svgcircle) 28 | : base(svgcircle) 29 | { 30 | CenterX = svgcircle.CenterX; 31 | CenterY = svgcircle.CenterY; 32 | Radius = svgcircle.Radius; 33 | } 34 | 35 | /// 36 | /// Gets or sets the x-axis coordinate of the center of the circle. 37 | /// 38 | public SvgValue CenterX 39 | { 40 | get => X; 41 | set => X = value; 42 | } 43 | 44 | /// 45 | /// Gets or sets the y-axis coordinate of the center of the circle. 46 | /// 47 | public SvgValue CenterY 48 | { 49 | get => Y; 50 | set => Y = value; 51 | } 52 | 53 | /// 54 | /// Gets or sets the radius of the circle. 55 | /// 56 | public SvgValue Radius { get; set; } 57 | 58 | /// 59 | public override string Tag() => "circle"; 60 | 61 | /// 62 | public override void AddAttributes(RenderTreeBuilder builder) 63 | { 64 | base.AddAttributes(builder); 65 | builder.AddAttribute(0, "cx", X); 66 | builder.AddAttribute(1, "cy", Y); 67 | builder.AddAttribute(2, "r", Radius); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgLine.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Components.Rendering; 8 | 9 | namespace SvgBlazor 10 | { 11 | /// 12 | /// The SvgLine class is responsible for providing the SVG line element. 13 | /// 14 | public partial class SvgLine : SvgElement 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | public SvgLine() 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class with provided SvgLine. 25 | /// 26 | /// Initial SvgLine. 27 | public SvgLine(SvgLine svgline) 28 | : base(svgline) 29 | { 30 | X1 = svgline.X1; 31 | Y1 = svgline.Y1; 32 | X2 = svgline.X2; 33 | Y2 = svgline.Y2; 34 | } 35 | 36 | /// 37 | /// Gets or sets start point x-axis coordinate. 38 | /// 39 | public SvgValue X1 40 | { 41 | get => X; 42 | set => X = value; 43 | } 44 | 45 | /// 46 | /// Gets or sets start point y-axis coordinate. 47 | /// 48 | public SvgValue Y1 49 | { 50 | get => Y; 51 | set => Y = value; 52 | } 53 | 54 | /// 55 | /// Gets or sets the end point x-axis coordinate. 56 | /// 57 | public SvgValue X2 { get; set; } 58 | 59 | /// 60 | /// Gets or sets the end point y-axis coordinate. 61 | /// 62 | public SvgValue Y2 { get; set; } 63 | 64 | /// 65 | public override string Tag() => "line"; 66 | 67 | /// 68 | public override void AddAttributes(RenderTreeBuilder builder) 69 | { 70 | base.AddAttributes(builder); 71 | builder.AddAttribute(0, "x1", X1); 72 | builder.AddAttribute(1, "y1", Y1); 73 | builder.AddAttribute(2, "x2", X2); 74 | builder.AddAttribute(3, "y2", Y2); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Elements/SvgComponent.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Drawing; 5 | using Xunit; 6 | using Bunit; 7 | 8 | namespace SvgBlazor.Tests 9 | { 10 | public class SvgComponentTest : TestContextWithSvgBlazorJsModule 11 | { 12 | [Fact] 13 | public void SvgComponentOnClick() 14 | { 15 | bool eventHandled = false; 16 | 17 | var comp = RenderComponent(parameters => parameters 18 | .Add(p => p.OnClick, _ => { eventHandled = true; }) 19 | ); 20 | 21 | comp.Render(); 22 | 23 | var svg = comp.Find("svg"); 24 | svg.Click(); 25 | 26 | Assert.True(eventHandled); 27 | } 28 | 29 | [Fact] 30 | public void SvgComponentOnMouseDown() 31 | { 32 | bool eventHandled = false; 33 | 34 | var comp = RenderComponent(parameters => parameters 35 | .Add(p => p.OnMouseDown, _ => { eventHandled = true; }) 36 | ); 37 | 38 | comp.Render(); 39 | 40 | var svg = comp.Find("svg"); 41 | svg.MouseDown(); 42 | 43 | Assert.True(eventHandled); 44 | } 45 | 46 | [Fact] 47 | public void SvgComponentOnMouseUp() 48 | { 49 | bool eventHandled = false; 50 | 51 | var comp = RenderComponent(parameters => parameters 52 | .Add(p => p.OnMouseUp, _ => { eventHandled = true; }) 53 | ); 54 | 55 | comp.Render(); 56 | 57 | var svg = comp.Find("svg"); 58 | svg.MouseUp(); 59 | 60 | Assert.True(eventHandled); 61 | } 62 | 63 | [Fact] 64 | public void SvgComponentOnMouseMove() 65 | { 66 | bool eventHandled = false; 67 | 68 | var comp = RenderComponent(parameters => parameters 69 | .Add(p => p.OnMouseMove, _ => { eventHandled = true; }) 70 | ); 71 | 72 | comp.Render(); 73 | 74 | var svg = comp.Find("svg"); 75 | svg.MouseMove(); 76 | 77 | Assert.True(eventHandled); 78 | } 79 | 80 | private class DummyElement : SvgElement 81 | { 82 | public override string Tag() => "dummy"; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgRect.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Components.Rendering; 8 | 9 | namespace SvgBlazor 10 | { 11 | /// 12 | /// The SvgRect class is responsible for providing the SVG rect element. 13 | /// 14 | public class SvgRect : SvgElement 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | public SvgRect() 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class with provided SvgRect. 25 | /// 26 | /// Initial SvgRect. 27 | public SvgRect(SvgRect svgrect) 28 | : base(svgrect) 29 | { 30 | Width = svgrect.Width; 31 | Height = svgrect.Height; 32 | Rx = svgrect.Rx; 33 | Ry = svgrect.Ry; 34 | } 35 | 36 | /// 37 | /// Gets or sets the width of the rect. 38 | /// 39 | public SvgValue Width { get; set; } 40 | 41 | /// 42 | /// Gets or sets the height of the rect. 43 | /// 44 | public SvgValue Height { get; set; } 45 | 46 | /// 47 | /// Gets or sets the horizontal corner radius of the rect. Defaults to Ry (if specified). 48 | /// 49 | public SvgValue Rx { get; set; } 50 | 51 | /// 52 | /// Gets or sets the vertical corner radius of the rect. Defaults to Rx (if specified). 53 | /// 54 | public SvgValue Ry { get; set; } 55 | 56 | /// 57 | public override string Tag() => "rect"; 58 | 59 | /// 60 | public override void AddAttributes(RenderTreeBuilder builder) 61 | { 62 | base.AddAttributes(builder); 63 | builder.AddAttribute(0, "x", X); 64 | builder.AddAttribute(1, "y", Y); 65 | builder.AddAttribute(2, "width", Width); 66 | builder.AddAttribute(3, "height", Height); 67 | builder.AddAttribute(4, "rx", Rx); 68 | builder.AddAttribute(5, "ry", Ry); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/SvgBlazor.Docs.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | $(MSBuildThisFileDirectory)../../ 9 | 10 | 11 | 12 | $(SolutionDir)src/SvgBlazor.Docs.Generator/bin/$(Configuration)/net6.0/SvgBlazor.Docs.Generator.dll 13 | $(SolutionDir)src/SvgBlazor/obj/$(Configuration)/net6.0/SvgBlazor.xml 14 | $(SolutionDir)README.md 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | runtime; build; native; contentfiles; analyzers; buildtransitive 43 | all 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgEllipse.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Components.Rendering; 8 | 9 | namespace SvgBlazor 10 | { 11 | /// 12 | /// The SvgEllipse class is responsible for providing the SVG ellipse element. 13 | /// 14 | public class SvgEllipse : SvgElement 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | public SvgEllipse() 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class with provided SvgEllipse. 25 | /// 26 | /// Initial SvgEllipse. 27 | public SvgEllipse(SvgEllipse svgellipse) 28 | : base(svgellipse) 29 | { 30 | CenterX = svgellipse.CenterX; 31 | CenterY = svgellipse.CenterY; 32 | RadiusX = svgellipse.RadiusX; 33 | RadiusY = svgellipse.RadiusY; 34 | } 35 | 36 | /// 37 | /// Gets or sets the x-axis coordinate of the center of the ellipse. 38 | /// 39 | public SvgValue CenterX 40 | { 41 | get => X; 42 | set => X = value; 43 | } 44 | 45 | /// 46 | /// Gets or sets the y-axis coordinate of the center of the ellipse. 47 | /// 48 | public SvgValue CenterY 49 | { 50 | get => Y; 51 | set => Y = value; 52 | } 53 | 54 | /// 55 | /// Gets or sets the radius on the x axis. 56 | /// 57 | public SvgValue RadiusX { get; set; } 58 | 59 | /// 60 | /// Gets or sets the radius on the y axis. 61 | /// 62 | public SvgValue RadiusY { get; set; } 63 | 64 | /// 65 | public override string Tag() => "ellipse"; 66 | 67 | /// 68 | public override void AddAttributes(RenderTreeBuilder builder) 69 | { 70 | base.AddAttributes(builder); 71 | builder.AddAttribute(0, "cx", CenterX); 72 | builder.AddAttribute(1, "cy", CenterY); 73 | builder.AddAttribute(2, "rx", RadiusX); 74 | builder.AddAttribute(3, "ry", RadiusY); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /.github/workflows/base-workflow.yml: -------------------------------------------------------------------------------- 1 | name: Base workflow 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | version: 7 | required: false 8 | type: string 9 | default: '0.0.0' 10 | dotnet-version: 11 | required: false 12 | type: string 13 | default: '6.0.x' 14 | publish-docs: 15 | required: false 16 | type: boolean 17 | default: false 18 | publish-nuget: 19 | required: false 20 | type: boolean 21 | default: false 22 | secrets: 23 | nuget-api-key: 24 | required: false 25 | jobs: 26 | build-and-test: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v2 30 | - name: Setup .NET 31 | uses: actions/setup-dotnet@v1 32 | with: 33 | dotnet-version: ${{ inputs.dotnet-version }} 34 | - name: Restore dependencies 35 | run: dotnet restore 36 | - name: Build 37 | run: dotnet build --no-restore 38 | - name: Test 39 | run: dotnet test --no-build --verbosity normal 40 | publish-docs: 41 | runs-on: ubuntu-latest 42 | if: ${{ inputs.publish-docs == true }} 43 | steps: 44 | - uses: actions/checkout@v2 45 | - name: Setup .NET 46 | uses: actions/setup-dotnet@v1 47 | with: 48 | dotnet-version: ${{ inputs.dotnet-version }} 49 | - name: Build 50 | run: dotnet build -c Release 51 | - name: Publish docs project 52 | run: dotnet publish ./src/SvgBlazor.Docs/SvgBlazor.Docs.csproj -c Release -o docsrelease --nologo 53 | - name: Change base-tag 54 | run: sed -i 's///g' docsrelease/wwwroot/index.html 55 | - name: Add .nojekyll file 56 | run: touch docsrelease/wwwroot/.nojekyll 57 | - name: Commit wwwroot to GitHub Pages 58 | uses: JamesIves/github-pages-deploy-action@3.7.1 59 | with: 60 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | BRANCH: gh-pages 62 | FOLDER: docsrelease/wwwroot 63 | publish-and-pack: 64 | runs-on: ubuntu-latest 65 | if: ${{ inputs.publish-nuget == true }} 66 | steps: 67 | - uses: actions/checkout@v2 68 | - name: Setup .NET 69 | uses: actions/setup-dotnet@v1 70 | with: 71 | dotnet-version: ${{ inputs.dotnet-version }} 72 | - name: Pack 73 | run: dotnet pack ./src/SvgBlazor/SvgBlazor.csproj -o output -c Release /p:Version=${{ inputs.version }} 74 | - name: Publish 75 | run: dotnet nuget push output/SvgBlazor.${{ inputs.version }}.nupkg -s https://api.nuget.org/v3/index.json -k ${{ secrets.nuget-api-key }} --skip-duplicate 76 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/ValueUnitTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using Xunit; 6 | using SvgBlazor; 7 | 8 | namespace SvgBlazor.Tests 9 | { 10 | public class ValueUnitTest 11 | { 12 | [Theory] 13 | [InlineData(1.1, "1.1")] 14 | [InlineData(1, "1")] 15 | [InlineData(0, "0")] 16 | public void ConstructorWithFloatValue(float value, string expected) 17 | { 18 | var svgValue = new SvgValue(value); 19 | Assert.Equal(expected, svgValue.ToString()); 20 | } 21 | 22 | [Theory] 23 | [InlineData(1.1, ValueUnit.Mm, "1.1mm")] 24 | [InlineData(1, ValueUnit.Percentage, "1%")] 25 | [InlineData(0, ValueUnit.NoUnit, "0")] 26 | public void ConstructorWithFloatValueAndUnit(float value, ValueUnit unit, string expected) 27 | { 28 | var svgValue = new SvgValue(value, unit); 29 | Assert.Equal(expected, svgValue.ToString()); 30 | } 31 | 32 | [Theory] 33 | [InlineData("123", "123")] 34 | [InlineData("test", "test")] 35 | public void ConstructorWithStringValue(string value, string expected) 36 | { 37 | var svgValue = new SvgValue(value); 38 | Assert.Equal(expected, svgValue.ToString()); 39 | } 40 | 41 | [Fact] 42 | public void ConstructorWithSvgValue() 43 | { 44 | var v1 = new SvgValue(1, ValueUnit.Percentage); 45 | var v2 = new SvgValue(v1); 46 | Assert.Equal("1%", v2.ToString()); 47 | } 48 | 49 | [Fact] 50 | public void AssignsFloat() 51 | { 52 | SvgValue value = 1.1f; 53 | Assert.Equal("1.1", value.ToString()); 54 | } 55 | 56 | [Fact] 57 | public void AssignsString() 58 | { 59 | SvgValue value = "test"; 60 | Assert.Equal("test", value.ToString()); 61 | } 62 | 63 | [Fact] 64 | public void AssignsInt() 65 | { 66 | SvgValue value = 1; 67 | Assert.Equal("1", value.ToString()); 68 | } 69 | 70 | [Fact] 71 | public void AssignsSvgValueAuto() 72 | { 73 | SvgValue value = SvgValue.Auto; 74 | Assert.Equal("auto", value.ToString()); 75 | } 76 | 77 | [Fact] 78 | public void AssignsDefaultSvgValue() 79 | { 80 | var value = new SvgValue(); 81 | Assert.Empty(value.ToString()); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Elements/Text/Examples/TextTextAnchorExample.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Interfaces; 5 | 6 | namespace SvgBlazor.Docs.Examples 7 | { 8 | public class TextTextAnchorExample : IExampleCode 9 | { 10 | public void Example(SvgComponent svg) 11 | { 12 | DrawLines(svg); 13 | { 14 | /* #example-code-start */ 15 | var text = new SvgText 16 | { 17 | X = 200, 18 | Y = 30, 19 | Text = "Let's drop the anchor", 20 | TextAnchor = TextAnchor.Start, 21 | }; 22 | /* #example-code-end */ 23 | svg.Add(text); 24 | } 25 | 26 | { 27 | /* #example-code-start */ 28 | var text = new SvgText 29 | { 30 | X = 200, 31 | Y = 60, 32 | Text = "Let's drop the anchor", 33 | TextAnchor = TextAnchor.Middle, 34 | }; 35 | /* #example-code-end */ 36 | svg.Add(text); 37 | } 38 | 39 | { 40 | /* #example-code-start */ 41 | var text = new SvgText 42 | { 43 | X = 200, 44 | Y = 90, 45 | Text = "Let's drop the anchor", 46 | TextAnchor = TextAnchor.End, 47 | }; 48 | /* #example-code-end */ 49 | svg.Add(text); 50 | } 51 | 52 | DrawCircles(svg); 53 | } 54 | 55 | private void DrawLines(SvgComponent svg) 56 | { 57 | var path = new SvgPath(); 58 | path.Path = "M200,0 L200,110 M0,30 L400,30 M0,60 L400,60 M0,90 L400,90"; 59 | path.Stroke = new SvgStroke 60 | { 61 | Color = "lightgray", 62 | DashArray = "4", 63 | }; 64 | 65 | svg.Add(path); 66 | } 67 | 68 | private void DrawCircles(SvgComponent svg) 69 | { 70 | var circle1 = new SvgCircle 71 | { 72 | CenterX = 200, 73 | CenterY = 30, 74 | Radius = 3, 75 | Fill = new SvgFill 76 | { 77 | Color = "red", 78 | }, 79 | }; 80 | 81 | var circle2 = new SvgCircle(circle1); 82 | circle2.CenterY = 60; 83 | 84 | var circle3 = new SvgCircle(circle1); 85 | circle3.CenterY = 90; 86 | 87 | svg.Add(circle1); 88 | svg.Add(circle2); 89 | svg.Add(circle3); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Pages/Attributes/Stroke/Examples/StrokeLineJoinExamples.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using SvgBlazor.Docs.Interfaces; 6 | 7 | namespace SvgBlazor.Docs.Examples 8 | { 9 | public class StrokeLineJoinExamples : IExampleCode 10 | { 11 | public void Example(SvgComponent svg) 12 | { 13 | /* #example-code-start */ 14 | var minterPath = new SvgPath 15 | { 16 | Path = "m 15 86 c 0 0 125 0 71 -49 c 58 13 65 21 65 52", 17 | Stroke = new SvgStroke 18 | { 19 | Color = "black", 20 | Width = 25, 21 | LineJoin = StrokeLineJoinStyle.Miter, 22 | }, 23 | Fill = new SvgFill { Color = "none" }, 24 | }; 25 | 26 | var roundPath = new SvgPath 27 | { 28 | Path = "m 15 186 c 0 0 125 0 71 -49 c 58 13 65 21 65 52", 29 | Stroke = new SvgStroke 30 | { 31 | Color = "black", 32 | Width = 25, 33 | LineJoin = StrokeLineJoinStyle.Round, 34 | }, 35 | Fill = new SvgFill { Color = "none" }, 36 | }; 37 | 38 | var bevelPath = new SvgPath 39 | { 40 | Path = "m 15 286 c 0 0 125 0 71 -49 c 58 13 65 21 65 52", 41 | Stroke = new SvgStroke 42 | { 43 | Color = "black", 44 | Width = 25, 45 | LineJoin = StrokeLineJoinStyle.Bevel, 46 | }, 47 | Fill = new SvgFill { Color = "none" }, 48 | }; 49 | 50 | var miterClipPath = new SvgPath 51 | { 52 | Path = "m 15 386 c 0 0 125 0 71 -49 c 58 13 65 21 65 52", 53 | Stroke = new SvgStroke 54 | { 55 | Color = "black", 56 | Width = 25, 57 | LineJoin = StrokeLineJoinStyle.MiterClip, 58 | }, 59 | Fill = new SvgFill { Color = "none" }, 60 | }; 61 | 62 | var arcsPath = new SvgPath 63 | { 64 | Path = "m 15 486 c 0 0 125 0 71 -49 c 58 13 65 21 65 52", 65 | Stroke = new SvgStroke 66 | { 67 | Color = "black", 68 | Width = 25, 69 | LineJoin = StrokeLineJoinStyle.Arcs, 70 | }, 71 | Fill = new SvgFill { Color = "none" }, 72 | }; 73 | 74 | /* #example-code-end */ 75 | svg.Add(minterPath); 76 | svg.Add(roundPath); 77 | svg.Add(bevelPath); 78 | svg.Add(miterClipPath); 79 | svg.Add(arcsPath); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/SvgBlazor/Base/SvgEventHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Components.Web; 8 | using SvgBlazor.Interfaces; 9 | 10 | namespace SvgBlazor 11 | { 12 | /// 13 | /// The base class for event handling. 14 | /// 15 | public class SvgEventHandler : ISvgEventHandler 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | public SvgEventHandler() 21 | { 22 | } 23 | 24 | /// 25 | /// Initializes a new instance of the class with provided SvgEventHandler. 26 | /// 27 | /// Initial SvgEventHandler. 28 | public SvgEventHandler(SvgEventHandler svgeventhandler) 29 | { 30 | OnClick = svgeventhandler.OnClick; 31 | OnMouseDown = svgeventhandler.OnMouseDown; 32 | OnMouseMove = svgeventhandler.OnMouseMove; 33 | OnMouseUp = svgeventhandler.OnMouseUp; 34 | OnMouseOver = svgeventhandler.OnMouseOver; 35 | OnMouseOut = svgeventhandler.OnMouseOut; 36 | } 37 | 38 | /// 39 | public EventCallback OnClick { get; set; } 40 | 41 | /// 42 | public EventCallback OnMouseDown { get; set; } 43 | 44 | /// 45 | public EventCallback OnMouseMove { get; set; } 46 | 47 | /// 48 | public EventCallback OnMouseUp { get; set; } 49 | 50 | /// 51 | public EventCallback OnMouseOver { get; set; } 52 | 53 | /// 54 | public EventCallback OnMouseOut { get; set; } 55 | 56 | /// 57 | public virtual async Task OnClickHandler(MouseEventArgs args) => await OnClick.InvokeAsync(args); 58 | 59 | /// 60 | public virtual async Task OnMouseDownHandler(MouseEventArgs args) => await OnMouseDown.InvokeAsync(args); 61 | 62 | /// 63 | public virtual async Task OnMouseMoveHandler(MouseEventArgs args) => await OnMouseMove.InvokeAsync(args); 64 | 65 | /// 66 | public virtual async Task OnMouseUpHandler(MouseEventArgs args) => await OnMouseUp.InvokeAsync(args); 67 | 68 | /// 69 | public virtual async Task OnMouseOverHandler(MouseEventArgs args) => await OnMouseOver.InvokeAsync(args); 70 | 71 | /// 72 | public virtual async Task OnMouseOutHandler(MouseEventArgs args) => await OnMouseOut.InvokeAsync(args); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Docs.Tests/ReflectionTypesExtensionsTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using SvgBlazor.Docs.Models; 5 | using System; 6 | using Xunit; 7 | 8 | namespace SvgBlazor.Docs.Tests 9 | { 10 | public class DummyClass 11 | { 12 | public int DummyProperty { get; set; } 13 | 14 | public void DummyMethod() 15 | { 16 | } 17 | 18 | public void DummyMethodWithParameters(float width, float height) 19 | { 20 | } 21 | } 22 | 23 | public class ReflectionTypesExtensionsTest 24 | { 25 | const string dummyXml = "" + 26 | "" + 27 | "SvgBlazor" + 28 | "" + 29 | " " + 30 | " Type summary." + 31 | " " + 32 | " " + 33 | " Property summary." + 34 | " " + 35 | " " + 36 | " Method summary." + 37 | " " + 38 | " " + 39 | " Method with parameters summary." + 40 | " " + 41 | "" + 42 | ""; 43 | 44 | [Fact] 45 | public void ReturnsTypeSummary() 46 | { 47 | var xmlDoc = new XmlDoc(dummyXml); 48 | Assert.Equal("Type summary.", 49 | xmlDoc.GetDocumentation(typeof(DummyClass))); 50 | } 51 | 52 | [Fact] 53 | public void ReturnsPropertySummary() 54 | { 55 | var xmlDoc = new XmlDoc(dummyXml); 56 | var dummyClassType = typeof(DummyClass); 57 | Assert.Equal("Property summary.", 58 | xmlDoc.GetDocumentation(dummyClassType.GetProperty("DummyProperty"))); 59 | } 60 | 61 | [Fact] 62 | public void ReturnsMethodSummary() 63 | { 64 | var xmlDoc = new XmlDoc(dummyXml); 65 | var dummyClassType = typeof(DummyClass); 66 | Assert.Equal("Method summary.", 67 | xmlDoc.GetDocumentation(dummyClassType.GetMethod("DummyMethod"))); 68 | } 69 | 70 | [Fact] 71 | public void ReturnsMethodWithParameteresSummary() 72 | { 73 | var xmlDoc = new XmlDoc(dummyXml); 74 | var dummyClassType = typeof(DummyClass); 75 | Assert.Equal("Method with parameters summary.", 76 | xmlDoc.GetDocumentation(dummyClassType.GetMethod("DummyMethodWithParameters"))); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/SvgBlazor/Interfaces/ISvgElement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using Microsoft.AspNetCore.Components; 5 | using Microsoft.AspNetCore.Components.Rendering; 6 | using Microsoft.AspNetCore.Components.Web; 7 | 8 | namespace SvgBlazor.Interfaces 9 | { 10 | /// 11 | /// The interface that represents the SvgElement. 12 | /// 13 | public interface ISvgElement : ISvgEventHandler 14 | { 15 | /// 16 | /// Gets or sets the x position of the element. 17 | /// 18 | SvgValue X { get; set; } 19 | 20 | /// 21 | /// Gets or sets the y position of the element. 22 | /// 23 | SvgValue Y { get; set; } 24 | 25 | /// 26 | /// Gets or sets the reference to a rendered element. 27 | /// 28 | ElementReference ElementReference { get; set; } 29 | 30 | /// 31 | /// Provides the tag to be used when rendering this element. 32 | /// 33 | /// The tag of the element. 34 | string Tag(); 35 | 36 | /// 37 | /// Builds the element based on the given RenderTreeBuilder object. 38 | /// 39 | /// RenderTreeBuilder object to be used during the build process. 40 | void BuildElement(RenderTreeBuilder builder); 41 | 42 | /// 43 | /// Allows to perform additional steps when building this element. The method is called just after adding attributes and before reference capture. 44 | /// 45 | /// RenderTreeBuilder object to be used during the build process. 46 | void BuildElementAdditionalSteps(RenderTreeBuilder builder); 47 | 48 | /// 49 | /// Sets the given element as the parent of this element. 50 | /// 51 | /// The element that will become the parent of this element. 52 | void SetParent(ISvgElement parent); 53 | 54 | /// 55 | /// Returns the parent element of this element. 56 | /// 57 | /// The parent element. 58 | ISvgElement Parent(); 59 | 60 | /// 61 | /// Refreshes the element. 62 | /// 63 | void Refresh(); 64 | 65 | /// 66 | /// Called when the mouse cursor moves over the element. 67 | /// 68 | /// Element sending the event. 69 | /// MouseEventArgs associated with the event. 70 | void ElementMouseOver(ISvgElement element, MouseEventArgs args); 71 | 72 | /// 73 | /// Called when the mouse cursor moves outside the element. 74 | /// 75 | /// Element sending the event. 76 | /// MouseEventArgs associated with the event. 77 | void ElementMouseOut(ISvgElement element, MouseEventArgs args); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/SvgBlazor/Interfaces/ISvgEventHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Components; 6 | using Microsoft.AspNetCore.Components.Web; 7 | 8 | namespace SvgBlazor.Interfaces 9 | { 10 | /// 11 | /// Adds event handling. 12 | /// 13 | public interface ISvgEventHandler 14 | { 15 | /// 16 | /// Gets or sets the OnClick event callback. 17 | /// 18 | EventCallback OnClick { get; set; } 19 | 20 | /// 21 | /// Gets or sets the OnMouseDown event callback. 22 | /// 23 | EventCallback OnMouseDown { get; set; } 24 | 25 | /// 26 | /// Gets or sets the OnMouseMove event callback. 27 | /// 28 | EventCallback OnMouseMove { get; set; } 29 | 30 | /// 31 | /// Gets or sets the OnMouseUp event callback. 32 | /// 33 | EventCallback OnMouseUp { get; set; } 34 | 35 | /// 36 | /// Gets or sets the OnMouseOver event callback. 37 | /// 38 | EventCallback OnMouseOver { get; set; } 39 | 40 | /// 41 | /// Gets or sets the OnMouseOut event callback. 42 | /// 43 | EventCallback OnMouseOut { get; set; } 44 | 45 | /// 46 | /// Handles the OnClick event. 47 | /// 48 | /// The MouseEventArgs. 49 | /// Result of the asynchronous operation. 50 | Task OnClickHandler(MouseEventArgs args); 51 | 52 | /// 53 | /// Handles the OnMouseDown event. 54 | /// 55 | /// The MouseEventArgs. 56 | /// Result of the asynchronous operation. 57 | Task OnMouseDownHandler(MouseEventArgs args); 58 | 59 | /// 60 | /// Handles the OnMouseMove event. 61 | /// 62 | /// The MouseEventArgs. 63 | /// Result of the asynchronous operation. 64 | Task OnMouseMoveHandler(MouseEventArgs args); 65 | 66 | /// 67 | /// Handles the OnMouseUp event. 68 | /// 69 | /// The MouseEventArgs. 70 | /// Result of the asynchronous operation. 71 | Task OnMouseUpHandler(MouseEventArgs args); 72 | 73 | /// 74 | /// Handles the OnMouseOver event. 75 | /// 76 | /// The MouseEventArgs. 77 | /// Result of the asynchronous operation. 78 | Task OnMouseOverHandler(MouseEventArgs args); 79 | 80 | /// 81 | /// Handles the OnMouseOut event. 82 | /// 83 | /// The MouseEventArgs. 84 | /// Result of the asynchronous operation. 85 | Task OnMouseOutHandler(MouseEventArgs args); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Docs.Generator.Tests/CodeFromExampleTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.IO; 5 | using System.Text; 6 | using Xunit; 7 | 8 | namespace SvgBlazor.Docs.Generator.Tests 9 | { 10 | public class CodeFromExampleTest 11 | { 12 | [Fact] 13 | public void ReturnsExampleCodeFromFullCode() 14 | { 15 | const string exampleCode = 16 | @"using System; 17 | using SvgBlazor.Docs.Interfaces; 18 | 19 | namespace SvgBlazor.Docs.Examples 20 | { 21 | public class CircleExample: IExampleCode 22 | { 23 | //#example-code-start 24 | public void Example(SvgComponent svg) 25 | { 26 | var circle = new SvgCircle() 27 | { 28 | CenterX = 100, 29 | Fill = new SvgFill { Color = ""blue"", Opacity = 0.5f }, 30 | }; 31 | 32 | svg.Add(circle); 33 | } 34 | //#example-code-end 35 | } 36 | }"; 37 | ExamplesCode ec = new (); 38 | using var stream = GenerateStreamFromString(exampleCode); 39 | string code = ec.GetCodeFromStream(new StreamReader(stream)); 40 | const string expectedCode = 41 | @"public void Example(SvgComponent svg) 42 | { 43 | var circle = new SvgCircle() 44 | { 45 | CenterX = 100, 46 | Fill = new SvgFill { Color = ""blue"", Opacity = 0.5f }, 47 | }; 48 | 49 | svg.Add(circle); 50 | }"; 51 | Assert.Equal(expectedCode, code); 52 | } 53 | 54 | [Fact] 55 | public void ReturnsExampleCodeWithTwoExamples() 56 | { 57 | const string exampleCode = 58 | @"using System; 59 | using SvgBlazor.Docs.Interfaces; 60 | 61 | namespace SvgBlazor.Docs.Examples 62 | { 63 | public class CircleExample: IExampleCode 64 | { 65 | //#example-code-start 66 | public void Example(SvgComponent svg) 67 | //#example-code-end 68 | { 69 | var circle = new SvgCircle() 70 | { 71 | //#example-code-start 72 | CenterX = 100, 73 | Fill = new SvgFill { Color = ""blue"", Opacity = 0.5f }, 74 | //#example-code-end 75 | }; 76 | svg.Add(circle); 77 | } 78 | 79 | } 80 | }"; 81 | ExamplesCode ec = new (); 82 | using var stream = GenerateStreamFromString(exampleCode); 83 | string code = ec.GetCodeFromStream(new StreamReader(stream)); 84 | string expectedCode = 85 | @"public void Example(SvgComponent svg) 86 | 87 | ... 88 | 89 | CenterX = 100, 90 | Fill = new SvgFill { Color = ""blue"", Opacity = 0.5f },"; 91 | Assert.Equal(expectedCode, code); 92 | } 93 | 94 | [Fact] 95 | public void ReturnsAllCodeWhenNoCompleteTagsFound() 96 | { 97 | const string exampleCode = @"TestLine1\r\n{\r\n//#example-code-start\r\nvoid Test()\r\n{\r\n}\r\n}"; 98 | using var stream = GenerateStreamFromString(exampleCode); 99 | ExamplesCode ec = new (); 100 | string code = ec.GetCodeFromStream(new StreamReader(stream)); 101 | Assert.Equal(exampleCode, code); 102 | } 103 | 104 | private static MemoryStream GenerateStreamFromString(string value) 105 | { 106 | return new MemoryStream(Encoding.UTF8.GetBytes(value ?? string.Empty)); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgPolygon.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Drawing; 7 | using System.Globalization; 8 | using System.Linq; 9 | using System.Text; 10 | using Microsoft.AspNetCore.Components; 11 | using Microsoft.AspNetCore.Components.Rendering; 12 | 13 | namespace SvgBlazor 14 | { 15 | /// 16 | /// The SvgPolygon class is responsible for providing the SVG polygon element. 17 | /// 18 | public class SvgPolygon : SvgElement 19 | { 20 | private readonly NumberFormatInfo _numberFormatInfo = new () { NumberDecimalSeparator = "." }; 21 | 22 | private List _points = new (); 23 | 24 | private string _pointsString; 25 | 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// 29 | public SvgPolygon() 30 | { 31 | } 32 | 33 | /// 34 | /// Initializes a new instance of the class with provided SvgPolygon. 35 | /// 36 | /// Initial SvgPolygon. 37 | public SvgPolygon(SvgPolygon svgpolygon) 38 | : base(svgpolygon) 39 | { 40 | _points = new List(svgpolygon._points); 41 | _pointsString = svgpolygon._pointsString; 42 | } 43 | 44 | /// 45 | /// Gets or sets the points of the polygon. 46 | /// 47 | public IEnumerable Points 48 | { 49 | get => _points; 50 | set 51 | { 52 | _points = value.ToList(); 53 | 54 | PointsToString(); 55 | } 56 | } 57 | 58 | /// 59 | public override string Tag() => "polygon"; 60 | 61 | /// 62 | public override void AddAttributes(RenderTreeBuilder builder) 63 | { 64 | base.AddAttributes(builder); 65 | builder.AddAttribute(0, "points", _pointsString); 66 | } 67 | 68 | /// 69 | /// Adds a point to the path. 70 | /// 71 | /// A point to add. 72 | public virtual void AddPoint(PointF point) 73 | { 74 | _points.Add(point); 75 | PointsToString(); 76 | } 77 | 78 | /// 79 | /// Removes all points from the path. 80 | /// 81 | public virtual void ClearPoints() 82 | { 83 | _points.Clear(); 84 | PointsToString(); 85 | } 86 | 87 | private void PointsToString() 88 | { 89 | const int charactersPerPoint = 10; 90 | var sb = new StringBuilder(_points.Count * charactersPerPoint); 91 | 92 | for (int i = 0; i < _points.Count; i++) 93 | { 94 | if (i > 0) 95 | { 96 | sb.Append(' '); 97 | } 98 | 99 | var point = _points[i]; 100 | sb.Append(point.X.ToString(_numberFormatInfo)); 101 | sb.Append(' '); 102 | sb.Append(point.Y.ToString(_numberFormatInfo)); 103 | } 104 | 105 | _pointsString = sb.ToString(); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/Svg.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Drawing; 7 | using Microsoft.AspNetCore.Components; 8 | using Microsoft.AspNetCore.Components.Rendering; 9 | using Microsoft.AspNetCore.Components.Web; 10 | using SvgBlazor.Interfaces; 11 | 12 | namespace SvgBlazor 13 | { 14 | /// 15 | /// The root element for SVG drawings. 16 | /// 17 | public class Svg : SvgContainer 18 | { 19 | /// 20 | /// Initializes a new instance of the class. 21 | /// 22 | public Svg() 23 | { 24 | } 25 | 26 | /// 27 | /// Initializes a new instance of the class with provided Svg element. 28 | /// 29 | /// Initial Svg element. 30 | public Svg(Svg svg) 31 | : base(svg) 32 | { 33 | Width = svg.Width; 34 | Height = svg.Height; 35 | ViewBoxWidth = svg.ViewBoxWidth; 36 | ViewBoxHeight = svg.ViewBoxHeight; 37 | } 38 | 39 | /// 40 | /// Gets or sets the width of the svg element. Optional. 41 | /// 42 | public float? Width { get; set; } 43 | 44 | /// 45 | /// Gets or sets the height of the svg element. Optional. 46 | /// 47 | public float? Height { get; set; } 48 | 49 | /// 50 | /// Gets or sets the optional width of the viewbox. If not set, the 'Width' value will be used. 51 | /// 52 | public float? ViewBoxWidth { get; set; } 53 | 54 | /// 55 | /// Gets or sets the optional height of the viewbox. If not set, the 'Height' value will be used. 56 | /// 57 | public float? ViewBoxHeight { get; set; } 58 | 59 | /// 60 | public override string Tag() => "svg"; 61 | 62 | /// 63 | public override void AddAttributes(RenderTreeBuilder builder) 64 | { 65 | base.AddAttributes(builder); 66 | builder.AddAttribute(1, "viewBox", string.Format("0 0 {0} {1}", ViewBoxWidth ?? Width ?? 0, ViewBoxHeight ?? Height ?? 0)); 67 | 68 | if (Width is not null) 69 | { 70 | builder.AddAttribute(2, "width", Width); 71 | } 72 | 73 | if (Height is not null) 74 | { 75 | builder.AddAttribute(3, "height", Height); 76 | } 77 | } 78 | 79 | /// 80 | /// Sets the size of the viewbox and redraws the svg. 81 | /// 82 | /// Width of the viewbox. 83 | /// Height of the viewbox. 84 | public void SetViewBox(float width, float height) 85 | { 86 | ViewBoxWidth = width; 87 | ViewBoxHeight = height; 88 | } 89 | 90 | /// 91 | /// Sets the size of the viewport and redraws the svg. 92 | /// 93 | /// Width of the viewport. 94 | /// Height of the viewport. 95 | public void SetSize(float width, float height) 96 | { 97 | Width = width; 98 | Height = height; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/SvgBlazor/Attributes/SvgStroke.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using Microsoft.AspNetCore.Components.Rendering; 6 | using SvgBlazor.Extensions; 7 | using SvgBlazor.Interfaces; 8 | 9 | namespace SvgBlazor 10 | { 11 | /// 12 | /// The SvgStroke class is responsible for providing the paint of the outline of an svg element. 13 | /// 14 | public class SvgStroke : ISvgAttribute 15 | { 16 | /// 17 | /// Initializes a new instance of the class. 18 | /// 19 | public SvgStroke() 20 | { 21 | } 22 | 23 | /// 24 | /// Initializes a new instance of the class with provided stroke. 25 | /// 26 | /// Initial SVG stroke. 27 | public SvgStroke(SvgStroke svgstroke) 28 | { 29 | Color = svgstroke.Color; 30 | DashArray = svgstroke.DashArray; 31 | DashOffset = svgstroke.DashOffset; 32 | LineCap = svgstroke.LineCap; 33 | LineJoin = svgstroke.LineJoin; 34 | MiterLimit = svgstroke.MiterLimit; 35 | Opacity = svgstroke.Opacity; 36 | Width = svgstroke.Width; 37 | } 38 | 39 | /// 40 | /// Gets or sets the appearance of the Stroke. Can be color, pattern or gradient (e.g. url(#pattern)). 41 | /// 42 | public string Color { get; set; } 43 | 44 | /// 45 | /// Gets or sets the stroke dash array. To present stroke as a pattern of dashes and gaps, assign properly formatted string. 46 | /// 47 | public string DashArray { get; set; } 48 | 49 | /// 50 | /// Gets or sets the dash offset. To render offset, assign value to DashOffset property. However, this will only work if a DashArray is assigned. 51 | /// 52 | public SvgValue DashOffset { get; set; } 53 | 54 | /// 55 | /// Gets or sets the style of the stroke at the start and end of an open subpath. 56 | /// 57 | public StrokeLineCapStyle? LineCap { get; set; } 58 | 59 | /// 60 | /// Gets or sets the shape definition at the join point of two lines. 61 | /// 62 | public StrokeLineJoinStyle? LineJoin { get; set; } 63 | 64 | /// 65 | /// Gets or sets the miter limit. Must be greater then or equal to 1. 66 | /// 67 | public int? MiterLimit { get; set; } 68 | 69 | /// 70 | /// Gets or sets the opacity of the stroke. 71 | /// 72 | public SvgValue Opacity { get; set; } 73 | 74 | /// 75 | /// Gets or sets the width of the stroke. 76 | /// 77 | public SvgValue Width { get; set; } 78 | 79 | /// 80 | public void RenderAttributes(RenderTreeBuilder builder) 81 | { 82 | builder.AddAttribute(0, "stroke", Color); 83 | builder.AddAttribute(1, "stroke-dasharray", DashArray); 84 | builder.AddAttribute(2, "stroke-dashoffset", DashOffset); 85 | builder.AddAttribute(3, "stroke-linecap", LineCap?.ToDescriptionString()); 86 | builder.AddAttribute(4, "stroke-linejoin", LineJoin?.ToDescriptionString()); 87 | builder.AddAttribute(5, "stroke-miterlimit", MiterLimit); 88 | builder.AddAttribute(6, "stroke-opacity", Opacity); 89 | builder.AddAttribute(7, "stroke-width", Width); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 | 7 | 8 |
9 | 99 |
100 | 101 | @code { 102 | private bool collapseNavMenu = true; 103 | 104 | private string NavMenuCssClass => collapseNavMenu ? "collapse" : null; 105 | 106 | private void ToggleNavMenu() 107 | { 108 | collapseNavMenu = !collapseNavMenu; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/img/svgblazor_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 15 | 24 | 26 | 30 | 34 | 35 | 36 | 38 | 46 | 50 | 54 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /SvgBlazor.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.810.3 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgBlazor", "src\SvgBlazor\SvgBlazor.csproj", "{2FEF4A96-A24F-47BB-894A-D2A6ACD15E2F}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgBlazor.Docs", "src\SvgBlazor.Docs\SvgBlazor.Docs.csproj", "{7D78592B-3B9F-49A4-AAE8-C01879273534}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {FFA512DA-CAC8-4344-9211-751A52C467D5} = {FFA512DA-CAC8-4344-9211-751A52C467D5} 11 | EndProjectSection 12 | EndProject 13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgBlazor.Tests", "tests\SvgBlazor.Tests\SvgBlazor.Tests.csproj", "{9DDD57DA-9F0B-4FFA-9E8C-8E3A8DDF99DE}" 14 | EndProject 15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgBlazor.Docs.Generator", "src\SvgBlazor.Docs.Generator\SvgBlazor.Docs.Generator.csproj", "{FFA512DA-CAC8-4344-9211-751A52C467D5}" 16 | EndProject 17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SvgBlazor.Docs.Generator.Tests", "tests\SvgBlazor.Docs.Generator.Tests\SvgBlazor.Docs.Generator.Tests.csproj", "{8F5DD64E-0CF6-430E-9DDE-BF980D3A5F9C}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SvgBlazor.Docs.Tests", "tests\SvgBlazor.Docs.Tests\SvgBlazor.Docs.Tests.csproj", "{65916D13-3A6F-467C-A84F-93468DA1BAB7}" 20 | EndProject 21 | Global 22 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 23 | Debug|Any CPU = Debug|Any CPU 24 | Release|Any CPU = Release|Any CPU 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {2FEF4A96-A24F-47BB-894A-D2A6ACD15E2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {2FEF4A96-A24F-47BB-894A-D2A6ACD15E2F}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {2FEF4A96-A24F-47BB-894A-D2A6ACD15E2F}.Release|Any CPU.ActiveCfg = Release|Any CPU 30 | {2FEF4A96-A24F-47BB-894A-D2A6ACD15E2F}.Release|Any CPU.Build.0 = Release|Any CPU 31 | {7D78592B-3B9F-49A4-AAE8-C01879273534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {7D78592B-3B9F-49A4-AAE8-C01879273534}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {7D78592B-3B9F-49A4-AAE8-C01879273534}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {7D78592B-3B9F-49A4-AAE8-C01879273534}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {9DDD57DA-9F0B-4FFA-9E8C-8E3A8DDF99DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {9DDD57DA-9F0B-4FFA-9E8C-8E3A8DDF99DE}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {9DDD57DA-9F0B-4FFA-9E8C-8E3A8DDF99DE}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {9DDD57DA-9F0B-4FFA-9E8C-8E3A8DDF99DE}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {FFA512DA-CAC8-4344-9211-751A52C467D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {FFA512DA-CAC8-4344-9211-751A52C467D5}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {FFA512DA-CAC8-4344-9211-751A52C467D5}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {FFA512DA-CAC8-4344-9211-751A52C467D5}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {8F5DD64E-0CF6-430E-9DDE-BF980D3A5F9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {8F5DD64E-0CF6-430E-9DDE-BF980D3A5F9C}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {8F5DD64E-0CF6-430E-9DDE-BF980D3A5F9C}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {8F5DD64E-0CF6-430E-9DDE-BF980D3A5F9C}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {65916D13-3A6F-467C-A84F-93468DA1BAB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {65916D13-3A6F-467C-A84F-93468DA1BAB7}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {65916D13-3A6F-467C-A84F-93468DA1BAB7}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {65916D13-3A6F-467C-A84F-93468DA1BAB7}.Release|Any CPU.Build.0 = Release|Any CPU 51 | EndGlobalSection 52 | GlobalSection(SolutionProperties) = preSolution 53 | HideSolutionNode = FALSE 54 | EndGlobalSection 55 | GlobalSection(ExtensibilityGlobals) = postSolution 56 | SolutionGuid = {314B00A4-A5F8-4CD0-9E8E-D35FFE123F7A} 57 | EndGlobalSection 58 | EndGlobal 59 | -------------------------------------------------------------------------------- /src/SvgBlazor/Elements/SvgText.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Drawing; 6 | using Microsoft.AspNetCore.Components; 7 | using Microsoft.AspNetCore.Components.Rendering; 8 | using SvgBlazor.Extensions; 9 | 10 | namespace SvgBlazor 11 | { 12 | /// 13 | /// The SvgText class is responsible for providing the SVG text element. 14 | /// 15 | public class SvgText : SvgElement 16 | { 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | public SvgText() 21 | { 22 | } 23 | 24 | /// 25 | /// Initializes a new instance of the class with provided SvgText. 26 | /// 27 | /// Initial SvgText. 28 | public SvgText(SvgText svgtext) 29 | : base(svgtext) 30 | { 31 | Text = svgtext.Text; 32 | ShiftX = svgtext.ShiftX; 33 | ShiftY = svgtext.ShiftY; 34 | Rotate = svgtext.Rotate; 35 | LengthAdjust = svgtext.LengthAdjust; 36 | TextLength = svgtext.TextLength; 37 | } 38 | 39 | /// 40 | /// Gets or sets the content. 41 | /// 42 | public string Text { get; set; } 43 | 44 | /// 45 | /// Gets or sets x-axis shift from the `X` coordinate. 46 | /// 47 | public SvgValue ShiftX { get; set; } 48 | 49 | /// 50 | /// Gets or sets y-axis shift from the `Y` coordinate. 51 | /// 52 | public SvgValue ShiftY { get; set; } 53 | 54 | /// 55 | /// Gets or sets rotation of each glyph. 56 | /// 57 | public string Rotate { get; set; } 58 | 59 | /// 60 | /// Gets or sets how the text should fit the length set in `TextLength` attribute. 61 | /// 62 | public TextLengthAdjust? LengthAdjust { get; set; } 63 | 64 | /// 65 | /// Gets or sets width that the text should be scaled to fit. 66 | /// 67 | public SvgValue TextLength { get; set; } 68 | 69 | /// 70 | /// Gets or sets the anchor of the text. 71 | /// 72 | public TextAnchor? TextAnchor { get; set; } 73 | 74 | /// 75 | /// Gets or sets the dominant baseline of the text. 76 | /// 77 | public TextDominantBaseline? DominantBaseline { get; set; } 78 | 79 | /// 80 | public override string Tag() => "text"; 81 | 82 | /// 83 | public override void AddAttributes(RenderTreeBuilder builder) 84 | { 85 | base.AddAttributes(builder); 86 | builder.AddAttribute(0, "x", X); 87 | builder.AddAttribute(1, "y", Y); 88 | builder.AddAttribute(2, "dx", ShiftX); 89 | builder.AddAttribute(3, "dy", ShiftY); 90 | builder.AddAttribute(4, "rotate", Rotate); 91 | builder.AddAttribute(5, "textLength", TextLength); 92 | 93 | if (LengthAdjust is not null) 94 | { 95 | builder.AddAttribute(6, "lengthAdjust", LengthAdjust.ToDescriptionString()); 96 | } 97 | 98 | if (TextAnchor is not null) 99 | { 100 | builder.AddAttribute(7, "text-anchor", TextAnchor.ToDescriptionString()); 101 | } 102 | 103 | if (DominantBaseline is not null) 104 | { 105 | builder.AddAttribute(8, "dominant-baseline", DominantBaseline.ToDescriptionString()); 106 | } 107 | 108 | builder.AddContent(9, Text); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/open-iconic/README.md: -------------------------------------------------------------------------------- 1 | [Open Iconic v1.1.1](http://useiconic.com/open) 2 | =========== 3 | 4 | ### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) 5 | 6 | 7 | 8 | ## What's in Open Iconic? 9 | 10 | * 223 icons designed to be legible down to 8 pixels 11 | * Super-light SVG files - 61.8 for the entire set 12 | * SVG sprite—the modern replacement for icon fonts 13 | * Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats 14 | * Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats 15 | * PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. 16 | 17 | 18 | ## Getting Started 19 | 20 | #### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. 21 | 22 | ### General Usage 23 | 24 | #### Using Open Iconic's SVGs 25 | 26 | We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). 27 | 28 | ``` 29 | icon name 30 | ``` 31 | 32 | #### Using Open Iconic's SVG Sprite 33 | 34 | Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. 35 | 36 | Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `` *tag and a unique class name for each different icon in the* `` *tag.* 37 | 38 | ``` 39 | 40 | 41 | 42 | ``` 43 | 44 | Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `` tag with equal width and height dimensions. 45 | 46 | ``` 47 | .icon { 48 | width: 16px; 49 | height: 16px; 50 | } 51 | ``` 52 | 53 | Coloring icons is even easier. All you need to do is set the `fill` rule on the `` tag. 54 | 55 | ``` 56 | .icon-account-login { 57 | fill: #f00; 58 | } 59 | ``` 60 | 61 | To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). 62 | 63 | #### Using Open Iconic's Icon Font... 64 | 65 | 66 | ##### …with Bootstrap 67 | 68 | You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` 69 | 70 | 71 | ``` 72 | 73 | ``` 74 | 75 | 76 | ``` 77 | 78 | ``` 79 | 80 | ##### …with Foundation 81 | 82 | You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` 83 | 84 | ``` 85 | 86 | ``` 87 | 88 | 89 | ``` 90 | 91 | ``` 92 | 93 | ##### …on its own 94 | 95 | You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` 96 | 97 | ``` 98 | 99 | ``` 100 | 101 | ``` 102 | 103 | ``` 104 | 105 | 106 | ## License 107 | 108 | ### Icons 109 | 110 | All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). 111 | 112 | ### Fonts 113 | 114 | All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). 115 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/js/csharp.min.js: -------------------------------------------------------------------------------- 1 | /*! `csharp` grammar compiled for Highlight.js 11.3.1 */ 2 | (()=>{var e=(()=>{"use strict";return e=>{const n={ 3 | keyword:["abstract","as","base","break","case","catch","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value|0","var","when","where","with","yield"]), 4 | built_in:["bool","byte","char","decimal","delegate","double","dynamic","enum","float","int","long","nint","nuint","object","sbyte","short","string","ulong","uint","ushort"], 5 | literal:["default","false","null","true"]},a=e.inherit(e.TITLE_MODE,{ 6 | begin:"[a-zA-Z](\\.?\\w)*"}),i={className:"number",variants:[{ 7 | begin:"\\b(0b[01']+)"},{ 8 | begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{ 9 | begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" 10 | }],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}] 11 | },t=e.inherit(s,{illegal:/\n/}),r={className:"subst",begin:/\{/,end:/\}/, 12 | keywords:n},l=e.inherit(r,{illegal:/\n/}),c={className:"string",begin:/\$"/, 13 | end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/ 14 | },e.BACKSLASH_ESCAPE,l]},o={className:"string",begin:/\$@"/,end:'"',contains:[{ 15 | begin:/\{\{/},{begin:/\}\}/},{begin:'""'},r]},d=e.inherit(o,{illegal:/\n/, 16 | contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},l]}) 17 | ;r.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.C_BLOCK_COMMENT_MODE], 18 | l.contains=[d,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.inherit(e.C_BLOCK_COMMENT_MODE,{ 19 | illegal:/\n/})];const g={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] 20 | },E={begin:"<",end:">",contains:[{beginKeywords:"in out"},a] 21 | },_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={ 22 | begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"], 23 | keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0, 24 | contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{ 25 | begin:"\x3c!--|--\x3e"},{begin:""}]}] 26 | }),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#", 27 | end:"$",keywords:{ 28 | keyword:"if else elif endif define undef warning error line region endregion pragma checksum" 29 | }},g,i,{beginKeywords:"class interface",relevance:0,end:/[{;=]/, 30 | illegal:/[^\s:,]/,contains:[{beginKeywords:"where class" 31 | },a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace", 32 | relevance:0,end:/[{;=]/,illegal:/[^\s:]/, 33 | contains:[a,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ 34 | beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/, 35 | contains:[a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta", 36 | begin:"^\\s*\\[(?=[\\w])",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{ 37 | className:"string",begin:/"/,end:/"/}]},{ 38 | beginKeywords:"new return throw await else",relevance:0},{className:"function", 39 | begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0, 40 | end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{ 41 | beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial", 42 | relevance:0},{begin:e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0, 43 | contains:[e.TITLE_MODE,E],relevance:0},{match:/\(\)/},{className:"params", 44 | begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0, 45 | contains:[g,i,e.C_BLOCK_COMMENT_MODE] 46 | },e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}})() 47 | ;hljs.registerLanguage("csharp",e)})(); -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/wwwroot/css/open-iconic/FONT-LICENSE: -------------------------------------------------------------------------------- 1 | SIL OPEN FONT LICENSE Version 1.1 2 | 3 | Copyright (c) 2014 Waybury 4 | 5 | PREAMBLE 6 | The goals of the Open Font License (OFL) are to stimulate worldwide 7 | development of collaborative font projects, to support the font creation 8 | efforts of academic and linguistic communities, and to provide a free and 9 | open framework in which fonts may be shared and improved in partnership 10 | with others. 11 | 12 | The OFL allows the licensed fonts to be used, studied, modified and 13 | redistributed freely as long as they are not sold by themselves. The 14 | fonts, including any derivative works, can be bundled, embedded, 15 | redistributed and/or sold with any software provided that any reserved 16 | names are not used by derivative works. The fonts and derivatives, 17 | however, cannot be released under any other type of license. The 18 | requirement for fonts to remain under this license does not apply 19 | to any document created using the fonts or their derivatives. 20 | 21 | DEFINITIONS 22 | "Font Software" refers to the set of files released by the Copyright 23 | Holder(s) under this license and clearly marked as such. This may 24 | include source files, build scripts and documentation. 25 | 26 | "Reserved Font Name" refers to any names specified as such after the 27 | copyright statement(s). 28 | 29 | "Original Version" refers to the collection of Font Software components as 30 | distributed by the Copyright Holder(s). 31 | 32 | "Modified Version" refers to any derivative made by adding to, deleting, 33 | or substituting -- in part or in whole -- any of the components of the 34 | Original Version, by changing formats or by porting the Font Software to a 35 | new environment. 36 | 37 | "Author" refers to any designer, engineer, programmer, technical 38 | writer or other person who contributed to the Font Software. 39 | 40 | PERMISSION & CONDITIONS 41 | Permission is hereby granted, free of charge, to any person obtaining 42 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 43 | redistribute, and sell modified and unmodified copies of the Font 44 | Software, subject to the following conditions: 45 | 46 | 1) Neither the Font Software nor any of its individual components, 47 | in Original or Modified Versions, may be sold by itself. 48 | 49 | 2) Original or Modified Versions of the Font Software may be bundled, 50 | redistributed and/or sold with any software, provided that each copy 51 | contains the above copyright notice and this license. These can be 52 | included either as stand-alone text files, human-readable headers or 53 | in the appropriate machine-readable metadata fields within text or 54 | binary files as long as those fields can be easily viewed by the user. 55 | 56 | 3) No Modified Version of the Font Software may use the Reserved Font 57 | Name(s) unless explicit written permission is granted by the corresponding 58 | Copyright Holder. This restriction only applies to the primary font name as 59 | presented to the users. 60 | 61 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 62 | Software shall not be used to promote, endorse or advertise any 63 | Modified Version, except to acknowledge the contribution(s) of the 64 | Copyright Holder(s) and the Author(s) or with their explicit written 65 | permission. 66 | 67 | 5) The Font Software, modified or unmodified, in part or in whole, 68 | must be distributed entirely under this license, and must not be 69 | distributed under any other license. The requirement for fonts to 70 | remain under this license does not apply to any document created 71 | using the Font Software. 72 | 73 | TERMINATION 74 | This license becomes null and void if any of the above conditions are 75 | not met. 76 | 77 | DISCLAIMER 78 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 79 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 80 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 81 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 82 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 83 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 84 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 85 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 86 | OTHER DEALINGS IN THE FONT SOFTWARE. 87 | -------------------------------------------------------------------------------- /tests/SvgBlazor.Tests/Attributes/StrokeAttributeTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System.Drawing; 5 | using Microsoft.AspNetCore.Components.Rendering; 6 | using Xunit; 7 | using Bunit; 8 | using SvgBlazor.Interfaces; 9 | 10 | namespace SvgBlazor.Tests 11 | { 12 | public class StrokeAttributeTest : TestContextWithSvgBlazorJsModule 13 | { 14 | [Fact] 15 | public void RendersAttributes() 16 | { 17 | var comp = RenderComponent(); 18 | 19 | comp.InvokeAsync(() => comp.Instance.Add(new DummyStrokeAttributesElement 20 | { 21 | Stroke = new SvgStroke 22 | { 23 | Color = "red", 24 | DashArray = "1 2 3", 25 | DashOffset = 2, 26 | Opacity = 0.5f, 27 | MiterLimit = 5, 28 | Width = 15, 29 | }, 30 | })); 31 | 32 | comp.Render(); 33 | 34 | var element = comp.Find("elementwithstroke"); 35 | Assert.Contains("red", element.GetAttribute("stroke")); 36 | Assert.Contains("1 2 3", element.GetAttribute("stroke-dasharray")); 37 | Assert.Contains("2", element.GetAttribute("stroke-dashoffset")); 38 | Assert.Contains("0.5", element.GetAttribute("stroke-opacity")); 39 | Assert.Contains("5", element.GetAttribute("stroke-miterlimit")); 40 | Assert.Contains("15", element.GetAttribute("stroke-width")); 41 | } 42 | 43 | [Theory] 44 | [InlineData(StrokeLineCapStyle.Butt, "butt")] 45 | [InlineData(StrokeLineCapStyle.Round, "round")] 46 | [InlineData(StrokeLineCapStyle.Square, "square")] 47 | public void RendersWithLineCapAttribute(StrokeLineCapStyle lineCapStyle, string attributeValue) 48 | { 49 | var comp = RenderComponent(); 50 | 51 | comp.InvokeAsync(() => comp.Instance.Add(new DummyStrokeAttributesElement 52 | { 53 | Stroke = new SvgStroke 54 | { 55 | LineCap = lineCapStyle, 56 | }, 57 | })); 58 | 59 | comp.Render(); 60 | 61 | var element = comp.Find("elementwithstroke"); 62 | Assert.Contains(attributeValue, element.GetAttribute("stroke-linecap")); 63 | } 64 | 65 | [Theory] 66 | [InlineData(StrokeLineJoinStyle.Arcs, "arcs")] 67 | [InlineData(StrokeLineJoinStyle.Round, "round")] 68 | [InlineData(StrokeLineJoinStyle.Bevel, "bevel")] 69 | [InlineData(StrokeLineJoinStyle.Miter, "miter")] 70 | [InlineData(StrokeLineJoinStyle.MiterClip, "miter-clip")] 71 | public void RendersWithLineJoinAttribute(StrokeLineJoinStyle lineJoinStyle, string attributeValue) 72 | { 73 | var comp = RenderComponent(); 74 | 75 | comp.InvokeAsync(() => comp.Instance.Add(new DummyStrokeAttributesElement 76 | { 77 | Stroke = new SvgStroke 78 | { 79 | LineJoin = lineJoinStyle, 80 | }, 81 | })); 82 | 83 | comp.Render(); 84 | 85 | var element = comp.Find("elementwithstroke"); 86 | Assert.Contains(attributeValue, element.GetAttribute("stroke-linejoin")); 87 | } 88 | 89 | [Fact] 90 | public void CopyConstructor() 91 | { 92 | var e1 = new SvgStroke() 93 | { 94 | Color = "red", 95 | DashArray = "1 2 3", 96 | DashOffset = 2, 97 | Opacity = 0.5f, 98 | MiterLimit = 5, 99 | Width = 15f, 100 | }; 101 | 102 | var e2 = new SvgStroke(e1); 103 | 104 | Assert.Equal("red", e2.Color); 105 | Assert.Equal("1 2 3", e2.DashArray); 106 | Assert.Equal(2f, e2.DashOffset.ToFloat()); 107 | Assert.Equal(0.5f, e2.Opacity.ToFloat()); 108 | Assert.Equal(5, e2.MiterLimit); 109 | Assert.Equal(15f, e2.Width.ToFloat()); 110 | } 111 | 112 | private class DummyStrokeAttributesElement : SvgElement 113 | { 114 | public override string Tag() => "elementwithstroke"; 115 | } 116 | } 117 | } -------------------------------------------------------------------------------- /src/SvgBlazor.Docs.Generator/ExamplesCode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Text.RegularExpressions; 9 | using System.Web; 10 | 11 | namespace SvgBlazor.Docs.Generator 12 | { 13 | public class ExamplesCode 14 | { 15 | public void Generate() 16 | { 17 | GenerateItems(ProjectPaths.PagesDirectoryPath); 18 | } 19 | 20 | public string GetCodeFromFile(string filepath) 21 | { 22 | using (StreamReader sr = new (filepath)) 23 | { 24 | return GetCodeFromStream(sr); 25 | } 26 | } 27 | 28 | public string GetCodeFromStream(StreamReader sr) 29 | { 30 | var allCode = sr.ReadToEnd(); 31 | 32 | MatchCollection matches = Regex.Matches(allCode, @"(#example-code-start.*?\n)([\s\S]*?)(.*?#example-code-end)"); 33 | 34 | if (matches.Count == 0) 35 | { 36 | return allCode; 37 | } 38 | 39 | StringBuilder sb = new (); 40 | 41 | for (int i = 0; i < matches.Count; i++) 42 | { 43 | if (i > 0) 44 | { 45 | AddCodesSeparator(sb); 46 | } 47 | 48 | if (matches[i].Groups.Count < 2) 49 | { 50 | break; 51 | } 52 | 53 | var exampleCode = matches[i].Groups[2].Value; 54 | 55 | sb.Append(CorrectIndentations(exampleCode)); 56 | } 57 | 58 | return sb.ToString(); 59 | } 60 | 61 | private void AddCodesSeparator(StringBuilder sb) 62 | { 63 | sb.AppendLine(); 64 | sb.AppendLine(); 65 | sb.AppendLine("..."); 66 | sb.AppendLine(); 67 | } 68 | 69 | private void GenerateItems(string path) 70 | { 71 | var directoryInfo = new DirectoryInfo(path); 72 | 73 | foreach (var entry in directoryInfo.GetDirectories()) 74 | { 75 | GenerateItem(entry); 76 | } 77 | } 78 | 79 | private void GenerateItem(DirectoryInfo itemDirectory) 80 | { 81 | var files = itemDirectory.EnumerateFiles("*.*", SearchOption.AllDirectories) 82 | .Where(s => 83 | (s.Name.EndsWith(".cs") || s.Name.EndsWith(".razor")) 84 | && s.DirectoryName.Contains(ProjectPaths.ExampleIdentifier)); 85 | 86 | foreach (var itemExample in files) 87 | { 88 | string code = GetCodeFromFile(itemExample.FullName); 89 | var outputPath = itemExample.FullName.Replace(itemExample.Extension, ".html"); 90 | SaveAsHtml(code, outputPath, itemExample.Extension); 91 | } 92 | } 93 | 94 | private void SaveAsHtml(string code, string outputPath, string extension) 95 | { 96 | var codeClass = extension switch 97 | { 98 | ".cs" => "language-csharp", 99 | ".razor" => "language-cshtml-razor", 100 | _ => throw new Exception("File extension not supported") 101 | }; 102 | 103 | var encodedCode = HttpUtility.HtmlEncode(code); 104 | var result = $"{encodedCode}"; 105 | File.WriteAllText(outputPath, result); 106 | } 107 | 108 | private string CorrectIndentations(string code) 109 | { 110 | string[] lines = code.Split( 111 | new string[] { "\r\n", "\r", "\n" }, 112 | StringSplitOptions.None); 113 | 114 | int indentChars = lines[0].TakeWhile(c => char.IsWhiteSpace(c)).Count(); 115 | 116 | if (indentChars == -1) 117 | { 118 | return code; 119 | } 120 | 121 | StringBuilder exampleCode = new (); 122 | foreach (var line in lines) 123 | { 124 | int charsToRemove = Math.Min(indentChars, line.Length); 125 | exampleCode.AppendLine(line.Remove(0, charsToRemove)); 126 | } 127 | 128 | return exampleCode.ToString().Trim(); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/SvgBlazor.Docs/Extractors/ElementApiExtractor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Approxoft. All rights reserved. 2 | // Licensed under the MIT License. See LICENSE in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using SvgBlazor.Docs.Models; 9 | 10 | namespace SvgBlazor.Docs.Extractors 11 | { 12 | public class ElementApiExtractor 13 | { 14 | private static readonly List SignaturesToFilterOut = new List 15 | { 16 | "GetType()", 17 | "ToString()", 18 | "Equals(System.Object)", 19 | "Equals(System.Object,System.Object)", 20 | "ReferenceEquals(System.Object,System.Object)", 21 | "GetHashCode()", 22 | }; 23 | 24 | private readonly XmlDoc _xmlDoc; 25 | 26 | public ElementApiExtractor(XmlDoc xmlDoc) => _xmlDoc = xmlDoc; 27 | 28 | public IEnumerable ExtractApiMethods(Type type) 29 | { 30 | var dict = new Dictionary(); 31 | 32 | Get(dict, type, t => 33 | { 34 | foreach (var methodInfo in t.GetMethods( 35 | BindingFlags.Instance | 36 | BindingFlags.Static | 37 | BindingFlags.Public).Where(m => !m.IsSpecialName)) 38 | { 39 | var signature = _xmlDoc.GetSignature(methodInfo); 40 | if (SignaturesToFilterOut.Contains(signature)) 41 | { 42 | continue; 43 | } 44 | 45 | var element = GetElementApiMethod(methodInfo); 46 | 47 | AddOrReplaceEntry(signature, dict, element); 48 | } 49 | }); 50 | 51 | return dict.Select(p => p.Value); 52 | } 53 | 54 | public IEnumerable ExtractApiProperties(Type type) 55 | { 56 | var dict = new Dictionary(); 57 | 58 | Get(dict, type, t => 59 | { 60 | foreach (var propertyInfo in t.GetProperties( 61 | BindingFlags.Instance | 62 | BindingFlags.Static | 63 | BindingFlags.Public)) 64 | { 65 | var name = propertyInfo.Name; 66 | var element = GetElementApiProperty(propertyInfo); 67 | 68 | AddOrReplaceEntry(name, dict, element); 69 | } 70 | }); 71 | 72 | return dict.Select(p => p.Value); 73 | } 74 | 75 | private static void Get(Dictionary dict, Type type, Action action) 76 | where T : IElementApiElement 77 | { 78 | foreach (var e in type.GetInterfaces()) 79 | { 80 | Get(dict, e, action); 81 | } 82 | 83 | if (type.BaseType is not null) 84 | { 85 | Get(dict, type.BaseType, action); 86 | } 87 | 88 | action?.Invoke(type); 89 | } 90 | 91 | private static void AddOrReplaceEntry( 92 | string key, 93 | Dictionary dictionary, 94 | T element) 95 | where T : IElementApiElement 96 | { 97 | if ((dictionary.ContainsKey(key) && !string.IsNullOrWhiteSpace(element.Description)) || 98 | !dictionary.ContainsKey(key)) 99 | { 100 | dictionary[key] = element; 101 | } 102 | } 103 | 104 | private static IEnumerable ParametersToString(ParameterInfo[] parameters) => 105 | parameters.Select(x => x.ParameterType.Name + " " + x.Name).ToArray(); 106 | 107 | private ElementApiMethod GetElementApiMethod(MethodInfo info) => 108 | new () 109 | { 110 | Name = info.Name, 111 | Parameters = ParametersToString(info.GetParameters()), 112 | ReturnValue = info.ReturnType.Name, 113 | Description = _xmlDoc.GetDocumentation(info), 114 | }; 115 | 116 | private ElementApiProperty GetElementApiProperty(PropertyInfo propertyInfo) => 117 | new () 118 | { 119 | Name = propertyInfo.Name, 120 | Type = propertyInfo.PropertyType.Name, 121 | DeclaringType = propertyInfo.DeclaringType.Name, 122 | Description = _xmlDoc.GetDocumentation(propertyInfo), 123 | }; 124 | } 125 | } --------------------------------------------------------------------------------