Skip to content

Commit

Permalink
feat!: Added ability to transform xml-based files using cshtml Razor …
Browse files Browse the repository at this point in the history
…templates.
  • Loading branch information
hennadiilu authored Apr 8, 2024
1 parent 095f3d0 commit 75f8be1
Show file tree
Hide file tree
Showing 23 changed files with 1,262 additions and 598 deletions.
6 changes: 4 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<Project>
<PropertyGroup>
<Version>1.0.0</Version>
<Description>The Docfx plugin to generate documentation from xml-based files via intermediate XSLT transformation into Markdown.</Description>
<Description>
The Docfx plugin to generate documentation from xml-based files via intermediate template transformations into Markdown.
</Description>
<PackageTags>Docfx plugin XSD XML Markdown documentation</PackageTags>

<Authors>Heleonix - Hennadii Lutsyshyn</Authors>
Expand All @@ -26,7 +28,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NeutralLanguage>en-US</NeutralLanguage>
<SatelliteResourceLanguages>en-US</SatelliteResourceLanguages>
</PropertyGroup>
Expand Down
132 changes: 121 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

[![Release: .NET / NuGet](https://github.com/Heleonix/Heleonix.Docfx.Plugins.XmlDoc/actions/workflows/release-net-nuget.yml/badge.svg)](https://github.com/Heleonix/Heleonix.Docfx.Plugins.XmlDoc/actions/workflows/release-net-nuget.yml)

The Docfx plugin to generate documentation from xml-based files via intermediate XSLT transformation into Markdown.
The Docfx plugin to generate documentation from xml-based files via intermediate template transformations into Markdown.

## Install

https://www.nuget.org/packages/Heleonix.Docfx.Plugins.XmlDoc

## Documentation

See [Heleonix.Docfx.Plugins.XmlDoc](https://heleonix.github.io/docs/Plugins/Heleonix.Docfx.Plugins.XmlDoc.html)

## Usage

1. Install the plugin and make it accessible for `Docfx` as a custom template. See [How to enable plugins](https://dotnet.github.io/docfx/tutorial/howto_build_your_own_type_of_documentation_with_custom_plug-in.html#enable-plug-in)
Expand All @@ -19,11 +23,11 @@ https://www.nuget.org/packages/Heleonix.Docfx.Plugins.XmlDoc
}
```
By default, `.xml` and `.xsd` file formats are recognized.
3. Configure the `docfx.json` with the plugin features. See the [Example].
3. Configure the `docfx.json` with the plugin features. See the [docfx.json](#docfx.json).

### Example
### Examples

Example of a configuration in a simple `docfx.json` file:
#### docfx.json

```json
{
Expand Down Expand Up @@ -52,7 +56,7 @@ Example of a configuration in a simple `docfx.json` file:
"templates/template-with-xmldoc-plugin"
],
"fileMetadata": {
"hx.xmldoc.xslt": { "**.xsd": "./xml-to-md.xslt" },
"hx.xmldoc.template": { "**.xsd": "./xml-to-md.xslt" },
"hx.xmldoc.store": { "../../some-external-location/*.xsd": "internal-store-folder" }
"hx.xmldoc.toc": {
"**/*-some.xsd": { "action": "InsertAfter", "key": "~/articles/introduction.md" },
Expand All @@ -63,14 +67,122 @@ Example of a configuration in a simple `docfx.json` file:
}
```

#### input xml-based file, i.e. Hx_NetBuild.xsd

```xml
<?xml version="1.0" encoding="utf-8"?>

<xs:schema xmlns:msb="http://schemas.microsoft.com/developer/msbuild/2003"
elementFormDefault="qualified"
targetNamespace="http://schemas.microsoft.com/developer/msbuild/2003"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Hx_NetBuild_ArtifactsDir" type="msb:StringPropertyType" substitutionGroup="msb:Property">
<xs:annotation>
<xs:documentation>A path to the NetBuild artifacts directory.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Hx_NetBuild_SlnFile" type="msb:StringPropertyType" substitutionGroup="msb:Property">
<xs:annotation>
<xs:documentation>A path to the solution file to build. Default is a .sln file found in the $Hx_WS_Dir.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="Hx_NetBuild_SnkFile" type="msb:StringPropertyType" substitutionGroup="msb:Property">
<xs:annotation>
<xs:documentation>The file with public/private keys pair to sign assemblies.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>

```
#### xslt template

```xml
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msb="http://schemas.microsoft.com/developer/msbuild/2003">
<xsl:output method="text" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:param name="filename"/>
<xsl:template match="/">
# <xsl:value-of select="$filename"/>
### Properties
<xsl:for-each select="xs:schema/xs:element[@substitutionGroup='msb:Property']">
#### <xsl:value-of select="@name"/>
<xsl:text>&#x0A;&#x0A;</xsl:text>
<xsl:value-of select="normalize-space(xs:annotation/xs:documentation)"/>
<xsl:text>&#x0A;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

```

#### cshtml template

```html
@using System
@using System.IO
@using System.Xml.Linq
@inherits RazorEngineCore.RazorEngineTemplateBase<XDocument>
@{
XDocument model = Model;
XNamespace xs = "http://www.w3.org/2001/XMLSchema";

var fileName = Path.GetFileNameWithoutExtension(model.Document.BaseUri);
var elements = model.Document.Element(xs + "schema").Elements(xs + "element");
var props = elements.Where(e => e.Attribute("substitutionGroup")?.Value == "msb:Property");
}
---
uid: @fileName
---

# @fileName

@if (props.Count() > 0)
{
<text>## Properties</text>
@:
foreach (var prop in props)
{
<text>#### @prop.Attribute("name").Value</text>
@:
<text>@prop.Element(xs + "annotation").Element(xs + "documentation").Value.Trim()</text>
@:
}
}
```

#### markdown output

```markdown
# Hx_NetBuild
### Properties

#### Hx_NetBuild_ArtifactsDir

A path to the NetBuild artifacts directory.

#### Hx_NetBuild_SlnFile

A path to the solution file to build. Default is a .sln file found in the $Hx_WS_Dir.

#### Hx_NetBuild_SnkFile

The file with public/private keys pair to sign assemblies.
```

### File Metadata

`hx.xmldoc.xslt` - path to XSLT file to convert xml-based file to Markdown, which is then converted into output HTML by Docfx.
`hx.xmldoc.template` - path to a template `.cshtml` or `.xslt` file to transform xml-based file to Markdown, which is then converted into output HTML by Docfx.

`hx.xmldoc.store` - a folder inside your documentation proejct, where the corresponding xml-based files are copied to
and then used as source files to generate output HTML from.
This is useful, when original files are not always available.
It works like metadata files generated from .NET projects/dlls/xml documentation.
and then used as source files to transform to intermediate markdown and generate output HTML from.
This is useful, when original files are not always available, i.e. when your single documentation project is applied
to different dotnet projects simultaneously to support multi-project documentation.
It works like metadata files generated from .NET projects/dlls/xml documentation, where generated `yaml` metadata could
be commited as part of your documentation project for future re-builds, when the original .NET project is not available.
Hrefs to such files can be specified as `internal-store-folder/your-file.xsd`.

`hx.xmldoc.toc` - specifies where and how the your xml-based files should be added into Table Of Contents.
Expand All @@ -88,11 +200,9 @@ Hrefs to such files can be specified as `internal-store-folder/your-file.xsd`.
You can watch the progress in the [PR: .NET](https://github.com/Heleonix/Heleonix.Docfx.Plugins.XmlDoc/actions/workflows/pr-net.yml) GitHub workflows
4. [Request review](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/requesting-a-pull-request-review) from the code owner
5. Once approved, merge your Pull Request via [Squash and merge](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#squash-and-merge-your-commits)

> **IMPORTANT**
> While merging, enter a [Conventional Commits](https://www.conventionalcommits.org/) commit message.
> This commit message will be used in automatically generated [Github Release Notes](https://github.com/Heleonix/Heleonix.Docfx.Plugins.XmlDoc/releases)
> and [NuGet Release Notes](https://www.nuget.org/packages/Heleonix.Docfx.Plugins.XmlDoc/#releasenotes-body-tab)
6. Monitor the [Release: .NET / NuGet](https://github.com/Heleonix/Heleonix.Docfx.Plugins.XmlDoc/actions/workflows/release-net-nuget.yml) GitHub workflow to make sure your changes are delivered successfully
7. In case of any issues, please contact [[email protected]](mailto:[email protected])
54 changes: 7 additions & 47 deletions src/Heleonix.Docfx.Plugins.XmlDoc/FileMetadata.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,6 @@ namespace Heleonix.Docfx.Plugins.XmlDoc;
/// <summary>
/// Represents the model of the supported <c>fileMetadata</c> specified for content files to be processed by this plugin.
/// </summary>
/// <example>
/// An example of the docfx.json:
/// <code>
/// {
/// "build": {
/// "content": [
/// {
/// "files": [ "**/*.{md,yml}" ],
/// "exclude": [ "_site/**" ]
/// },
/// {
/// "files": [ "*.xsd" ],
/// "src": "../../some-external-location"
/// },
/// {
/// "files": [ "internal-store-folder/*.xsd" ]
/// }
/// ],
/// "resource": [
/// {
/// "files": [ "images/**" ]
/// }
/// ],
/// "output": "_site",
/// "template": [
/// "default",
/// "templates/your-template-with"
/// ],
/// "fileMetadata": {
/// "hx.xmldoc.xslt": { "**.xsd": "./xml-to-md.xslt" },
/// "hx.xmldoc.store": { "../../some-external-location/*.xsd": "internal-store-folder" }
/// "hx.xmldoc.toc": {
/// "**/*-some.xsd": { "action": "InsertAfter", "key": "~/articles/introduction.md" },
/// "**/*-other.xsd": { "action": "AppendChild", "key": "Namespace.Class.whatever.uid" }
/// }
/// }
/// }
/// }
/// </code>
/// </example>
public class FileMetadata
{
/// <summary>
Expand All @@ -58,9 +18,9 @@ public class FileMetadata
public const string StoreKey = "hx.xmldoc.store";

/// <summary>
/// The name of the xslt key in the <c>fileMetadata</c> of content files.
/// The name of the template key in the <c>fileMetadata</c> of content files.
/// </summary>
public const string XsltKey = "hx.xmldoc.xslt";
public const string TemplateKey = "hx.xmldoc.template";

/// <summary>
/// The name of the Table Of Contents key in the <c>fileMetadata</c> of content files.
Expand All @@ -77,10 +37,10 @@ public class FileMetadata
public string Store { get; set; }

/// <summary>
/// The <c>hx.xmldoc.xslt</c> file metadata to specify a path to an XSLT file to transform XML-based content files
/// into Markdown for further generation of HTML output files styled with the documentation templates.
/// The <c>hx.xmldoc.template</c> file metadata to specify a path to a template file to transform XML-based
/// content files into Markdown for further generation of HTML output files styled with the documentation templates.
/// </summary>
public string Xslt { get; set; }
public string Template { get; set; }

/// <summary>
/// The <c>hx.xmldoc.toc</c> file metadata to specify a configuration for
Expand All @@ -106,8 +66,8 @@ public static FileMetadata From(IDictionary<string, object> dictionary)
dictionary.TryGetValue(FileMetadata.StoreKey, out var obj);
metadata.Store = obj as string;

dictionary.TryGetValue(FileMetadata.XsltKey, out obj);
metadata.Xslt = obj as string;
dictionary.TryGetValue(FileMetadata.TemplateKey, out obj);
metadata.Template = obj as string;

dictionary.TryGetValue(FileMetadata.TocKey, out var tocObj);
metadata.Toc = TocMetadata.From(tocObj as IDictionary<string, object>);
Expand Down
Loading

0 comments on commit 75f8be1

Please sign in to comment.