├── docs ├── images │ ├── Code.png │ ├── LPFlow.png │ ├── Diagram.png │ ├── favicon.ico │ ├── favicon.jpg │ ├── FrontMatter.png │ ├── GitHubPages.png │ ├── Navigation.png │ ├── jumbotron.jpg │ ├── DocsForLiterateLib.png │ └── LiterateLibInVSCode.png ├── syntax-highlight │ ├── syntax.js │ ├── syntax-base.less │ ├── monokai.less │ ├── son-of-obsidian.less │ ├── coding-horror.less │ ├── solarized-light.less │ ├── monokai.min.css │ ├── son-of-obsidian.min.css │ ├── coding-horror.min.css │ ├── solarized-light.min.css │ ├── monokai.css │ ├── son-of-obsidian.css │ ├── solarized-light.css │ └── coding-horror.css ├── font-awesome │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── bootstrap │ └── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 ├── css │ ├── landingpage.css │ ├── plain.min.css │ ├── book.min.css │ ├── modern.min.css │ ├── plain.css │ ├── book.css │ └── modern.css ├── sidebar │ ├── sidebar.min.css │ ├── sidebar.css │ ├── sidebar.less │ └── sidebar.js └── mermaid │ ├── mermaid.css │ └── mermaid.dark.css ├── DefaultTheme ├── default_assets │ ├── syntax-highlight │ │ ├── syntax.js │ │ ├── syntax-base.less │ │ ├── monokai.less │ │ ├── son-of-obsidian.less │ │ ├── solarized-light.less │ │ ├── coding-horror.less │ │ ├── monokai.min.css │ │ ├── son-of-obsidian.min.css │ │ ├── coding-horror.min.css │ │ ├── solarized-light.min.css │ │ ├── monokai.css │ │ ├── son-of-obsidian.css │ │ ├── coding-horror.css │ │ └── solarized-light.css │ ├── font-awesome │ │ └── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ ├── bootstrap │ │ └── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ ├── css │ │ ├── landingpage.css │ │ ├── plain.min.css │ │ ├── book.min.css │ │ ├── modern.min.css │ │ ├── plain.css │ │ ├── book.css │ │ ├── plain.less │ │ ├── modern.css │ │ ├── book.less │ │ └── modern.less │ ├── sidebar │ │ ├── sidebar.min.css │ │ ├── sidebar.css │ │ ├── sidebar.less │ │ └── sidebar.js │ └── mermaid │ │ ├── mermaid.css │ │ └── mermaid.dark.css ├── compilerconfig.json ├── IPageTemplate.cs ├── DefaultPageTemplate.cs ├── LandingPageTemplate.cs ├── include │ ├── LandingScripts.tt │ ├── LandingStyles.tt │ ├── Footer.tt │ ├── LandingHead.tt │ ├── Head.tt │ ├── SideBar.tt │ ├── Styles.tt │ ├── Toc.tt │ ├── Scripts.tt │ ├── Pager.tt │ └── NavBar.tt ├── DefaultTheme.cs ├── LandingPage.tt ├── compilerconfig.json.defaults ├── DefaultPage.tt └── DefaultTheme.csproj ├── LiterateCS.Theme ├── LiterateCS.Theme.csproj ├── Theme.cs ├── LiterateException.cs ├── DirHelpers.cs ├── Toc.cs └── PageParams.cs ├── .gitignore ├── defaults.yml ├── License.md ├── .vscode ├── launch.json └── tasks.json ├── TestPackage.ps1 ├── LiterateCS ├── LiterateCS.csproj ├── MdWeaver.cs ├── Program.cs ├── Macro.cs ├── HtmlWeaver.cs ├── TocManager.cs ├── BlockList.cs └── SplitPath.cs ├── Installation.md ├── TableOfContents.md ├── TOC.yml ├── LiterateCS.sln ├── README.md └── index.md /docs/images/Code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/Code.png -------------------------------------------------------------------------------- /docs/images/LPFlow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/LPFlow.png -------------------------------------------------------------------------------- /docs/images/Diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/Diagram.png -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/favicon.ico -------------------------------------------------------------------------------- /docs/images/favicon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/favicon.jpg -------------------------------------------------------------------------------- /docs/images/FrontMatter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/FrontMatter.png -------------------------------------------------------------------------------- /docs/images/GitHubPages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/GitHubPages.png -------------------------------------------------------------------------------- /docs/images/Navigation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/Navigation.png -------------------------------------------------------------------------------- /docs/images/jumbotron.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/jumbotron.jpg -------------------------------------------------------------------------------- /docs/syntax-highlight/syntax.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('[data-toggle="tooltip"]').tooltip(); 3 | }); -------------------------------------------------------------------------------- /docs/images/DocsForLiterateLib.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/DocsForLiterateLib.png -------------------------------------------------------------------------------- /docs/images/LiterateLibInVSCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/images/LiterateLibInVSCode.png -------------------------------------------------------------------------------- /docs/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/syntax.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | $('[data-toggle="tooltip"]').tooltip(); 3 | }); -------------------------------------------------------------------------------- /docs/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /docs/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /docs/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /docs/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /docs/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /docs/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /docs/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /docs/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/docs/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /DefaultTheme/compilerconfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "outputFile": "default_assets/sidebar/sidebar.css", 4 | "inputFile": "default_assets/sidebar/sidebar.less" 5 | } 6 | ] -------------------------------------------------------------------------------- /DefaultTheme/default_assets/font-awesome/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/font-awesome/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/font-awesome/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johtela/LiterateCS/HEAD/DefaultTheme/default_assets/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /DefaultTheme/IPageTemplate.cs: -------------------------------------------------------------------------------- 1 | namespace DefaultTheme 2 | { 3 | using LiterateCS.Theme; 4 | 5 | interface IPageTemplate 6 | { 7 | PageParams Params { get; set; } 8 | string Render (); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /DefaultTheme/DefaultPageTemplate.cs: -------------------------------------------------------------------------------- 1 | namespace DefaultTheme 2 | { 3 | using LiterateCS.Theme; 4 | 5 | public partial class DefaultPage : IPageTemplate 6 | { 7 | public PageParams Params { get; set; } 8 | 9 | public string Render () 10 | { 11 | return TransformText (); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DefaultTheme/LandingPageTemplate.cs: -------------------------------------------------------------------------------- 1 | namespace DefaultTheme 2 | { 3 | using LiterateCS.Theme; 4 | 5 | public partial class LandingPage : IPageTemplate 6 | { 7 | public PageParams Params { get; set; } 8 | 9 | public string Render () 10 | { 11 | return TransformText (); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /LiterateCS.Theme/LiterateCS.Theme.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /docs/css/landingpage.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | margin-bottom: 0px; 3 | } 4 | .jumbotron { 5 | background-image: url("../images/jumbotron.jpg"); 6 | background-size: cover; 7 | } 8 | img.img-responsive { 9 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); 10 | zoom: 1; 11 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/landingpage.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | margin-bottom: 0px; 3 | } 4 | .jumbotron { 5 | background-image: url("../images/jumbotron.jpg"); 6 | background-size: cover; 7 | } 8 | img.img-responsive { 9 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); 10 | zoom: 1; 11 | } -------------------------------------------------------------------------------- /DefaultTheme/include/LandingScripts.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # This .gitignore file was automatically created by Microsoft(R) Visual Studio. 3 | ################################################################################ 4 | 5 | .vs 6 | bin 7 | obj 8 | /packages 9 | *.csproj.user 10 | *.swp 11 | *.zip 12 | *.nupkg 13 | /buildlog.txt 14 | launchSettings.json -------------------------------------------------------------------------------- /DefaultTheme/include/LandingStyles.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | /bootstrap.min.css" /> 6 | 7 | 8 | -------------------------------------------------------------------------------- /DefaultTheme/include/Footer.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | 6 | 14 | -------------------------------------------------------------------------------- /docs/syntax-highlight/syntax-base.less: -------------------------------------------------------------------------------- 1 | @code-tab-size: 4; 2 | 3 | .code-block { 4 | -moz-tab-size: @code-tab-size; 5 | -o-tab-size: @code-tab-size; 6 | tab-size: @code-tab-size; 7 | 8 | -webkit-hyphens: none; 9 | -moz-hyphens: none; 10 | -ms-hyphens: none; 11 | hyphens: none; 12 | 13 | white-space: pre; 14 | word-spacing: normal; 15 | word-break: normal; 16 | word-wrap: normal; 17 | overflow-x: auto; 18 | overflow-y: hidden; 19 | } 20 | .tooltip-inner { 21 | max-width: 1000px; 22 | } 23 | -------------------------------------------------------------------------------- /docs/sidebar/sidebar.min.css: -------------------------------------------------------------------------------- 1 | .main-menu ul{list-style-type:none;padding:0;}.main-menu ul ul{font-size:.98em;padding-left:10px;}.main-menu li a{padding-bottom:3px;padding-top:3px;display:block;color:#456;text-decoration:none;}.main-menu li a:hover,.main-menu li a.selected{padding-left:5px;background-color:#456;color:#fff;}.main-menu li a:active{padding-left:5px;background-color:#000;color:#fff;}#sidebar{padding-top:1em;border-radius:3px;}@media(max-width:991px){.sidebar-popup{position:absolute;background-color:rgba(0,0,0,.5);z-index:100;}} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/syntax-base.less: -------------------------------------------------------------------------------- 1 | @code-tab-size: 4; 2 | 3 | .code-block { 4 | -moz-tab-size: @code-tab-size; 5 | -o-tab-size: @code-tab-size; 6 | tab-size: @code-tab-size; 7 | 8 | -webkit-hyphens: none; 9 | -moz-hyphens: none; 10 | -ms-hyphens: none; 11 | hyphens: none; 12 | 13 | white-space: pre; 14 | word-spacing: normal; 15 | word-break: normal; 16 | word-wrap: normal; 17 | overflow-x: auto; 18 | overflow-y: hidden; 19 | } 20 | .tooltip-inner { 21 | max-width: 1000px; 22 | } 23 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/sidebar/sidebar.min.css: -------------------------------------------------------------------------------- 1 | .main-menu ul{list-style-type:none;padding:0;}.main-menu ul ul{font-size:.98em;padding-left:10px;}.main-menu li a{padding-bottom:3px;padding-top:3px;display:block;color:#456;text-decoration:none;}.main-menu li a:hover,.main-menu li a.selected{padding-left:5px;background-color:#456;color:#fff;}.main-menu li a:active{padding-left:5px;background-color:#000;color:#fff;}#sidebar{padding-top:1em;border-radius:3px;}@media(max-width:991px){.sidebar-popup{position:absolute;background-color:rgba(0,0,0,.5);z-index:100;}} -------------------------------------------------------------------------------- /DefaultTheme/include/LandingHead.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | 6 | 7 | 8 | 9 | 10 | <#= Params["projectname"] #> 11 | 12 | 13 | <#@ include file="LandingStyles.tt" #> 14 | -------------------------------------------------------------------------------- /DefaultTheme/include/Head.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | 6 | 7 | 8 | 9 | 10 | <#= Params.Filename + " - " + Params["projectname"] #> 11 | 12 | 13 | <#@ include file="styles.tt" #> 14 | -------------------------------------------------------------------------------- /defaults.yml: -------------------------------------------------------------------------------- 1 | # Front matter defaults 2 | --- 3 | ProjectName: LiterateCS 4 | GitHub: https://github.com/johtela/LiterateCS 5 | Download: https://www.nuget.org/packages/LiterateCS/ 6 | License: License.html 7 | Footer: "Copyright © 2022 Tommi Johtela" 8 | ShowDescriptionsInToc: false 9 | BootstrapStyle: readable 10 | MarkdownStyle: book 11 | SyntaxHighlight: solarized-light 12 | UseDiagrams: true 13 | DiagramStyle: mermaid 14 | UseMath: true 15 | Logo: images/favicon.ico 16 | 17 | # Command line arguments 18 | --- 19 | filters: 20 | - "LiterateCS/*.cs" 21 | - "LiterateCS.Theme/*.cs" 22 | - "*.md" 23 | output: docs 24 | solution: LiterateCS.sln 25 | format: html 26 | trim: true 27 | verbose: true 28 | updatetoc: true 29 | buildlog: buildlog.txt -------------------------------------------------------------------------------- /docs/sidebar/sidebar.css: -------------------------------------------------------------------------------- 1 | .main-menu ul { 2 | list-style-type: none; 3 | padding: 0px; 4 | } 5 | .main-menu ul ul { 6 | font-size: 0.98em; 7 | padding-left: 10px; 8 | } 9 | .main-menu li a { 10 | padding-bottom: 3px; 11 | padding-top: 3px; 12 | display: block; 13 | color: #456; 14 | text-decoration: none; 15 | } 16 | .main-menu li a:hover, 17 | .main-menu li a.selected { 18 | padding-left: 5px; 19 | background-color: #456; 20 | color: #fff; 21 | } 22 | .main-menu li a:active { 23 | padding-left: 5px; 24 | background-color: #000; 25 | color: #fff; 26 | } 27 | #sidebar { 28 | padding-top: 1em; 29 | border-radius: 3px; 30 | } 31 | @media (max-width: 991px) { 32 | .sidebar-popup { 33 | position: absolute; 34 | background-color: rgba(0, 0, 0, 0.5); 35 | z-index: 100; 36 | } 37 | } -------------------------------------------------------------------------------- /DefaultTheme/include/SideBar.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | 6 |
7 |
8 |

On This Page

9 |
10 | 13 |
14 |
15 |
16 |

Table of Contents

17 |
18 | 21 |
22 | -------------------------------------------------------------------------------- /docs/sidebar/sidebar.less: -------------------------------------------------------------------------------- 1 | @text-color: #456; 2 | @highlight-bg-color: #000; 3 | @highlight-color: #fff; 4 | 5 | .main-menu { 6 | ul { 7 | list-style-type: none; 8 | padding: 0px; 9 | ul { 10 | font-size: 0.98em; 11 | padding-left: 10px; 12 | } 13 | } 14 | li a { 15 | padding-bottom: 3px; 16 | padding-top: 3px; 17 | display: block; 18 | color: @text-color; 19 | text-decoration: none; 20 | &:hover, &.selected { 21 | padding-left: 5px; 22 | background-color: @text-color; 23 | color: @highlight-color; 24 | } 25 | &:active { 26 | padding-left: 5px; 27 | background-color: @highlight-bg-color; 28 | color: @highlight-color; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /DefaultTheme/include/Styles.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | /bootstrap.min.css" /> 6 | 7 | 8 | .min.css" /> 9 | .min.css" /> 10 | .css" /> 11 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/sidebar/sidebar.css: -------------------------------------------------------------------------------- 1 | .main-menu ul { 2 | list-style-type: none; 3 | padding: 0px; 4 | } 5 | .main-menu ul ul { 6 | font-size: 0.98em; 7 | padding-left: 10px; 8 | } 9 | .main-menu li a { 10 | padding-bottom: 3px; 11 | padding-top: 3px; 12 | display: block; 13 | color: #456; 14 | text-decoration: none; 15 | } 16 | .main-menu li a:hover, 17 | .main-menu li a.selected { 18 | padding-left: 5px; 19 | background-color: #456; 20 | color: #fff; 21 | } 22 | .main-menu li a:active { 23 | padding-left: 5px; 24 | background-color: #000; 25 | color: #fff; 26 | } 27 | #sidebar { 28 | padding-top: 1em; 29 | border-radius: 3px; 30 | } 31 | @media (max-width: 991px) { 32 | .sidebar-popup { 33 | position: absolute; 34 | background-color: rgba(0, 0, 0, 0.5); 35 | z-index: 100; 36 | } 37 | } -------------------------------------------------------------------------------- /docs/syntax-highlight/monokai.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #f8f8f2; 6 | background: #272822; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #d0d0c8; 11 | } 12 | .keyword { 13 | color: #66d9ef; 14 | } 15 | .comment { 16 | color: #a6e22e; 17 | } 18 | .preprocessor { 19 | color: slategray; 20 | } 21 | .string { 22 | color: #f92672; 23 | } 24 | .number { 25 | color: #ae81ff; 26 | } 27 | .typename { 28 | color: #e6db74; 29 | } 30 | a { 31 | color: inherit; 32 | &:visited { 33 | color: inherit; 34 | } 35 | &:hover { 36 | color: deepskyblue; 37 | text-decoration: underline; 38 | } 39 | &:active { 40 | color: blueviolet; 41 | text-decoration: underline; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /docs/syntax-highlight/son-of-obsidian.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #f1f2f2; 6 | background: #22282a; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #e8e2b7; 11 | } 12 | .keyword { 13 | color: #93c763; 14 | } 15 | .comment { 16 | color: #66747b; 17 | } 18 | .preprocessor { 19 | color: #a082bd; 20 | } 21 | .string { 22 | color: #ec7600; 23 | } 24 | .number { 25 | color: #ffcd22; 26 | } 27 | .typename { 28 | color: #678cb1; 29 | } 30 | a { 31 | color: inherit; 32 | &:visited { 33 | color: inherit; 34 | } 35 | &:hover { 36 | color: deepskyblue; 37 | text-decoration: underline; 38 | } 39 | &:active { 40 | color: blueviolet; 41 | text-decoration: underline; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/monokai.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #f8f8f2; 6 | background: #272822; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #d0d0c8; 11 | } 12 | .keyword { 13 | color: #66d9ef; 14 | } 15 | .comment { 16 | color: #a6e22e; 17 | } 18 | .preprocessor { 19 | color: slategray; 20 | } 21 | .string { 22 | color: #f92672; 23 | } 24 | .number { 25 | color: #ae81ff; 26 | } 27 | .typename { 28 | color: #e6db74; 29 | } 30 | a { 31 | color: inherit; 32 | &:visited { 33 | color: inherit; 34 | } 35 | &:hover { 36 | color: deepskyblue; 37 | text-decoration: underline; 38 | } 39 | &:active { 40 | color: blueviolet; 41 | text-decoration: underline; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/son-of-obsidian.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #f1f2f2; 6 | background: #22282a; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #e8e2b7; 11 | } 12 | .keyword { 13 | color: #93c763; 14 | } 15 | .comment { 16 | color: #66747b; 17 | } 18 | .preprocessor { 19 | color: #a082bd; 20 | } 21 | .string { 22 | color: #ec7600; 23 | } 24 | .number { 25 | color: #ffcd22; 26 | } 27 | .typename { 28 | color: #678cb1; 29 | } 30 | a { 31 | color: inherit; 32 | &:visited { 33 | color: inherit; 34 | } 35 | &:hover { 36 | color: deepskyblue; 37 | text-decoration: underline; 38 | } 39 | &:active { 40 | color: blueviolet; 41 | text-decoration: underline; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /docs/syntax-highlight/coding-horror.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #000000; 6 | background: #F8F8F8; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #000000; 11 | } 12 | .keyword { 13 | color: #000080; 14 | } 15 | .comment { 16 | color: #008000; 17 | } 18 | .preprocessor { 19 | color: slategray; 20 | } 21 | .string { 22 | color: #000000; 23 | background: #ffffe6; 24 | } 25 | .number { 26 | color: #800000; 27 | } 28 | .typename { 29 | color: #a65300; 30 | } 31 | a { 32 | color: inherit; 33 | &:visited { 34 | color: inherit; 35 | } 36 | &:hover { 37 | color: blue; 38 | text-decoration: underline; 39 | } 40 | &:active { 41 | color: blueviolet; 42 | text-decoration: underline; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /docs/syntax-highlight/solarized-light.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #657b83; 6 | background: #fdf6e3; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #719a07; 11 | } 12 | .keyword { 13 | color: #859900; 14 | } 15 | .comment { 16 | color: #93a1a1; 17 | } 18 | .preprocessor { 19 | color: #cb4b16; 20 | } 21 | .string { 22 | color: #2aa198; 23 | } 24 | .number { 25 | color: #2aa198; 26 | } 27 | .typename { 28 | color: #b58900; 29 | font-weight: bold 30 | } 31 | a { 32 | color: inherit; 33 | &:visited { 34 | color: inherit; 35 | } 36 | &:hover { 37 | color: blue; 38 | text-decoration: underline; 39 | } 40 | &:active { 41 | color: blueviolet; 42 | text-decoration: underline; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /DefaultTheme/include/Toc.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | <#+ public void OutputToc (List
sections) 6 | { #> 7 | 32 | <#+ } 33 | 34 | private string SectionStyle (Section section) 35 | { 36 | return section == Params.CurrentSection ? " class=\"selected\"" : ""; 37 | } 38 | 39 | #> -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/solarized-light.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #657b83; 6 | background: #fdf6e3; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #719a07; 11 | } 12 | .keyword { 13 | color: #859900; 14 | } 15 | .comment { 16 | color: #93a1a1; 17 | } 18 | .preprocessor { 19 | color: #cb4b16; 20 | } 21 | .string { 22 | color: #2aa198; 23 | } 24 | .number { 25 | color: #2aa198; 26 | } 27 | .typename { 28 | color: #b58900; 29 | font-weight: bold 30 | } 31 | a { 32 | color: inherit; 33 | &:visited { 34 | color: inherit; 35 | } 36 | &:hover { 37 | color: blue; 38 | text-decoration: underline; 39 | } 40 | &:active { 41 | color: blueviolet; 42 | text-decoration: underline; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/coding-horror.less: -------------------------------------------------------------------------------- 1 | @import "syntax-base.less"; 2 | 3 | pre.csharp, 4 | code.csharp { 5 | color: #000000; 6 | background: #F8F8F8; 7 | .code-block (); 8 | 9 | .punctuation { 10 | color: #000000; 11 | } 12 | .keyword { 13 | color: #000080; 14 | } 15 | .comment { 16 | color: #008000; 17 | } 18 | .preprocessor { 19 | color: slategray; 20 | } 21 | .string { 22 | color: #000000; 23 | background: #ffffe6; 24 | } 25 | .number { 26 | color: #800000; 27 | } 28 | .typename { 29 | color: #a65300; 30 | } 31 | a { 32 | color: inherit; 33 | &:visited { 34 | color: inherit; 35 | } 36 | &:hover { 37 | color: blue; 38 | text-decoration: underline; 39 | } 40 | &:active { 41 | color: blueviolet; 42 | text-decoration: underline; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /DefaultTheme/include/Scripts.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | 6 | 7 | 8 | 9 | 10 | <# 11 | if (Params["usemath", null] != null) 12 | { 13 | #> 14 | 15 | 16 | <# 17 | } 18 | if (Params["usediagrams", null] != null) 19 | { 20 | #> 21 | 22 | 23 | <# 24 | } 25 | #> -------------------------------------------------------------------------------- /DefaultTheme/include/Pager.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.IO" #> 5 | <#@ import namespace="LiterateCS.Theme" #> 6 | <#+ public void OutputPager () 7 | { 8 | var current = Params.CurrentSection; 9 | if (current == null) 10 | return; 11 | var prev = Params.Toc.PreviousSection (current); 12 | var next = Params.Toc.NextSection (current); 13 | #> 14 | 18 | <#+ } 19 | 20 | private string Disabled (Section entry) => 21 | entry == null ? " disabled" : ""; 22 | 23 | private string Link (Section entry) => 24 | entry != null ? Params.SectionPath (entry) : "#"; 25 | 26 | private string Title (Section entry) => 27 | entry != null ? ": " + entry.Page : ""; 28 | #> -------------------------------------------------------------------------------- /DefaultTheme/DefaultTheme.cs: -------------------------------------------------------------------------------- 1 | namespace DefaultTheme 2 | { 3 | using System; 4 | using LiterateCS.Theme; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | public class DefaultTheme : Theme 9 | { 10 | private static Dictionary> _templates = 11 | new Dictionary> 12 | { 13 | {"default", () => new DefaultPage () }, 14 | {"landing", () => new LandingPage () } 15 | }; 16 | 17 | public override string[] AvalailablePageTemplates => 18 | _templates.Keys.ToArray (); 19 | 20 | public override string AssetDir => "default_assets"; 21 | 22 | public override string RenderPage (string pageTemplate, PageParams pageParams) 23 | { 24 | var templName = pageTemplate ?? "default"; 25 | if (!_templates.ContainsKey (templName)) 26 | throw new ArgumentException ("Unsupported page template: " + pageTemplate); 27 | var template = _templates[templName] (); 28 | template.Params = pageParams; 29 | return template.Render(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DefaultTheme/LandingPage.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".html" #> 7 | 8 | 9 | 10 | <#@ include file="include/LandingHead.tt" #> 11 | 12 | 13 | <#@ include file="include/navbar.tt" #> 14 | 15 | 16 |
17 |
18 | <#= Params["_jumbotron"] #> 19 |

Learn more »

20 |
21 |
22 | 23 |
24 | <#= Params.Contents #> 25 |
26 | 27 | <#@ include file="include/Footer.tt" #> 28 | 29 | <#@ include file="include/LandingScripts.tt" #> 30 | 31 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/sidebar/sidebar.less: -------------------------------------------------------------------------------- 1 | @text-color: #456; 2 | @highlight-bg-color: #000; 3 | @highlight-color: #fff; 4 | 5 | .main-menu { 6 | ul { 7 | list-style-type: none; 8 | padding: 0px; 9 | ul { 10 | font-size: 0.98em; 11 | padding-left: 10px; 12 | } 13 | } 14 | li a { 15 | padding-bottom: 3px; 16 | padding-top: 3px; 17 | display: block; 18 | color: @text-color; 19 | text-decoration: none; 20 | &:hover, &.selected { 21 | padding-left: 5px; 22 | background-color: @text-color; 23 | color: @highlight-color; 24 | } 25 | &:active { 26 | padding-left: 5px; 27 | background-color: @highlight-bg-color; 28 | color: @highlight-color; 29 | } 30 | } 31 | } 32 | 33 | #sidebar { 34 | padding-top: 1em; 35 | border-radius: 3px; 36 | } 37 | 38 | @media(max-width: 991px) { 39 | .sidebar-popup { 40 | position: absolute; 41 | background-color: rgba(0,0,0,0.5); 42 | z-index: 100; 43 | } 44 | } -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | **Copyright © 2018 Tommi Johtela** 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. -------------------------------------------------------------------------------- /DefaultTheme/compilerconfig.json.defaults: -------------------------------------------------------------------------------- 1 | { 2 | "compilers": { 3 | "less": { 4 | "autoPrefix": "", 5 | "cssComb": "none", 6 | "ieCompat": true, 7 | "strictMath": false, 8 | "strictUnits": false, 9 | "relativeUrls": true, 10 | "rootPath": "", 11 | "sourceMapRoot": "", 12 | "sourceMapBasePath": "", 13 | "sourceMap": false 14 | }, 15 | "sass": { 16 | "includePath": "", 17 | "indentType": "space", 18 | "indentWidth": 2, 19 | "outputStyle": "nested", 20 | "Precision": 5, 21 | "relativeUrls": true, 22 | "sourceMapRoot": "", 23 | "sourceMap": false 24 | }, 25 | "stylus": { 26 | "sourceMap": false 27 | }, 28 | "babel": { 29 | "sourceMap": false 30 | }, 31 | "coffeescript": { 32 | "bare": false, 33 | "runtimeMode": "node", 34 | "sourceMap": false 35 | } 36 | }, 37 | "minifiers": { 38 | "css": { 39 | "enabled": true, 40 | "termSemicolons": true, 41 | "gzip": false 42 | }, 43 | "javascript": { 44 | "enabled": true, 45 | "termSemicolons": true, 46 | "gzip": false 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /DefaultTheme/DefaultPage.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="false" hostspecific="false" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Text" #> 5 | <#@ import namespace="System.Collections.Generic" #> 6 | <#@ output extension=".html" #> 7 | <#@ include file="include/Toc.tt" #> 8 | <#@ include file="include/Pager.tt" #> 9 | 10 | 11 | 12 | <#@ include file="include/Head.tt" #> 13 | 14 | 15 | <#@ include file="include/navbar.tt" #> 16 | 17 |
18 |
19 | 22 |
23 | <# OutputPager (); #> 24 |
25 | <#= Params.Contents #> 26 |
27 | <# OutputPager (); #> 28 |
29 |
30 |
31 | <#@ include file="include/Footer.tt" #> 32 | 33 | <#@ include file="include/Scripts.tt" #> 34 | 35 | 36 | -------------------------------------------------------------------------------- /docs/syntax-highlight/monokai.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#f8f8f2;background:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#d0d0c8;}pre.csharp .keyword,code.csharp .keyword{color:#66d9ef;}pre.csharp .comment,code.csharp .comment{color:#a6e22e;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#708090;}pre.csharp .string,code.csharp .string{color:#f92672;}pre.csharp .number,code.csharp .number{color:#ae81ff;}pre.csharp .typename,code.csharp .typename{color:#e6db74;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00bfff;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to find out which attributes exist for C# debugging 3 | // Use hover for the description of the existing attributes 4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": ".NET Core Launch (console)", 9 | "type": "coreclr", 10 | "request": "launch", 11 | "preLaunchTask": "build", 12 | // If you have changed target frameworks, make sure to update the program path. 13 | "program": "${workspaceFolder}/LiterateCS/bin/Debug/net6.0/publish/LiterateCS.exe", 14 | "args": [], 15 | "cwd": "${workspaceFolder}", 16 | // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console 17 | "console": "internalConsole", 18 | "stopAtEntry": false 19 | }, 20 | { 21 | "name": ".NET Core Attach", 22 | "type": "coreclr", 23 | "request": "attach", 24 | "processId": "${command:pickProcess}" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /docs/syntax-highlight/son-of-obsidian.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#f1f2f2;background:#22282a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#e8e2b7;}pre.csharp .keyword,code.csharp .keyword{color:#93c763;}pre.csharp .comment,code.csharp .comment{color:#66747b;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#a082bd;}pre.csharp .string,code.csharp .string{color:#ec7600;}pre.csharp .number,code.csharp .number{color:#ffcd22;}pre.csharp .typename,code.csharp .typename{color:#678cb1;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00bfff;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /docs/syntax-highlight/coding-horror.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#000;background:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#000;}pre.csharp .keyword,code.csharp .keyword{color:#000080;}pre.csharp .comment,code.csharp .comment{color:#008000;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#708090;}pre.csharp .string,code.csharp .string{color:#000;background:#ffffe6;}pre.csharp .number,code.csharp .number{color:#800000;}pre.csharp .typename,code.csharp .typename{color:#a65300;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00f;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/monokai.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#f8f8f2;background:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#d0d0c8;}pre.csharp .keyword,code.csharp .keyword{color:#66d9ef;}pre.csharp .comment,code.csharp .comment{color:#a6e22e;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#708090;}pre.csharp .string,code.csharp .string{color:#f92672;}pre.csharp .number,code.csharp .number{color:#ae81ff;}pre.csharp .typename,code.csharp .typename{color:#e6db74;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00bfff;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /docs/syntax-highlight/solarized-light.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#657b83;background:#fdf6e3;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#719a07;}pre.csharp .keyword,code.csharp .keyword{color:#859900;}pre.csharp .comment,code.csharp .comment{color:#93a1a1;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#cb4b16;}pre.csharp .string,code.csharp .string{color:#2aa198;}pre.csharp .number,code.csharp .number{color:#2aa198;}pre.csharp .typename,code.csharp .typename{color:#b58900;font-weight:bold;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00f;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/son-of-obsidian.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#f1f2f2;background:#22282a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#e8e2b7;}pre.csharp .keyword,code.csharp .keyword{color:#93c763;}pre.csharp .comment,code.csharp .comment{color:#66747b;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#a082bd;}pre.csharp .string,code.csharp .string{color:#ec7600;}pre.csharp .number,code.csharp .number{color:#ffcd22;}pre.csharp .typename,code.csharp .typename{color:#678cb1;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00bfff;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/coding-horror.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#000;background:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#000;}pre.csharp .keyword,code.csharp .keyword{color:#000080;}pre.csharp .comment,code.csharp .comment{color:#008000;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#708090;}pre.csharp .string,code.csharp .string{color:#000;background:#ffffe6;}pre.csharp .number,code.csharp .number{color:#800000;}pre.csharp .typename,code.csharp .typename{color:#a65300;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00f;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/solarized-light.min.css: -------------------------------------------------------------------------------- 1 | .code-block{-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}.tooltip-inner{max-width:1000px;}pre.csharp,code.csharp{color:#657b83;background:#fdf6e3;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;overflow-x:auto;overflow-y:hidden;}pre.csharp .punctuation,code.csharp .punctuation{color:#719a07;}pre.csharp .keyword,code.csharp .keyword{color:#859900;}pre.csharp .comment,code.csharp .comment{color:#93a1a1;}pre.csharp .preprocessor,code.csharp .preprocessor{color:#cb4b16;}pre.csharp .string,code.csharp .string{color:#2aa198;}pre.csharp .number,code.csharp .number{color:#2aa198;}pre.csharp .typename,code.csharp .typename{color:#b58900;font-weight:bold;}pre.csharp a,code.csharp a{color:inherit;}pre.csharp a:visited,code.csharp a:visited{color:inherit;}pre.csharp a:hover,code.csharp a:hover{color:#00f;text-decoration:underline;}pre.csharp a:active,code.csharp a:active{color:#8a2be2;text-decoration:underline;} -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "build", 6 | "command": "dotnet", 7 | "type": "process", 8 | "args": [ 9 | "build", 10 | "${workspaceFolder}/LiterateCS/LiterateCS.csproj" 11 | ], 12 | "group": { 13 | "kind": "build", 14 | "isDefault": true 15 | }, 16 | "problemMatcher": "$msCompile" 17 | }, 18 | { 19 | "label": "publish", 20 | "command": "dotnet", 21 | "type": "process", 22 | "args": [ 23 | "publish", 24 | "${workspaceFolder}/LiterateCS/LiterateCS.csproj", 25 | "--configuration Release", 26 | ], 27 | "problemMatcher": "$msCompile" 28 | }, 29 | { 30 | "label": "watch", 31 | "command": "dotnet", 32 | "type": "process", 33 | "args": [ 34 | "watch", 35 | "run", 36 | "${workspaceFolder}/LiterateCS/LiterateCS.csproj" 37 | ], 38 | "problemMatcher": "$msCompile" 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /TestPackage.ps1: -------------------------------------------------------------------------------- 1 | function Assert ([scriptblock] $condition) 2 | { 3 | if (!(& $condition)) 4 | { 5 | throw "Condition {$condition} does not hold." 6 | } 7 | } 8 | 9 | $rootdir = split-path -parent $MyInvocation.MyCommand.Definition 10 | Set-Location $rootdir 11 | [Environment]::CurrentDirectory = $rootdir 12 | 13 | Write-Host "Installing the package." 14 | dotnet tool install -g LiterateCS --add-source LiterateCS\bin\Release 15 | 16 | Write-Host "Generating HTML documentation for LiterateCS." 17 | & { 18 | $ErrorActionPreference = "SilentlyContinue" 19 | & literatecs LiterateCS\*.cs LiterateCS.Theme\*.cs *.md -s LiterateCS.sln -o docs -f html -tv 20 | } 21 | Assert { $LASTEXITCODE -eq 0 } 22 | Assert { Test-Path docs } 23 | Assert { Test-Path docs\*.html } 24 | Assert { Test-Path docs\LiterateCS\*.html } 25 | Assert { Test-Path docs\LiterateCS.Theme\*.html } 26 | Assert { Test-Path docs\bootstrap } 27 | Assert { Test-Path docs\css\*.min.css } 28 | Assert { Test-Path docs\font-awesome } 29 | Assert { Test-Path docs\Images\*.png } 30 | Assert { Test-Path docs\mermaid\*.css } 31 | Assert { Test-Path docs\sidebar\*.min.css } 32 | Assert { Test-Path docs\syntax-highlight\*.min.css } 33 | 34 | Write-Host "Uninstalling the package." 35 | dotnet tool uninstall -g LiterateCS 36 | 37 | Pop-Location 38 | -------------------------------------------------------------------------------- /docs/syntax-highlight/monokai.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #f8f8f2; 22 | background: #272822; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #d0d0c8; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #66d9ef; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #a6e22e; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: slategray; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #f92672; 56 | } 57 | pre.csharp .number, 58 | code.csharp .number { 59 | color: #ae81ff; 60 | } 61 | pre.csharp .typename, 62 | code.csharp .typename { 63 | color: #e6db74; 64 | } 65 | pre.csharp a, 66 | code.csharp a { 67 | color: inherit; 68 | } 69 | pre.csharp a:visited, 70 | code.csharp a:visited { 71 | color: inherit; 72 | } 73 | pre.csharp a:hover, 74 | code.csharp a:hover { 75 | color: deepskyblue; 76 | text-decoration: underline; 77 | } 78 | pre.csharp a:active, 79 | code.csharp a:active { 80 | color: blueviolet; 81 | text-decoration: underline; 82 | } -------------------------------------------------------------------------------- /docs/syntax-highlight/son-of-obsidian.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #f1f2f2; 22 | background: #22282a; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #e8e2b7; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #93c763; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #66747b; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: #a082bd; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #ec7600; 56 | } 57 | pre.csharp .number, 58 | code.csharp .number { 59 | color: #ffcd22; 60 | } 61 | pre.csharp .typename, 62 | code.csharp .typename { 63 | color: #678cb1; 64 | } 65 | pre.csharp a, 66 | code.csharp a { 67 | color: inherit; 68 | } 69 | pre.csharp a:visited, 70 | code.csharp a:visited { 71 | color: inherit; 72 | } 73 | pre.csharp a:hover, 74 | code.csharp a:hover { 75 | color: deepskyblue; 76 | text-decoration: underline; 77 | } 78 | pre.csharp a:active, 79 | code.csharp a:active { 80 | color: blueviolet; 81 | text-decoration: underline; 82 | } -------------------------------------------------------------------------------- /docs/css/plain.min.css: -------------------------------------------------------------------------------- 1 | .markdown{color:#333;font-size:16px;line-height:1.6;}.markdown a{color:#0645ad;text-decoration:none;}.markdown a:visited{color:#0b0080;}.markdown a:hover{color:#06e;}.markdown a:active{color:#faa700;}.markdown a:focus{outline:thin dotted;}.markdown a:hover,.markdown a:active{outline:0;}.markdown p{margin:1em 0;}.markdown img{max-width:100%;}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{color:#111;line-height:1em;margin-top:1.5em;}.markdown h1{margin-top:0;border-bottom:1px solid #ddd;font-size:30px;}.markdown h2{font-size:24px;}.markdown h3{font-size:18px;}.markdown h4{font-size:16px;}.markdown h5{font-size:14px;}.markdown h6{font-size:12px;}.markdown blockquote{color:#666;font-style:italic;margin:0;padding-left:3em;border:none;}.markdown hr{height:4px;padding:0;margin:16px 0;background-color:#e7e7e7;border:0 none;}.markdown code,.markdown pre{font-size:.95em;tab-size:4;overflow-x:auto;overflow-y:hidden;}.markdown pre{white-space:pre-wrap;word-wrap:break-word;}.markdown b,.markdown strong{font-weight:bold;}.markdown ins{background:#ff9;color:#000;text-decoration:none;}.markdown mark{background:#ff0;color:#000;font-style:italic;font-weight:bold;}.markdown sub,.markdown sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}.markdown sup{top:-.5em;}.markdown sub{bottom:-.25em;}.markdown ul,.markdown ol{margin:1em 0;padding:0 0 0 2em;}.markdown li p:last-child{margin:0;}.markdown dd{margin:0 0 0 2em;}.markdown img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;}.markdown table{border:none;border-collapse:collapse;margin-left:1em;margin-right:1em;}.markdown tbody tr{border-bottom:1px solid #ddd;}.markdown th,.markdown td{padding:.5em;}.markdown th{border-bottom:2px solid #ddd;}.markdown td{vertical-align:top;}.markdown svg{display:block;margin-left:auto;margin-right:auto;} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/monokai.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #f8f8f2; 22 | background: #272822; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #d0d0c8; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #66d9ef; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #a6e22e; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: slategray; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #f92672; 56 | } 57 | pre.csharp .number, 58 | code.csharp .number { 59 | color: #ae81ff; 60 | } 61 | pre.csharp .typename, 62 | code.csharp .typename { 63 | color: #e6db74; 64 | } 65 | pre.csharp a, 66 | code.csharp a { 67 | color: inherit; 68 | } 69 | pre.csharp a:visited, 70 | code.csharp a:visited { 71 | color: inherit; 72 | } 73 | pre.csharp a:hover, 74 | code.csharp a:hover { 75 | color: deepskyblue; 76 | text-decoration: underline; 77 | } 78 | pre.csharp a:active, 79 | code.csharp a:active { 80 | color: blueviolet; 81 | text-decoration: underline; 82 | } -------------------------------------------------------------------------------- /docs/syntax-highlight/solarized-light.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #657b83; 22 | background: #fdf6e3; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #719a07; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #859900; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #93a1a1; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: #cb4b16; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #2aa198; 56 | } 57 | pre.csharp .number, 58 | code.csharp .number { 59 | color: #2aa198; 60 | } 61 | pre.csharp .typename, 62 | code.csharp .typename { 63 | color: #b58900; 64 | font-weight: bold; 65 | } 66 | pre.csharp a, 67 | code.csharp a { 68 | color: inherit; 69 | } 70 | pre.csharp a:visited, 71 | code.csharp a:visited { 72 | color: inherit; 73 | } 74 | pre.csharp a:hover, 75 | code.csharp a:hover { 76 | color: blue; 77 | text-decoration: underline; 78 | } 79 | pre.csharp a:active, 80 | code.csharp a:active { 81 | color: blueviolet; 82 | text-decoration: underline; 83 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/son-of-obsidian.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #f1f2f2; 22 | background: #22282a; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #e8e2b7; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #93c763; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #66747b; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: #a082bd; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #ec7600; 56 | } 57 | pre.csharp .number, 58 | code.csharp .number { 59 | color: #ffcd22; 60 | } 61 | pre.csharp .typename, 62 | code.csharp .typename { 63 | color: #678cb1; 64 | } 65 | pre.csharp a, 66 | code.csharp a { 67 | color: inherit; 68 | } 69 | pre.csharp a:visited, 70 | code.csharp a:visited { 71 | color: inherit; 72 | } 73 | pre.csharp a:hover, 74 | code.csharp a:hover { 75 | color: deepskyblue; 76 | text-decoration: underline; 77 | } 78 | pre.csharp a:active, 79 | code.csharp a:active { 80 | color: blueviolet; 81 | text-decoration: underline; 82 | } -------------------------------------------------------------------------------- /docs/syntax-highlight/coding-horror.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #000000; 22 | background: #F8F8F8; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #000000; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #000080; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #008000; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: slategray; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #000000; 56 | background: #ffffe6; 57 | } 58 | pre.csharp .number, 59 | code.csharp .number { 60 | color: #800000; 61 | } 62 | pre.csharp .typename, 63 | code.csharp .typename { 64 | color: #a65300; 65 | } 66 | pre.csharp a, 67 | code.csharp a { 68 | color: inherit; 69 | } 70 | pre.csharp a:visited, 71 | code.csharp a:visited { 72 | color: inherit; 73 | } 74 | pre.csharp a:hover, 75 | code.csharp a:hover { 76 | color: blue; 77 | text-decoration: underline; 78 | } 79 | pre.csharp a:active, 80 | code.csharp a:active { 81 | color: blueviolet; 82 | text-decoration: underline; 83 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/plain.min.css: -------------------------------------------------------------------------------- 1 | .markdown{color:#333;font-size:16px;line-height:1.6;}.markdown a{color:#0645ad;text-decoration:none;}.markdown a:visited{color:#0b0080;}.markdown a:hover{color:#06e;}.markdown a:active{color:#faa700;}.markdown a:focus{outline:thin dotted;}.markdown a:hover,.markdown a:active{outline:0;}.markdown p{margin:1em 0;}.markdown img{max-width:100%;}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{color:#111;line-height:1em;margin-top:1.5em;}.markdown h1{margin-top:0;border-bottom:1px solid #ddd;font-size:30px;}.markdown h2{font-size:24px;}.markdown h3{font-size:18px;}.markdown h4{font-size:16px;}.markdown h5{font-size:14px;}.markdown h6{font-size:12px;}.markdown blockquote{color:#666;font-style:italic;margin:0;padding-left:3em;border:none;}.markdown hr{height:4px;padding:0;margin:16px 0;background-color:#e7e7e7;border:0 none;}.markdown code,.markdown pre{font-size:.95em;tab-size:4;overflow-x:auto;overflow-y:hidden;}.markdown pre{white-space:pre-wrap;word-wrap:break-word;}.markdown b,.markdown strong{font-weight:bold;}.markdown ins{background:#ff9;color:#000;text-decoration:none;}.markdown mark{background:#ff0;color:#000;font-style:italic;font-weight:bold;}.markdown sub,.markdown sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}.markdown sup{top:-.5em;}.markdown sub{bottom:-.25em;}.markdown ul,.markdown ol{margin:1em 0;padding:0 0 0 2em;}.markdown li p:last-child{margin:0;}.markdown dd{margin:0 0 0 2em;}.markdown img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;}.markdown table{border:none;border-collapse:collapse;margin-left:1em;margin-right:1em;}.markdown tbody tr{border-bottom:1px solid #ddd;}.markdown th,.markdown td{padding:.5em;}.markdown th{border-bottom:2px solid #ddd;}.markdown td{vertical-align:top;}.markdown svg{display:block;margin-left:auto;margin-right:auto;} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/coding-horror.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #000000; 22 | background: #F8F8F8; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #000000; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #000080; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #008000; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: slategray; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #000000; 56 | background: #ffffe6; 57 | } 58 | pre.csharp .number, 59 | code.csharp .number { 60 | color: #800000; 61 | } 62 | pre.csharp .typename, 63 | code.csharp .typename { 64 | color: #a65300; 65 | } 66 | pre.csharp a, 67 | code.csharp a { 68 | color: inherit; 69 | } 70 | pre.csharp a:visited, 71 | code.csharp a:visited { 72 | color: inherit; 73 | } 74 | pre.csharp a:hover, 75 | code.csharp a:hover { 76 | color: blue; 77 | text-decoration: underline; 78 | } 79 | pre.csharp a:active, 80 | code.csharp a:active { 81 | color: blueviolet; 82 | text-decoration: underline; 83 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/syntax-highlight/solarized-light.css: -------------------------------------------------------------------------------- 1 | .code-block { 2 | -moz-tab-size: 4; 3 | -o-tab-size: 4; 4 | tab-size: 4; 5 | -webkit-hyphens: none; 6 | -moz-hyphens: none; 7 | -ms-hyphens: none; 8 | hyphens: none; 9 | white-space: pre; 10 | word-spacing: normal; 11 | word-break: normal; 12 | word-wrap: normal; 13 | overflow-x: auto; 14 | overflow-y: hidden; 15 | } 16 | .tooltip-inner { 17 | max-width: 1000px; 18 | } 19 | pre.csharp, 20 | code.csharp { 21 | color: #657b83; 22 | background: #fdf6e3; 23 | -moz-tab-size: 4; 24 | -o-tab-size: 4; 25 | tab-size: 4; 26 | -webkit-hyphens: none; 27 | -moz-hyphens: none; 28 | -ms-hyphens: none; 29 | hyphens: none; 30 | white-space: pre; 31 | word-spacing: normal; 32 | word-break: normal; 33 | word-wrap: normal; 34 | overflow-x: auto; 35 | overflow-y: hidden; 36 | } 37 | pre.csharp .punctuation, 38 | code.csharp .punctuation { 39 | color: #719a07; 40 | } 41 | pre.csharp .keyword, 42 | code.csharp .keyword { 43 | color: #859900; 44 | } 45 | pre.csharp .comment, 46 | code.csharp .comment { 47 | color: #93a1a1; 48 | } 49 | pre.csharp .preprocessor, 50 | code.csharp .preprocessor { 51 | color: #cb4b16; 52 | } 53 | pre.csharp .string, 54 | code.csharp .string { 55 | color: #2aa198; 56 | } 57 | pre.csharp .number, 58 | code.csharp .number { 59 | color: #2aa198; 60 | } 61 | pre.csharp .typename, 62 | code.csharp .typename { 63 | color: #b58900; 64 | font-weight: bold; 65 | } 66 | pre.csharp a, 67 | code.csharp a { 68 | color: inherit; 69 | } 70 | pre.csharp a:visited, 71 | code.csharp a:visited { 72 | color: inherit; 73 | } 74 | pre.csharp a:hover, 75 | code.csharp a:hover { 76 | color: blue; 77 | text-decoration: underline; 78 | } 79 | pre.csharp a:active, 80 | code.csharp a:active { 81 | color: blueviolet; 82 | text-decoration: underline; 83 | } -------------------------------------------------------------------------------- /LiterateCS/LiterateCS.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | Exe 6 | true 7 | literatecs 8 | LiterateCS 9 | Tommi Johtela 10 | 11 | Copyright © 2022 Tommi Johtela 12 | Literate programming tool for C#. 13 | https://johtela.github.io/LiterateCS/ 14 | https://johtela.github.io/LiterateCS/License.html 15 | favicon.jpg 16 | https://github.com/johtela/LiterateCS 17 | GitHub 18 | .net csharp literate-programming 19 | true 20 | 2.0.0.0 21 | 2.0.0.0 22 | 2.0.0 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /LiterateCS.Theme/Theme.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Theme Base Class 3 | 4 | Theme assemblies have to include a class which inherits from the Theme class 5 | and implements a few abstract methods. The Theme base class defines the 6 | interface through which the HtmlGenerator class can use the theme. 7 | */ 8 | namespace LiterateCS.Theme 9 | { 10 | using System.IO; 11 | 12 | public abstract class Theme 13 | { 14 | /* 15 | The first property that needs to be implemented returns the list of page 16 | templates available in the theme. A theme can have as many templates 17 | as it likes, but it must define at least one: the default template. The 18 | name of the default template should be "default". 19 | */ 20 | public abstract string[] AvalailablePageTemplates { get; } 21 | /* 22 | The second property that themes must implement is the path to the asset 23 | directory. LiterateCS copies all the assets automatically to the output 24 | directory. If you want to customize this behavior, you can override the 25 | CopyAssets method below. 26 | */ 27 | public abstract string AssetDir { get; } 28 | /* 29 | The third method to implement performs the rendering of the page using 30 | the template specified. The default template is used, if `pageTemplate` 31 | is `null`. Page parameters are set by the HtmlGerenator and passed to 32 | the render method. 33 | */ 34 | public abstract string RenderPage (string pageTemplate, PageParams pageParams); 35 | /* 36 | Theme class provides a default implementation for copying the auxiliary 37 | files needed by the HTML pages. The default implementation copies all the 38 | files under the asseet directory. 39 | */ 40 | public virtual void CopyAssets (string assetDir, string outputDir) 41 | { 42 | DirHelpers.CopySubDirectories (assetDir, outputDir, "*", true); 43 | foreach (var file in DirHelpers.Dir (assetDir, "*", true)) 44 | File.Copy (file, file.Replace (assetDir, outputDir), true); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /DefaultTheme/DefaultTheme.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | TextTemplatingFilePreprocessor 26 | DefaultPage.cs 27 | DefaultTheme 28 | 29 | 30 | TextTemplatingFilePreprocessor 31 | LandingPage.cs 32 | DefaultTheme 33 | 34 | 35 | true 36 | true 37 | PreserveNewest 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | True 48 | True 49 | DefaultPage.tt 50 | 51 | 52 | True 53 | True 54 | LandingPage.tt 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /docs/css/book.min.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Libre+Baskerville:400,400i,700|Roboto+Mono:400,700');.markdown{color:#444;font-family:'Libre Baskerville',serif;font-size:16px;line-height:1.8em;}.markdown a{color:#0645ad;text-decoration:none;}.markdown a:visited{color:#0b0080;}.markdown a:hover{color:#06e;}.markdown a:active{color:#faa700;}.markdown a:focus{outline:thin dotted;}.markdown a:hover,.markdown a:active{outline:0;}.markdown p{margin:1em 0;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;}.markdown img{max-width:100%;}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{font-weight:normal;color:#111;line-height:1em;}.markdown h1{margin-top:0;}.markdown h2,.markdown h3{margin-top:1.5em;border-bottom:.1em #eee solid;}.markdown blockquote{color:#666;font-style:italic;font-size:17px;margin:0 0 0 5%;text-align:justify;border-left:5px solid #ffa258;padding:10px 25px 10px 35px;box-shadow:2px 2px 15px #ccc;background-color:#f9f4ee;max-width:90%;}.markdown blockquote:before{display:block;padding-left:10px;content:"“";font-size:50px;color:#ccc;position:relative;left:-40px;top:20px;height:0;}.markdown hr{display:block;height:2px;border:0;border-top:1px solid #aaa;border-bottom:1px solid #eee;margin:1em 0;padding:0;}.markdown code,.markdown pre{font-family:'Roboto Mono',monospace;font-size:95%;tab-size:4;overflow-x:auto;overflow-y:hidden;hyphens:none;}.markdown pre{white-space:pre-wrap;word-wrap:break-word;}.markdown b,.markdown strong{font-weight:bold;}.markdown ins{background:#ff9;color:#000;text-decoration:none;}.markdown mark{background:#ff0;color:#000;font-style:italic;font-weight:bold;}.markdown sub,.markdown sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}.markdown sup{top:-.5em;}.markdown sub{bottom:-.25em;}.markdown ul,.markdown ol{margin:1em 0;padding:0 0 0 2em;}.markdown li p:last-child{margin:0;}.markdown dd{margin:0 0 0 2em;}.markdown img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;}.markdown table{border:1px #ccc solid;border-collapse:collapse;margin-left:2em;margin-right:2em;}.markdown tbody tr:nth-child(odd){background-color:#f2f2f2;}.markdown th,.markdown td{padding:.5em;border-right:1px #ccc solid;}.markdown th{background-color:#ddd;}.markdown td{vertical-align:top;}.markdown svg{display:block;margin-left:auto;margin-right:auto;} -------------------------------------------------------------------------------- /LiterateCS.Theme/LiterateException.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Reporting Errors 3 | 4 | There are several cases when an exception might be thrown because of invalid input 5 | data or some user-related error. For these cases, we define a custom Exception class. 6 | When thrown, it will be reported differently than the other "unexpected" exceptions 7 | caught in the main program. We try to give as much information as possible about the 8 | error, so that user knows how to fix the problem. 9 | */ 10 | namespace LiterateCS.Theme 11 | { 12 | using System; 13 | using System.Text; 14 | 15 | public class LiterateException : Exception 16 | { 17 | /* 18 | The errors always refer to some file we are processing, so we can define it 19 | as a mandatory field of the exception. 20 | */ 21 | public readonly string FileName; 22 | /* 23 | The other fields that we require are the actual error message, the link to 24 | the documentation that helps the user to understand what the application 25 | expects, and the inner exception which can be null. Inner exception explains 26 | the actual problem; the outer exception gives the context what the application 27 | was doing when it encountered the error. 28 | */ 29 | public LiterateException (string message, string file, string helpLink, 30 | Exception innerException) : base (message, innerException) 31 | { 32 | FileName = file; 33 | HelpLink = helpLink; 34 | } 35 | 36 | public LiterateException (string message, string file, string helpLink) 37 | : this (message, file, helpLink, null) { } 38 | /* 39 | We format the fields of the exception to a readable layout by overriding the 40 | ToString method. 41 | */ 42 | public override string ToString () 43 | { 44 | var res = new StringBuilder (); 45 | res.AppendFormat ("Error occurred while accessing file: {0}\n\n", 46 | FileName); 47 | res.AppendLine ("Description:"); 48 | res.AppendLine ("------------"); 49 | res.AppendLine (Message); 50 | if (InnerException != null) 51 | { 52 | res.AppendLine (); 53 | res.AppendLine ("Detailed Description:"); 54 | res.AppendLine ("---------------------"); 55 | res.AppendLine (InnerException.Message); 56 | } 57 | res.AppendLine (); 58 | res.AppendFormat ("For more information see: {0}", HelpLink); 59 | return res.ToString (); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/book.min.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Libre+Baskerville:400,400i,700|Roboto+Mono:400,700');.markdown{color:#444;font-family:'Libre Baskerville',serif;font-size:16px;line-height:1.8em;}.markdown a{color:#0645ad;text-decoration:none;}.markdown a:visited{color:#0b0080;}.markdown a:hover{color:#06e;}.markdown a:active{color:#faa700;}.markdown a:focus{outline:thin dotted;}.markdown a:hover,.markdown a:active{outline:0;}.markdown p{margin:1em 0;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;}.markdown img{max-width:100%;}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{font-weight:normal;color:#111;line-height:1em;}.markdown h1{margin-top:0;}.markdown h2,.markdown h3{margin-top:1.5em;border-bottom:.1em #eee solid;}.markdown blockquote{color:#666;font-style:italic;font-size:17px;margin:0 0 0 5%;text-align:justify;border-left:5px solid #ffa258;padding:10px 25px 10px 35px;box-shadow:2px 2px 15px #ccc;background-color:#f9f4ee;max-width:90%;}.markdown blockquote:before{display:block;padding-left:10px;content:"“";font-size:50px;color:#ccc;position:relative;left:-40px;top:20px;height:0;}.markdown hr{display:block;height:2px;border:0;border-top:1px solid #aaa;border-bottom:1px solid #eee;margin:1em 0;padding:0;}.markdown code,.markdown pre{font-family:'Roboto Mono',monospace;font-size:95%;tab-size:4;overflow-x:auto;overflow-y:hidden;hyphens:none;}.markdown pre{white-space:pre-wrap;word-wrap:break-word;}.markdown b,.markdown strong{font-weight:bold;}.markdown ins{background:#ff9;color:#000;text-decoration:none;}.markdown mark{background:#ff0;color:#000;font-style:italic;font-weight:bold;}.markdown sub,.markdown sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}.markdown sup{top:-.5em;}.markdown sub{bottom:-.25em;}.markdown ul,.markdown ol{margin:1em 0;padding:0 0 0 2em;}.markdown li p:last-child{margin:0;}.markdown dd{margin:0 0 0 2em;}.markdown img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;}.markdown table{border:1px #ccc solid;border-collapse:collapse;margin-left:2em;margin-right:2em;}.markdown tbody tr:nth-child(odd){background-color:#f2f2f2;}.markdown th,.markdown td{padding:.5em;border-right:1px #ccc solid;}.markdown th{background-color:#ddd;}.markdown td{vertical-align:top;}.markdown svg{display:block;margin-left:auto;margin-right:auto;} -------------------------------------------------------------------------------- /LiterateCS.Theme/DirHelpers.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Directory Utilities 3 | 4 | This class contains utility functions needed by theme assemblies as well as the 5 | LiterateCS tool. It is an assorted collection static functions, mostly related to 6 | directory manipulation, that do not logically belong to any other class. 7 | */ 8 | namespace LiterateCS.Theme 9 | { 10 | using System.IO; 11 | using System.Linq; 12 | 13 | public static class DirHelpers 14 | { 15 | /* 16 | The following method copies all subdirectories of a given input directory 17 | to a target directory. **Note** that it only copies the directory structure, 18 | not the files inside those directories. 19 | 20 | You can specify a glob filter for the input directories. Only directories 21 | with names matching the filter will be copied. If you want all the 22 | directories copied, give `*` as the filter. 23 | 24 | You can also specify with the `recurse` parameter whether the whole 25 | directory tree is copied, or just the top level directories. 26 | */ 27 | public static void CopySubDirectories (string inputRoot, string outputRoot, 28 | string filter, bool recurse) 29 | { 30 | foreach (string subDir in Directory.GetDirectories (inputRoot, filter, 31 | GetSearchOption (recurse))) 32 | EnsureExists (subDir.Replace (inputRoot, outputRoot)); 33 | } 34 | /* 35 | The method below is used to make sure that a given directory exists. Most 36 | of the file operations fail, if a target directory does not exist. 37 | */ 38 | public static void EnsureExists (string dir) 39 | { 40 | if (!Directory.Exists (dir)) 41 | Directory.CreateDirectory (dir); 42 | } 43 | /* 44 | The following methods are just shorthands for GetFiles and Copy methods 45 | defined in the System.IO namespace. They define a more convenient 46 | signature for the wrapped methods. 47 | */ 48 | public static string[] Dir (string path, string filter, bool recurse) => 49 | Directory.GetFiles (path, filter, GetSearchOption (recurse)); 50 | 51 | public static void Copy (string file, string targetFolder, bool overwrite) 52 | { 53 | File.Copy (file, Path.Combine (targetFolder, Path.GetFileName (file)), overwrite); 54 | } 55 | 56 | public static SearchOption GetSearchOption (bool recurse) => 57 | recurse ? 58 | SearchOption.AllDirectories : 59 | SearchOption.TopDirectoryOnly; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /docs/css/modern.min.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:400,700|Roboto+Slab:300,400');.markdown{color:#333;font-family:'Roboto Slab',sans-serif;font-weight:400;font-size:16px;line-height:1.8em;text-align:justify;}.markdown a{color:#0645ad;text-decoration:none;}.markdown a:visited{color:#0b0080;}.markdown a:hover{color:#06e;}.markdown a:active{color:#faa700;}.markdown a:focus{outline:thin dotted;}.markdown a:hover,.markdown a:active{outline:0;}.markdown p{margin:8px;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;}.markdown img{max-width:100%;}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{font-weight:normal;color:#111;line-height:1.1em;text-align:left;clear:right;}.markdown h1{margin-top:0;border-bottom:solid;border-bottom-width:thick;border-bottom-color:#eee;}.markdown h2,.markdown h3{margin-top:1.5em;background-color:#eee;padding:.25em;border-radius:4px;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.19);}.markdown blockquote{color:#444;font-weight:300;text-align:right;margin-left:30%;max-width:70%;padding:1em;border:none;}.markdown hr{display:block;height:2px;border:0;border-top:1px solid #aaa;border-bottom:1px solid #eee;margin:1em 0;padding:0;}.markdown code,.markdown pre{font-family:'Roboto Mono',monospace;background-color:transparent;font-size:98%;tab-size:4;overflow-x:auto;overflow-y:hidden;hyphens:none;}.markdown pre{white-space:pre-wrap;word-wrap:break-word;}.markdown p em{font-style:normal;font-weight:600;}.markdown b,.markdown strong{font-weight:bold;}.markdown ins{background:#ff9;color:#000;text-decoration:none;}.markdown mark{background:#ff0;color:#000;font-style:italic;font-weight:bold;}.markdown sub,.markdown sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}.markdown sup{top:-.5em;}.markdown sub{bottom:-.25em;}.markdown ul,.markdown ol{margin:8px 0;padding:0 3em 0 3em;}.markdown ul{list-style:circle;}.markdown li{padding-left:8px;margin-bottom:8px;}.markdown li p:last-child{margin:0;}.markdown dd{margin:0 0 0 2em;}.markdown img,.markdown svg{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;float:right;margin:0 0 12px 12px;display:block;}.markdown table{border:none;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.19);margin-left:auto;margin-right:auto;}.markdown tbody tr:nth-child(odd){background-color:#eee;}.markdown th,.markdown td{padding:.5em;}.markdown th{color:#fff;background-color:#111;}.markdown td{vertical-align:top;} -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/modern.min.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:400,700|Roboto+Slab:300,400');.markdown{color:#333;font-family:'Roboto Slab',sans-serif;font-weight:400;font-size:16px;line-height:1.8em;text-align:justify;}.markdown a{color:#0645ad;text-decoration:none;}.markdown a:visited{color:#0b0080;}.markdown a:hover{color:#06e;}.markdown a:active{color:#faa700;}.markdown a:focus{outline:thin dotted;}.markdown a:hover,.markdown a:active{outline:0;}.markdown p{margin:8px;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto;}.markdown img{max-width:100%;}.markdown h1,.markdown h2,.markdown h3,.markdown h4,.markdown h5,.markdown h6{font-weight:normal;color:#111;line-height:1.1em;text-align:left;clear:right;}.markdown h1{margin-top:0;border-bottom:solid;border-bottom-width:thick;border-bottom-color:#eee;}.markdown h2,.markdown h3{margin-top:1.5em;background-color:#eee;padding:.25em;border-radius:4px;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.19);}.markdown blockquote{color:#444;font-weight:300;text-align:right;margin-left:30%;max-width:70%;padding:1em;border:none;}.markdown hr{display:block;height:2px;border:0;border-top:1px solid #aaa;border-bottom:1px solid #eee;margin:1em 0;padding:0;}.markdown code,.markdown pre{font-family:'Roboto Mono',monospace;background-color:transparent;font-size:98%;tab-size:4;overflow-x:auto;overflow-y:hidden;hyphens:none;}.markdown pre{white-space:pre-wrap;word-wrap:break-word;}.markdown p em{font-style:normal;font-weight:600;}.markdown b,.markdown strong{font-weight:bold;}.markdown ins{background:#ff9;color:#000;text-decoration:none;}.markdown mark{background:#ff0;color:#000;font-style:italic;font-weight:bold;}.markdown sub,.markdown sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}.markdown sup{top:-.5em;}.markdown sub{bottom:-.25em;}.markdown ul,.markdown ol{margin:8px 0;padding:0 3em 0 3em;}.markdown ul{list-style:circle;}.markdown li{padding-left:8px;margin-bottom:8px;}.markdown li p:last-child{margin:0;}.markdown dd{margin:0 0 0 2em;}.markdown img,.markdown svg{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;float:right;margin:0 0 12px 12px;display:block;}.markdown table{border:none;box-shadow:0 1px 2px 0 rgba(0,0,0,.2),0 1px 5px 0 rgba(0,0,0,.19);margin-left:auto;margin-right:auto;}.markdown tbody tr:nth-child(odd){background-color:#eee;}.markdown th,.markdown td{padding:.5em;}.markdown th{color:#fff;background-color:#111;}.markdown td{vertical-align:top;} -------------------------------------------------------------------------------- /DefaultTheme/include/NavBar.tt: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ import namespace="System.Linq" #> 3 | <#@ import namespace="System.Text" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | 6 | -------------------------------------------------------------------------------- /Installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | LiterateCS runs on top of the [.NET 6]. It is distributed as a [Nuget] package 4 | and deployed as [.NET global tool]. This makes it easy to install, uninstall, and 5 | update. 6 | 7 | ## Prerequisites 8 | 9 | Before installing LiterateCS, make sure that you have **.NET SDK version 6.0 or 10 | newer** installed. If you don't have it already, you can dowload it from 11 | [here][.NET 6]. 12 | 13 | ## Installing 14 | 15 | To install LiterateCS, open a command prompt (PowerShell or classic version) and 16 | type: 17 | 18 | > dotnet tool install -g literatecs 19 | 20 | This downloads the tool from [nuget.org][Nuget] and installs it in the folder 21 | `$HOME/.dotnet/tools/.store/literatecs` by default. It also creates an executable 22 | into `$HOME/.dotnet/tools` that should be already in your search path. 23 | 24 | To verify that LiterateCS is correctly installed you can type: 25 | 26 | > literatecs --help 27 | 28 | This should print the help screen showing the available command line options. 29 | 30 | To see what other global tools you have installed, you can run: 31 | 32 | > dotnet tool list -g 33 | 34 | This shows you all the currently installed .NET core global tools. 35 | 36 | **Note**: Contrary to what the name "global tools" suggests, they are actually 37 | user-specific. They are not visible to other users of the computer. This is 38 | obvious when you know that the installation directory is under the home directory. 39 | 40 | ## Uninstalling 41 | 42 | Uninstallation is easy. Just type: 43 | 44 | > dotnet tool uninstall -g literatecs 45 | 46 | This removes all the files previously installed. 47 | 48 | ## Updating 49 | 50 | Updating to a new version is also a simple matter: 51 | 52 | > dotnet tool update -g literatecs 53 | 54 | This checks for the newer version of the tool in [Nuget] repository and if one is 55 | found, downloads and installs it. 56 | 57 | ## Installing Project Template 58 | 59 | Optionally, you can also install the [project template] for creating C# projects that 60 | readily contain the metadata used by LiterateCS. To install the project template 61 | use the following command: 62 | 63 | > dotnet new -i LiterateCS.Templates.LiterateLib.CSharp 64 | 65 | After that you can create a new literate project with: 66 | 67 | > dotnet new literatelib 68 | 69 | If you don't like the project template, you can uninstall with the `-u` option. 70 | 71 | > dotnet new -u LiterateCS.Templates.LiterateLib.CSharp 72 | 73 | [.NET 6]: https://dotnet.microsoft.com/en-us/download/dotnet/6.0 74 | [Nuget]: https://nuget.org 75 | [.NET global tool]: https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools 76 | [project template]: https://github.com/johtela/LiterateCS.Templates -------------------------------------------------------------------------------- /docs/sidebar/sidebar.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | var navbarHeight = $(".navbar").height(); 3 | $("body").css({ "padding-top": navbarHeight + "px" }); 4 | 5 | var sidebarMainMenu = $('#header-menu ul:first'); 6 | var staticContent = $('#static-content'); 7 | staticContent.find('h1').each(function () { 8 | sidebarMainMenu.append('
  • ' + $(this).html() + '
  • '); 9 | title = sidebarMainMenu.find('#' + $(this).attr('id')); 10 | }); 11 | for (var i = 2; i <= 3; i++) { 12 | addHeaderLevel(i); 13 | } 14 | 15 | function addHeaderLevel (level) 16 | { 17 | staticContent.find('h' + level).each(function () { 18 | prevTitle = sidebarMainMenu.find('#' + $(this) 19 | .prevAll('h' + (level - 1)) 20 | .first() 21 | .attr('id').replace('.', '\\.') + '-menu'); 22 | prevTitle.not(":has(ul)").append(''); 23 | prevTitle.find('.sub-menu').append('
  • ' + $(this).html() + '
  • '); 25 | }); 26 | } 27 | 28 | // Sidebar toggling 29 | var sidebarVisible = "col-sm-4 col-xs-6 sidebar-popup"; 30 | var sidebarHidden = "hidden-sm hidden-xs"; 31 | var closeArrow = "fa-angle-double-left"; 32 | var openArrow = "fa-angle-double-right"; 33 | 34 | function isSidebarOpen() { 35 | return $("#sidebar").hasClass("col-sm-4"); 36 | } 37 | 38 | function closeSidebar() { 39 | $("#sidebar").removeClass(sidebarVisible) 40 | .addClass(sidebarHidden); 41 | $("#sidebar-toggle-icon").removeClass(closeArrow) 42 | .addClass(openArrow); 43 | } 44 | 45 | function openSidebar() { 46 | $("#sidebar").removeClass(sidebarHidden) 47 | .addClass(sidebarVisible); 48 | $("#sidebar-toggle-icon").removeClass(openArrow) 49 | .addClass(closeArrow); 50 | } 51 | 52 | $("#sidebar-toggle").click(function(e) { 53 | e.preventDefault(); 54 | if ($("#sidebar").is(":visible") && !isSidebarOpen()) { 55 | window.scrollTo(0, 0); 56 | } 57 | else if (isSidebarOpen()) { 58 | closeSidebar(); 59 | } 60 | else { 61 | openSidebar(); 62 | window.scrollTo(0, 0); 63 | } 64 | }); 65 | 66 | $(".page-link").click(function (e) { 67 | $(window).bind('hashchange', function (e) { 68 | window.scrollBy(0, -navbarHeight - 8); 69 | $(window).unbind('hashchange'); 70 | }); 71 | if (isSidebarOpen ()) 72 | closeSidebar(); 73 | }); 74 | }); -------------------------------------------------------------------------------- /DefaultTheme/default_assets/sidebar/sidebar.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function () { 2 | var navbarHeight = $(".navbar").height(); 3 | $("body").css({ "padding-top": navbarHeight + "px" }); 4 | 5 | var sidebarMainMenu = $('#header-menu ul:first'); 6 | var staticContent = $('#static-content'); 7 | staticContent.find('h1').each(function () { 8 | sidebarMainMenu.append('
  • ' + $(this).html() + '
  • '); 9 | title = sidebarMainMenu.find('#' + $(this).attr('id')); 10 | }); 11 | for (var i = 2; i <= 3; i++) { 12 | addHeaderLevel(i); 13 | } 14 | 15 | function addHeaderLevel (level) 16 | { 17 | staticContent.find('h' + level).each(function () { 18 | prevTitle = sidebarMainMenu.find('#' + $(this) 19 | .prevAll('h' + (level - 1)) 20 | .first() 21 | .attr('id').replace('.', '\\.') + '-menu'); 22 | prevTitle.not(":has(ul)").append(''); 23 | prevTitle.find('.sub-menu').append('
  • ' + $(this).html() + '
  • '); 25 | }); 26 | } 27 | 28 | // Sidebar toggling 29 | var sidebarVisible = "col-sm-4 col-xs-6 sidebar-popup"; 30 | var sidebarHidden = "hidden-sm hidden-xs"; 31 | var closeArrow = "fa-angle-double-left"; 32 | var openArrow = "fa-angle-double-right"; 33 | 34 | function isSidebarOpen() { 35 | return $("#sidebar").hasClass("col-sm-4"); 36 | } 37 | 38 | function closeSidebar() { 39 | $("#sidebar").removeClass(sidebarVisible) 40 | .addClass(sidebarHidden); 41 | $("#sidebar-toggle-icon").removeClass(closeArrow) 42 | .addClass(openArrow); 43 | } 44 | 45 | function openSidebar() { 46 | $("#sidebar").removeClass(sidebarHidden) 47 | .addClass(sidebarVisible); 48 | $("#sidebar-toggle-icon").removeClass(openArrow) 49 | .addClass(closeArrow); 50 | } 51 | 52 | $("#sidebar-toggle").click(function(e) { 53 | e.preventDefault(); 54 | if ($("#sidebar").is(":visible") && !isSidebarOpen()) { 55 | window.scrollTo(0, 0); 56 | } 57 | else if (isSidebarOpen()) { 58 | closeSidebar(); 59 | } 60 | else { 61 | openSidebar(); 62 | window.scrollTo(0, 0); 63 | } 64 | }); 65 | 66 | $(".page-link").click(function (e) { 67 | $(window).bind('hashchange', function (e) { 68 | window.scrollBy(0, -navbarHeight - 8); 69 | $(window).unbind('hashchange'); 70 | }); 71 | if (isSidebarOpen ()) 72 | closeSidebar(); 73 | }); 74 | }); -------------------------------------------------------------------------------- /LiterateCS/MdWeaver.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Markdown Weaver 3 | 4 | Now we can look at how markdown output is generated. This is the easier of the 5 | two use cases. We only need to split source files into comments and code and 6 | _weave_ the generated blocks to the output files. The splitting part is done 7 | in the [BlockBuilder](BlockBuilder.html) class. The markdown weaver takes the 8 | generated block lists and writes them verbatim to the output files. 9 | */ 10 | namespace LiterateCS 11 | { 12 | using Microsoft.CodeAnalysis; 13 | using System.IO; 14 | 15 | public class MdWeaver : Weaver 16 | { 17 | public MdWeaver (Options options) 18 | : base (options) 19 | { } 20 | /* 21 | ## Generating Output 22 | 23 | The first method to be implemented is to generate documentation from 24 | an input directory. We use the inherited function to enumerate input 25 | files of a specific type. We transform the files by calling the 26 | appropriate `Weave*` function. 27 | */ 28 | protected override void GenerateFromFiles () 29 | { 30 | foreach (var file in SourceFiles ()) 31 | WeaveFromCode (file); 32 | foreach (var file in MarkdownFiles ()) 33 | WeaveFromMarkdown (file); 34 | } 35 | /* 36 | The second options is to use a solution as an input. Again we iterate 37 | markdown and C# source files separately and call the correct method to 38 | transform them to output. 39 | */ 40 | protected override void GenerateFromSolution () 41 | { 42 | foreach (var doc in CSharpDocumentsInSolution ()) 43 | WeaveFromCSharpDocument (doc.Item1, doc.Item2); 44 | foreach (var inputFile in MarkdownFiles ()) 45 | WeaveFromMarkdown (inputFile); 46 | } 47 | /* 48 | ### Weaving the Output 49 | The rest of the code in this class consist of helper functions which 50 | split the input files to blocks and compile the output from them. 51 | Since the blocks already contain valid markdown, no further processing 52 | is needed to transform them. 53 | */ 54 | private void WeaveFromMarkdown (SplitPath mdFile) 55 | { 56 | SplitPath outputFile = CreateOutputPath (mdFile, _options.MarkdownExt); 57 | OutputBlocks (BlockListFromMarkdown (!mdFile), !outputFile); 58 | } 59 | 60 | private void WeaveFromCode (SplitPath codeFile) 61 | { 62 | SplitPath outputFile = CreateOutputPath (codeFile, _options.MarkdownExt); 63 | OutputBlocks (BlockListFromCode (!codeFile), !outputFile); 64 | } 65 | 66 | private void WeaveFromCSharpDocument (SplitPath codeFile, 67 | Document document) 68 | { 69 | SplitPath outputFile = CreateOutputPath (codeFile, _options.MarkdownExt); 70 | OutputBlocks (BlockListFromDocument (document), !outputFile); 71 | } 72 | 73 | private void OutputBlocks (BlockList blocks, string outputFile) 74 | { 75 | using (var writer = File.CreateText (outputFile)) 76 | foreach (var block in blocks) 77 | writer.Write (block.Contents); 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /TableOfContents.md: -------------------------------------------------------------------------------- 1 | # Table of Contents File 2 | 3 | To make it easier for the reader to find a specific topic the pages should 4 | be organized in a logical structure. The structure of the documentation is 5 | defined in the table of contents, or _TOC_, file. This file is used only when 6 | HTML output is selected. Markdown output does not currently utilize the TOC. 7 | 8 | ## File Format 9 | 10 | TOC is stored in a special file called `TOC.yml`. It is defined in [YAML](http://yaml.org/) 11 | format, as is the [front matter](FrontMatter.html). The contents of the file 12 | is laid out in the following way: 13 | 14 | contents: 15 | - page: 16 | file: <relative file path> 17 | desc: <description of the topic> 18 | 19 | - page: <title> 20 | desc: <description of the topic> 21 | subs: 22 | - page: <subtopic title> 23 | file: <relative file path> 24 | desc: <description of the topic> 25 | ... 26 | 27 | - page: <title> 28 | file: <relative file path> 29 | desc: <description of the topic> 30 | ... 31 | 32 | The format is hierarchical. The first keyword is `contents:` under which the 33 | topics are listed. For each topic there is `page:` which contains the title 34 | of the topic. `file:` specifies the relative file path to the source file 35 | that contains the documentation. This information is optional, so it can be 36 | left out, if there is no file associated to the topic. 37 | 38 | `desc:` contains a description string that can be optionally used in the 39 | TOC. This field can also be left out, if it is not needed. 40 | 41 | Subtopics can be added to any level by inserting them under the `subs:` keyword. 42 | Exactly same fields are available to subtopics as for the main level topics. 43 | 44 | ## Example 45 | 46 | Below is an excerpt from the TOC of this project. It serves as an example on 47 | how a TOC file typically looks like: 48 | 49 | contents: 50 | - page: Introduction 51 | file: Index.md 52 | desc: Introduction to literate programming and to the LiterateCS tool. 53 | 54 | - page: Command Line Options 55 | file: src\Options.cs 56 | desc: Lists the available command line options and input parameters. 57 | 58 | - page: Main Program 59 | file: src\Program.cs 60 | desc: Main program that initiates the document generation. 61 | 62 | - page: Themes 63 | desc: Customizing the HTML output. 64 | subs: 65 | - page: Directory Utilities 66 | file: CSWeave.Theme\DirHelpers.cs 67 | desc: Functions that help file/directory management. 68 | 69 | - page: Theme Base Class 70 | file: CSWeave.Theme\Theme.cs 71 | desc: Base class for themes to inherit from. 72 | 73 | - page: Front Matter 74 | file: FrontMatter.md 75 | desc: Defining document metadata. 76 | -------------------------------------------------------------------------------- /docs/css/plain.css: -------------------------------------------------------------------------------- 1 | .markdown { 2 | color: #333; 3 | /*font-family: "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";*/ 4 | font-size: 16px; 5 | line-height: 1.6; 6 | } 7 | .markdown a { 8 | color: #0645ad; 9 | text-decoration: none; 10 | } 11 | .markdown a:visited { 12 | color: #0b0080; 13 | } 14 | .markdown a:hover { 15 | color: #06e; 16 | } 17 | .markdown a:active { 18 | color: #faa700; 19 | } 20 | .markdown a:focus { 21 | outline: thin dotted; 22 | } 23 | .markdown a:hover, 24 | .markdown a:active { 25 | outline: 0; 26 | } 27 | .markdown p { 28 | margin: 1em 0; 29 | } 30 | .markdown img { 31 | max-width: 100%; 32 | } 33 | .markdown h1, 34 | .markdown h2, 35 | .markdown h3, 36 | .markdown h4, 37 | .markdown h5, 38 | .markdown h6 { 39 | color: #111; 40 | line-height: 1em; 41 | margin-top: 1.5em; 42 | } 43 | .markdown h1 { 44 | margin-top: 0; 45 | border-bottom: 1px solid #ddd; 46 | font-size: 30px; 47 | } 48 | .markdown h2 { 49 | font-size: 24px; 50 | } 51 | .markdown h3 { 52 | font-size: 18px; 53 | } 54 | .markdown h4 { 55 | font-size: 16px; 56 | } 57 | .markdown h5 { 58 | font-size: 14px; 59 | } 60 | .markdown h6 { 61 | font-size: 12px; 62 | } 63 | .markdown blockquote { 64 | color: #666666; 65 | font-style: italic; 66 | margin: 0; 67 | padding-left: 3em; 68 | border: none; 69 | } 70 | .markdown hr { 71 | height: 4px; 72 | padding: 0; 73 | margin: 16px 0; 74 | background-color: #e7e7e7; 75 | border: 0 none; 76 | } 77 | .markdown code, 78 | .markdown pre { 79 | /*font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;*/ 80 | font-size: 0.95em; 81 | tab-size: 4; 82 | overflow-x: auto; 83 | overflow-y: hidden; 84 | } 85 | .markdown pre { 86 | white-space: pre-wrap; 87 | word-wrap: break-word; 88 | } 89 | .markdown b, 90 | .markdown strong { 91 | font-weight: bold; 92 | } 93 | .markdown ins { 94 | background: #ff9; 95 | color: #000; 96 | text-decoration: none; 97 | } 98 | .markdown mark { 99 | background: #ff0; 100 | color: #000; 101 | font-style: italic; 102 | font-weight: bold; 103 | } 104 | .markdown sub, 105 | .markdown sup { 106 | font-size: 75%; 107 | line-height: 0; 108 | position: relative; 109 | vertical-align: baseline; 110 | } 111 | .markdown sup { 112 | top: -0.5em; 113 | } 114 | .markdown sub { 115 | bottom: -0.25em; 116 | } 117 | .markdown ul, 118 | .markdown ol { 119 | margin: 1em 0; 120 | padding: 0 0 0 2em; 121 | } 122 | .markdown li p:last-child { 123 | margin: 0; 124 | } 125 | .markdown dd { 126 | margin: 0 0 0 2em; 127 | } 128 | .markdown img { 129 | border: 0; 130 | -ms-interpolation-mode: bicubic; 131 | vertical-align: middle; 132 | } 133 | .markdown table { 134 | border: none; 135 | border-collapse: collapse; 136 | margin-left: 1em; 137 | margin-right: 1em; 138 | } 139 | .markdown tbody tr { 140 | border-bottom: 1px solid #ddd; 141 | } 142 | .markdown th, 143 | .markdown td { 144 | padding: 0.5em; 145 | } 146 | .markdown th { 147 | border-bottom: 2px solid #ddd; 148 | } 149 | .markdown td { 150 | vertical-align: top; 151 | } 152 | .markdown svg { 153 | display: block; 154 | margin-left: auto; 155 | margin-right: auto; 156 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/plain.css: -------------------------------------------------------------------------------- 1 | .markdown { 2 | color: #333; 3 | /*font-family: "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";*/ 4 | font-size: 16px; 5 | line-height: 1.6; 6 | } 7 | .markdown a { 8 | color: #0645ad; 9 | text-decoration: none; 10 | } 11 | .markdown a:visited { 12 | color: #0b0080; 13 | } 14 | .markdown a:hover { 15 | color: #06e; 16 | } 17 | .markdown a:active { 18 | color: #faa700; 19 | } 20 | .markdown a:focus { 21 | outline: thin dotted; 22 | } 23 | .markdown a:hover, 24 | .markdown a:active { 25 | outline: 0; 26 | } 27 | .markdown p { 28 | margin: 1em 0; 29 | } 30 | .markdown img { 31 | max-width: 100%; 32 | } 33 | .markdown h1, 34 | .markdown h2, 35 | .markdown h3, 36 | .markdown h4, 37 | .markdown h5, 38 | .markdown h6 { 39 | color: #111; 40 | line-height: 1em; 41 | margin-top: 1.5em; 42 | } 43 | .markdown h1 { 44 | margin-top: 0; 45 | border-bottom: 1px solid #ddd; 46 | font-size: 30px; 47 | } 48 | .markdown h2 { 49 | font-size: 24px; 50 | } 51 | .markdown h3 { 52 | font-size: 18px; 53 | } 54 | .markdown h4 { 55 | font-size: 16px; 56 | } 57 | .markdown h5 { 58 | font-size: 14px; 59 | } 60 | .markdown h6 { 61 | font-size: 12px; 62 | } 63 | .markdown blockquote { 64 | color: #666666; 65 | font-style: italic; 66 | margin: 0; 67 | padding-left: 3em; 68 | border: none; 69 | } 70 | .markdown hr { 71 | height: 4px; 72 | padding: 0; 73 | margin: 16px 0; 74 | background-color: #e7e7e7; 75 | border: 0 none; 76 | } 77 | .markdown code, 78 | .markdown pre { 79 | /*font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;*/ 80 | font-size: 0.95em; 81 | tab-size: 4; 82 | overflow-x: auto; 83 | overflow-y: hidden; 84 | } 85 | .markdown pre { 86 | white-space: pre-wrap; 87 | word-wrap: break-word; 88 | } 89 | .markdown b, 90 | .markdown strong { 91 | font-weight: bold; 92 | } 93 | .markdown ins { 94 | background: #ff9; 95 | color: #000; 96 | text-decoration: none; 97 | } 98 | .markdown mark { 99 | background: #ff0; 100 | color: #000; 101 | font-style: italic; 102 | font-weight: bold; 103 | } 104 | .markdown sub, 105 | .markdown sup { 106 | font-size: 75%; 107 | line-height: 0; 108 | position: relative; 109 | vertical-align: baseline; 110 | } 111 | .markdown sup { 112 | top: -0.5em; 113 | } 114 | .markdown sub { 115 | bottom: -0.25em; 116 | } 117 | .markdown ul, 118 | .markdown ol { 119 | margin: 1em 0; 120 | padding: 0 0 0 2em; 121 | } 122 | .markdown li p:last-child { 123 | margin: 0; 124 | } 125 | .markdown dd { 126 | margin: 0 0 0 2em; 127 | } 128 | .markdown img { 129 | border: 0; 130 | -ms-interpolation-mode: bicubic; 131 | vertical-align: middle; 132 | } 133 | .markdown table { 134 | border: none; 135 | border-collapse: collapse; 136 | margin-left: 1em; 137 | margin-right: 1em; 138 | } 139 | .markdown tbody tr { 140 | border-bottom: 1px solid #ddd; 141 | } 142 | .markdown th, 143 | .markdown td { 144 | padding: 0.5em; 145 | } 146 | .markdown th { 147 | border-bottom: 2px solid #ddd; 148 | } 149 | .markdown td { 150 | vertical-align: top; 151 | } 152 | .markdown svg { 153 | display: block; 154 | margin-left: auto; 155 | margin-right: auto; 156 | } -------------------------------------------------------------------------------- /TOC.yml: -------------------------------------------------------------------------------- 1 | contents: 2 | - page: Home 3 | file: index.md 4 | desc: Literate programming home page. 5 | 6 | - page: Introduction 7 | file: Introduction.md 8 | desc: Introduction to literate programming and to the LiterateCS tool. 9 | 10 | - page: Command Line Options 11 | file: LiterateCS\Options.cs 12 | desc: Lists the available command line options and input parameters. 13 | 14 | - page: Main Program 15 | file: LiterateCS\Program.cs 16 | desc: Main program that initiates the document generation. 17 | 18 | - page: SplitPath Structure 19 | file: LiterateCS\SplitPath.cs 20 | desc: > 21 | Helper data structure that makes working with file and directory paths 22 | easier. 23 | 24 | - page: Document Weaver 25 | file: LiterateCS\Weaver.cs 26 | desc: Weaver reads the source files and outputs documents based on options. 27 | 28 | - page: Markdown Weaver 29 | file: LiterateCS\MdWeaver.cs 30 | desc: Weaver subclass that outputs Markdown as output. 31 | 32 | - page: HTML Weaver 33 | file: LiterateCS\HtmlWeaver.cs 34 | desc: Weaver subclass that outputs HTML as output. 35 | 36 | - page: TOC Manager 37 | file: LiterateCS\TocManager.cs 38 | desc: "Loads, saves and updates table of contents." 39 | 40 | - page: Source Blocks 41 | file: LiterateCS\BlockList.cs 42 | desc: Data structure that splits a source file into comments and code. 43 | 44 | - page: Macros 45 | file: LiterateCS\Macro.cs 46 | desc: Subsequences of block lists that can be inserted into MD files. 47 | 48 | - page: Block Builder 49 | file: LiterateCS\BlockBuilder.cs 50 | desc: "C# syntax tree walker that will create a block list from a source file." 51 | 52 | - page: HTML Block Builder 53 | file: LiterateCS\HtmlBlockBuilder.cs 54 | desc: Subclass of block builder that enriches code blocks in HTML output. 55 | 56 | - page: HTML Generation 57 | file: LiterateCS\HtmlGenerator.cs 58 | desc: Markdown to HTML generation and template processing. 59 | 60 | - page: Themes 61 | desc: Customizing the HTML output. 62 | subs: 63 | - page: Directory Utilities 64 | file: LiterateCS.Theme\DirHelpers.cs 65 | desc: Functions that help file/directory management. 66 | 67 | - page: Table of Contents Classes 68 | file: LiterateCS.Theme\Toc.cs 69 | desc: Data structure representing the table of contents. 70 | 71 | - page: Page Parameters 72 | file: LiterateCS.Theme\PageParams.cs 73 | desc: Parameters available for a theme when it is rendering a page. 74 | 75 | - page: Theme Base Class 76 | file: LiterateCS.Theme\Theme.cs 77 | desc: Base class for themes to inherit from. 78 | 79 | - page: Reporting Errors 80 | file: LiterateCS.Theme\LiterateException.cs 81 | desc: Exception class for "expected" user errors. 82 | 83 | - page: Front Matter 84 | file: FrontMatter.md 85 | desc: Defining document metadata. 86 | 87 | - page: Table of Contents File 88 | file: TableOfContents.md 89 | desc: Description of the TOC file format. 90 | 91 | - page: "Tips & Tricks" 92 | file: TipsAndTricks.md 93 | desc: How to configure the tool to improve your workflow. 94 | 95 | - page: License 96 | file: License.md 97 | desc: Program license and terms of use. 98 | 99 | - page: README 100 | file: README.md 101 | desc: TODO! Add page description. 102 | 103 | - page: Installation 104 | file: Installation.md 105 | desc: TODO! Add page description. 106 | -------------------------------------------------------------------------------- /LiterateCS/Program.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Main Program 3 | 4 | The main program is very simple. It just parses the command line arguments and calls the 5 | [Weaver](Weaver.html) class that does the actual work. 6 | */ 7 | namespace LiterateCS 8 | { 9 | using System; 10 | using CommandLine; 11 | using LiterateCS.Theme; 12 | 13 | /* 14 | The main class is imaginatively named as `Program`. 15 | */ 16 | class Program 17 | { 18 | static int Main (string[] args) 19 | { 20 | /* 21 | ## Command Line Parsing 22 | First we create a command line parser and configure it to be case 23 | insensitive. 24 | */ 25 | var cmdLineParser = new Parser (settings => 26 | { 27 | settings.CaseSensitive = false; 28 | settings.HelpWriter = Console.Out; 29 | }); 30 | /* 31 | Then we parse the command line options into an object that contains the 32 | settings. We use the settings read from the `defaults.yml` file to 33 | initialize the Options object. 34 | 35 | If the parsing fails, the parser will output usage information 36 | automatically after which we terminate the program with exit code 0. 37 | */ 38 | try 39 | { 40 | var defaultOptions = new Lazy<Options> (Options.LoadFromDefaultsFile); 41 | cmdLineParser.ParseArguments (() => defaultOptions.Value, args) 42 | .WithParsed (GenerateDocumentation); 43 | return 0; 44 | } 45 | catch (LiterateException le) 46 | { 47 | /* 48 | If some parameters are wrong, we get a LiterateException for those errors. 49 | The exception can output itself cleanly by overriding the ToString method. 50 | We exit with error code 1. 51 | */ 52 | Console.ForegroundColor = ConsoleColor.Red; 53 | Console.WriteLine (le); 54 | Console.ResetColor (); 55 | return 1; 56 | } 57 | catch (Exception e) 58 | { 59 | /* 60 | If an unexpected exception is thrown during the process, its error message 61 | is outputted and the program is terminated with an error code 2. 62 | */ 63 | #region Main Error Handler 64 | 65 | Console.ForegroundColor = ConsoleColor.Red; 66 | Console.WriteLine ("Unexpected error in document generation:"); 67 | Console.WriteLine (e.Message); 68 | Console.ResetColor (); 69 | Console.WriteLine (e.StackTrace); 70 | if (e.InnerException != null) 71 | { 72 | Console.WriteLine ("Inner exception:"); 73 | Console.WriteLine (e.InnerException.Message); 74 | Console.WriteLine (e.InnerException.StackTrace); 75 | } 76 | return 2; 77 | /* 78 | _This code block is used as an example on how to embed code into 79 | markdown files._ 80 | */ 81 | #endregion 82 | } 83 | } 84 | /* 85 | ## Generating Documentation 86 | If the parsing succeeds, CommandLineParser library will call the 87 | GenerateDocumentation method with the parsed options. 88 | */ 89 | private static void GenerateDocumentation (Options options) 90 | { 91 | /* 92 | First we output the effective options we are going to use. This helps 93 | the user to see what options were picked form `defaults.yml` file. 94 | */ 95 | options.OutputEffectiveOptions (); 96 | /* 97 | Then we create a [Weaver](Weaver.html) object and call its `Generate` 98 | method to generate the documentation according to the options. 99 | */ 100 | var weaver = options.Format == OutputFormat.html ? 101 | new HtmlWeaver (options) : 102 | (Weaver)new MdWeaver (options); 103 | weaver.GenerateDocumentation (); 104 | } 105 | } 106 | } 107 | /* 108 | That's all! To see how the documentation generation actually works, jump to the 109 | [Weaver](Weaver.html) class. 110 | */ 111 | -------------------------------------------------------------------------------- /docs/css/book.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Libre+Baskerville:400,400i,700|Roboto+Mono:400,700'); 2 | .markdown { 3 | color: #444; 4 | font-family: 'Libre Baskerville', serif; 5 | font-size: 16px; 6 | line-height: 1.8em; 7 | } 8 | .markdown a { 9 | color: #0645ad; 10 | text-decoration: none; 11 | } 12 | .markdown a:visited { 13 | color: #0b0080; 14 | } 15 | .markdown a:hover { 16 | color: #06e; 17 | } 18 | .markdown a:active { 19 | color: #faa700; 20 | } 21 | .markdown a:focus { 22 | outline: thin dotted; 23 | } 24 | .markdown a:hover, 25 | .markdown a:active { 26 | outline: 0; 27 | } 28 | .markdown p { 29 | margin: 1em 0; 30 | -ms-hyphens: auto; 31 | -moz-hyphens: auto; 32 | -webkit-hyphens: auto; 33 | hyphens: auto; 34 | } 35 | .markdown img { 36 | max-width: 100%; 37 | } 38 | .markdown h1, 39 | .markdown h2, 40 | .markdown h3, 41 | .markdown h4, 42 | .markdown h5, 43 | .markdown h6 { 44 | font-weight: normal; 45 | color: #111; 46 | line-height: 1em; 47 | } 48 | .markdown h1 { 49 | margin-top: 0; 50 | } 51 | .markdown h2, 52 | .markdown h3 { 53 | margin-top: 1.5em; 54 | border-bottom: 0.1em #EEE solid; 55 | } 56 | .markdown blockquote { 57 | color: #666; 58 | font-style: italic; 59 | font-size: 17px; 60 | margin: 0 0 0 5%; 61 | text-align: justify; 62 | border-left: 5px solid #ffa258; 63 | padding: 10px 25px 10px 35px; 64 | box-shadow: 2px 2px 15px #ccc; 65 | background-color: #f9f4ee; 66 | max-width: 90%; 67 | } 68 | .markdown blockquote:before { 69 | display: block; 70 | padding-left: 10px; 71 | content: "\201C"; 72 | font-size: 50px; 73 | color: #ccc; 74 | position: relative; 75 | left: -40px; 76 | top: 20px; 77 | height: 0; 78 | } 79 | .markdown hr { 80 | display: block; 81 | height: 2px; 82 | border: 0; 83 | border-top: 1px solid #aaa; 84 | border-bottom: 1px solid #eee; 85 | margin: 1em 0; 86 | padding: 0; 87 | } 88 | .markdown code, 89 | .markdown pre { 90 | font-family: 'Roboto Mono', monospace; 91 | font-size: 95%; 92 | tab-size: 4; 93 | overflow-x: auto; 94 | overflow-y: hidden; 95 | hyphens: none; 96 | } 97 | .markdown pre { 98 | white-space: pre-wrap; 99 | word-wrap: break-word; 100 | } 101 | .markdown b, 102 | .markdown strong { 103 | font-weight: bold; 104 | } 105 | .markdown ins { 106 | background: #ff9; 107 | color: #000; 108 | text-decoration: none; 109 | } 110 | .markdown mark { 111 | background: #ff0; 112 | color: #000; 113 | font-style: italic; 114 | font-weight: bold; 115 | } 116 | .markdown sub, 117 | .markdown sup { 118 | font-size: 75%; 119 | line-height: 0; 120 | position: relative; 121 | vertical-align: baseline; 122 | } 123 | .markdown sup { 124 | top: -0.5em; 125 | } 126 | .markdown sub { 127 | bottom: -0.25em; 128 | } 129 | .markdown ul, 130 | .markdown ol { 131 | margin: 1em 0; 132 | padding: 0 0 0 2em; 133 | } 134 | .markdown li p:last-child { 135 | margin: 0; 136 | } 137 | .markdown dd { 138 | margin: 0 0 0 2em; 139 | } 140 | .markdown img { 141 | border: 0; 142 | -ms-interpolation-mode: bicubic; 143 | vertical-align: middle; 144 | } 145 | .markdown table { 146 | border: 1px #CCC solid; 147 | border-collapse: collapse; 148 | margin-left: 2em; 149 | margin-right: 2em; 150 | } 151 | .markdown tbody tr:nth-child(odd) { 152 | background-color: #f2f2f2; 153 | } 154 | .markdown th, 155 | .markdown td { 156 | padding: 0.5em; 157 | border-right: 1px #CCC solid; 158 | } 159 | .markdown th { 160 | background-color: #DDD; 161 | } 162 | .markdown td { 163 | vertical-align: top; 164 | } 165 | .markdown svg { 166 | display: block; 167 | margin-left: auto; 168 | margin-right: auto; 169 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/book.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Libre+Baskerville:400,400i,700|Roboto+Mono:400,700'); 2 | .markdown { 3 | color: #444; 4 | font-family: 'Libre Baskerville', serif; 5 | font-size: 16px; 6 | line-height: 1.8em; 7 | } 8 | .markdown a { 9 | color: #0645ad; 10 | text-decoration: none; 11 | } 12 | .markdown a:visited { 13 | color: #0b0080; 14 | } 15 | .markdown a:hover { 16 | color: #06e; 17 | } 18 | .markdown a:active { 19 | color: #faa700; 20 | } 21 | .markdown a:focus { 22 | outline: thin dotted; 23 | } 24 | .markdown a:hover, 25 | .markdown a:active { 26 | outline: 0; 27 | } 28 | .markdown p { 29 | margin: 1em 0; 30 | -ms-hyphens: auto; 31 | -moz-hyphens: auto; 32 | -webkit-hyphens: auto; 33 | hyphens: auto; 34 | } 35 | .markdown img { 36 | max-width: 100%; 37 | } 38 | .markdown h1, 39 | .markdown h2, 40 | .markdown h3, 41 | .markdown h4, 42 | .markdown h5, 43 | .markdown h6 { 44 | font-weight: normal; 45 | color: #111; 46 | line-height: 1em; 47 | } 48 | .markdown h1 { 49 | margin-top: 0; 50 | } 51 | .markdown h2, 52 | .markdown h3 { 53 | margin-top: 1.5em; 54 | border-bottom: 0.1em #EEE solid; 55 | } 56 | .markdown blockquote { 57 | color: #666; 58 | font-style: italic; 59 | font-size: 17px; 60 | margin: 0 0 0 5%; 61 | text-align: justify; 62 | border-left: 5px solid #ffa258; 63 | padding: 10px 25px 10px 35px; 64 | box-shadow: 2px 2px 15px #ccc; 65 | background-color: #f9f4ee; 66 | max-width: 90%; 67 | } 68 | .markdown blockquote:before { 69 | display: block; 70 | padding-left: 10px; 71 | content: "\201C"; 72 | font-size: 50px; 73 | color: #ccc; 74 | position: relative; 75 | left: -40px; 76 | top: 20px; 77 | height: 0; 78 | } 79 | .markdown hr { 80 | display: block; 81 | height: 2px; 82 | border: 0; 83 | border-top: 1px solid #aaa; 84 | border-bottom: 1px solid #eee; 85 | margin: 1em 0; 86 | padding: 0; 87 | } 88 | .markdown code, 89 | .markdown pre { 90 | font-family: 'Roboto Mono', monospace; 91 | font-size: 95%; 92 | tab-size: 4; 93 | overflow-x: auto; 94 | overflow-y: hidden; 95 | hyphens: none; 96 | } 97 | .markdown pre { 98 | white-space: pre-wrap; 99 | word-wrap: break-word; 100 | } 101 | .markdown b, 102 | .markdown strong { 103 | font-weight: bold; 104 | } 105 | .markdown ins { 106 | background: #ff9; 107 | color: #000; 108 | text-decoration: none; 109 | } 110 | .markdown mark { 111 | background: #ff0; 112 | color: #000; 113 | font-style: italic; 114 | font-weight: bold; 115 | } 116 | .markdown sub, 117 | .markdown sup { 118 | font-size: 75%; 119 | line-height: 0; 120 | position: relative; 121 | vertical-align: baseline; 122 | } 123 | .markdown sup { 124 | top: -0.5em; 125 | } 126 | .markdown sub { 127 | bottom: -0.25em; 128 | } 129 | .markdown ul, 130 | .markdown ol { 131 | margin: 1em 0; 132 | padding: 0 0 0 2em; 133 | } 134 | .markdown li p:last-child { 135 | margin: 0; 136 | } 137 | .markdown dd { 138 | margin: 0 0 0 2em; 139 | } 140 | .markdown img { 141 | border: 0; 142 | -ms-interpolation-mode: bicubic; 143 | vertical-align: middle; 144 | } 145 | .markdown table { 146 | border: 1px #CCC solid; 147 | border-collapse: collapse; 148 | margin-left: 2em; 149 | margin-right: 2em; 150 | } 151 | .markdown tbody tr:nth-child(odd) { 152 | background-color: #f2f2f2; 153 | } 154 | .markdown th, 155 | .markdown td { 156 | padding: 0.5em; 157 | border-right: 1px #CCC solid; 158 | } 159 | .markdown th { 160 | background-color: #DDD; 161 | } 162 | .markdown td { 163 | vertical-align: top; 164 | } 165 | .markdown svg { 166 | display: block; 167 | margin-left: auto; 168 | margin-right: auto; 169 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/plain.less: -------------------------------------------------------------------------------- 1 | @bordercolor: #ddd; 2 | 3 | .markdown { 4 | color: #333; 5 | /*font-family: "Segoe UI", Arial, freesans, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";*/ 6 | font-size: 16px; 7 | line-height: 1.6; 8 | 9 | a { 10 | color: #0645ad; 11 | text-decoration: none; 12 | 13 | &:visited { 14 | color: #0b0080; 15 | } 16 | 17 | &:hover { 18 | color: #06e; 19 | } 20 | 21 | &:active { 22 | color: #faa700; 23 | } 24 | 25 | &:focus { 26 | outline: thin dotted; 27 | } 28 | 29 | &:hover, &:active { 30 | outline: 0; 31 | } 32 | } 33 | 34 | p { 35 | margin: 1em 0; 36 | } 37 | 38 | img { 39 | max-width: 100%; 40 | } 41 | 42 | h1, h2, h3, h4, h5, h6 { 43 | color: #111; 44 | line-height: 1em; 45 | margin-top: 1.5em; 46 | } 47 | 48 | h1 { 49 | margin-top: 0; 50 | border-bottom: 1px solid @bordercolor; 51 | font-size: 30px; 52 | } 53 | 54 | h2 { 55 | font-size: 24px; 56 | } 57 | 58 | h3 { 59 | font-size: 18px; 60 | } 61 | 62 | h4 { 63 | font-size: 16px; 64 | } 65 | 66 | h5 { 67 | font-size: 14px; 68 | } 69 | 70 | h6 { 71 | font-size: 12px; 72 | } 73 | 74 | blockquote { 75 | color: #666666; 76 | font-style: italic; 77 | margin: 0; 78 | padding-left: 3em; 79 | border: none; 80 | } 81 | 82 | hr { 83 | height: 4px; 84 | padding: 0; 85 | margin: 16px 0; 86 | background-color: #e7e7e7; 87 | border: 0 none; 88 | } 89 | 90 | code, pre { 91 | /*font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;*/ 92 | font-size: 0.95em; 93 | tab-size: 4; 94 | overflow-x: auto; 95 | overflow-y: hidden; 96 | } 97 | 98 | pre { 99 | white-space: pre-wrap; 100 | word-wrap: break-word; 101 | } 102 | 103 | b, strong { 104 | font-weight: bold; 105 | } 106 | 107 | ins { 108 | background: #ff9; 109 | color: #000; 110 | text-decoration: none; 111 | } 112 | 113 | mark { 114 | background: #ff0; 115 | color: #000; 116 | font-style: italic; 117 | font-weight: bold; 118 | } 119 | 120 | sub, sup { 121 | font-size: 75%; 122 | line-height: 0; 123 | position: relative; 124 | vertical-align: baseline; 125 | } 126 | 127 | sup { 128 | top: -0.5em; 129 | } 130 | 131 | sub { 132 | bottom: -0.25em; 133 | } 134 | 135 | ul, ol { 136 | margin: 1em 0; 137 | padding: 0 0 0 2em; 138 | } 139 | 140 | li p:last-child { 141 | margin: 0; 142 | } 143 | 144 | dd { 145 | margin: 0 0 0 2em; 146 | } 147 | 148 | img { 149 | border: 0; 150 | -ms-interpolation-mode: bicubic; 151 | vertical-align: middle; 152 | } 153 | 154 | table { 155 | border: none; 156 | border-collapse: collapse; 157 | margin-left: 1em; 158 | margin-right: 1em; 159 | } 160 | 161 | tbody tr { 162 | border-bottom: 1px solid @bordercolor; 163 | } 164 | 165 | th, td { 166 | padding: 0.5em; 167 | } 168 | 169 | th { 170 | border-bottom: 2px solid @bordercolor; 171 | } 172 | 173 | td { 174 | vertical-align: top; 175 | } 176 | 177 | svg { 178 | display: block; 179 | margin-left: auto; 180 | margin-right: auto; 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /LiterateCS.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27703.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiterateCS.Theme", "LiterateCS.Theme\LiterateCS.Theme.csproj", "{9FD7E951-AAEE-4F36-A09B-395D19D32861}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{2E18EDBB-7E93-4F46-894F-E77C852F09E3}" 9 | ProjectSection(SolutionItems) = preProject 10 | .gitignore = .gitignore 11 | defaults.yml = defaults.yml 12 | FrontMatter.md = FrontMatter.md 13 | index.md = index.md 14 | Installation.md = Installation.md 15 | Introduction.md = Introduction.md 16 | License.md = License.md 17 | README.md = README.md 18 | TableOfContents.md = TableOfContents.md 19 | TestPackage.ps1 = TestPackage.ps1 20 | TipsAndTricks.md = TipsAndTricks.md 21 | TOC.yml = TOC.yml 22 | EndProjectSection 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiterateCS", "LiterateCS\LiterateCS.csproj", "{E164D885-0B71-45B9-A119-A9D9092CB5EF}" 25 | EndProject 26 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{6BE0685D-E844-4BDF-82C8-8A276D753D50}" 27 | EndProject 28 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "images", "images", "{FF495549-4370-4B02-8DDE-E427229E7E74}" 29 | ProjectSection(SolutionItems) = preProject 30 | docs\images\Code.png = docs\images\Code.png 31 | docs\images\Diagram.png = docs\images\Diagram.png 32 | docs\images\favicon.ico = docs\images\favicon.ico 33 | docs\images\FrontMatter.png = docs\images\FrontMatter.png 34 | docs\images\GitHubPages.png = docs\images\GitHubPages.png 35 | docs\images\jumbotron.jpg = docs\images\jumbotron.jpg 36 | docs\images\LiterateLibInVSCode.png = docs\images\LiterateLibInVSCode.png 37 | docs\images\LPFlow.png = docs\images\LPFlow.png 38 | docs\images\Navigation.png = docs\images\Navigation.png 39 | EndProjectSection 40 | EndProject 41 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DefaultTheme", "DefaultTheme\DefaultTheme.csproj", "{001FF036-7669-44BB-BB78-40B62D937916}" 42 | EndProject 43 | Global 44 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 45 | Debug|Any CPU = Debug|Any CPU 46 | Release|Any CPU = Release|Any CPU 47 | EndGlobalSection 48 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 49 | {9FD7E951-AAEE-4F36-A09B-395D19D32861}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 50 | {9FD7E951-AAEE-4F36-A09B-395D19D32861}.Debug|Any CPU.Build.0 = Debug|Any CPU 51 | {9FD7E951-AAEE-4F36-A09B-395D19D32861}.Release|Any CPU.ActiveCfg = Release|Any CPU 52 | {9FD7E951-AAEE-4F36-A09B-395D19D32861}.Release|Any CPU.Build.0 = Release|Any CPU 53 | {E164D885-0B71-45B9-A119-A9D9092CB5EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 54 | {E164D885-0B71-45B9-A119-A9D9092CB5EF}.Debug|Any CPU.Build.0 = Debug|Any CPU 55 | {E164D885-0B71-45B9-A119-A9D9092CB5EF}.Release|Any CPU.ActiveCfg = Release|Any CPU 56 | {E164D885-0B71-45B9-A119-A9D9092CB5EF}.Release|Any CPU.Build.0 = Release|Any CPU 57 | {001FF036-7669-44BB-BB78-40B62D937916}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 58 | {001FF036-7669-44BB-BB78-40B62D937916}.Debug|Any CPU.Build.0 = Debug|Any CPU 59 | {001FF036-7669-44BB-BB78-40B62D937916}.Release|Any CPU.ActiveCfg = Release|Any CPU 60 | {001FF036-7669-44BB-BB78-40B62D937916}.Release|Any CPU.Build.0 = Release|Any CPU 61 | EndGlobalSection 62 | GlobalSection(SolutionProperties) = preSolution 63 | HideSolutionNode = FALSE 64 | EndGlobalSection 65 | GlobalSection(NestedProjects) = preSolution 66 | {FF495549-4370-4B02-8DDE-E427229E7E74} = {6BE0685D-E844-4BDF-82C8-8A276D753D50} 67 | EndGlobalSection 68 | GlobalSection(ExtensibilityGlobals) = postSolution 69 | SolutionGuid = {7BCDA963-6159-43CD-BCFF-FF24FDA22064} 70 | EndGlobalSection 71 | EndGlobal 72 | -------------------------------------------------------------------------------- /docs/css/modern.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:400,700|Roboto+Slab:300,400'); 2 | .markdown { 3 | color: #333; 4 | font-family: 'Roboto Slab', sans-serif; 5 | font-weight: 400; 6 | font-size: 16px; 7 | line-height: 1.8em; 8 | text-align: justify; 9 | } 10 | .markdown a { 11 | color: #0645ad; 12 | text-decoration: none; 13 | } 14 | .markdown a:visited { 15 | color: #0b0080; 16 | } 17 | .markdown a:hover { 18 | color: #06e; 19 | } 20 | .markdown a:active { 21 | color: #faa700; 22 | } 23 | .markdown a:focus { 24 | outline: thin dotted; 25 | } 26 | .markdown a:hover, 27 | .markdown a:active { 28 | outline: 0; 29 | } 30 | .markdown p { 31 | margin: 8px; 32 | -ms-hyphens: auto; 33 | -moz-hyphens: auto; 34 | -webkit-hyphens: auto; 35 | hyphens: auto; 36 | } 37 | .markdown img { 38 | max-width: 100%; 39 | } 40 | .markdown h1, 41 | .markdown h2, 42 | .markdown h3, 43 | .markdown h4, 44 | .markdown h5, 45 | .markdown h6 { 46 | font-weight: normal; 47 | color: #111; 48 | line-height: 1.1em; 49 | text-align: left; 50 | clear: right; 51 | } 52 | .markdown h1 { 53 | margin-top: 0; 54 | border-bottom: solid; 55 | border-bottom-width: thick; 56 | border-bottom-color: #eee; 57 | } 58 | .markdown h2, 59 | .markdown h3 { 60 | margin-top: 1.5em; 61 | background-color: #eee; 62 | padding: 0.25em; 63 | border-radius: 4px; 64 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.19); 65 | } 66 | .markdown blockquote { 67 | color: #444; 68 | font-weight: 300; 69 | text-align: right; 70 | margin-left: 30%; 71 | max-width: 70%; 72 | padding: 1em; 73 | border: none; 74 | } 75 | .markdown hr { 76 | display: block; 77 | height: 2px; 78 | border: 0; 79 | border-top: 1px solid #aaa; 80 | border-bottom: 1px solid #eee; 81 | margin: 1em 0; 82 | padding: 0; 83 | } 84 | .markdown code, 85 | .markdown pre { 86 | font-family: 'Roboto Mono', monospace; 87 | background-color: transparent; 88 | font-size: 98%; 89 | tab-size: 4; 90 | overflow-x: auto; 91 | overflow-y: hidden; 92 | hyphens: none; 93 | } 94 | .markdown pre { 95 | white-space: pre-wrap; 96 | word-wrap: break-word; 97 | } 98 | .markdown p em { 99 | font-style: normal; 100 | font-weight: 600; 101 | } 102 | .markdown b, 103 | .markdown strong { 104 | font-weight: bold; 105 | } 106 | .markdown ins { 107 | background: #ff9; 108 | color: #000; 109 | text-decoration: none; 110 | } 111 | .markdown mark { 112 | background: #ff0; 113 | color: #000; 114 | font-style: italic; 115 | font-weight: bold; 116 | } 117 | .markdown sub, 118 | .markdown sup { 119 | font-size: 75%; 120 | line-height: 0; 121 | position: relative; 122 | vertical-align: baseline; 123 | } 124 | .markdown sup { 125 | top: -0.5em; 126 | } 127 | .markdown sub { 128 | bottom: -0.25em; 129 | } 130 | .markdown ul, 131 | .markdown ol { 132 | margin: 8px 0; 133 | padding: 0 3em 0 3em; 134 | } 135 | .markdown ul { 136 | list-style: circle; 137 | } 138 | .markdown li { 139 | padding-left: 8px; 140 | margin-bottom: 8px; 141 | } 142 | .markdown li p:last-child { 143 | margin: 0; 144 | } 145 | .markdown dd { 146 | margin: 0 0 0 2em; 147 | } 148 | .markdown img, 149 | .markdown svg { 150 | border: 0; 151 | -ms-interpolation-mode: bicubic; 152 | vertical-align: middle; 153 | float: right; 154 | margin: 0 0 12px 12px; 155 | display: block; 156 | } 157 | .markdown table { 158 | border: none; 159 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.19); 160 | margin-left: auto; 161 | margin-right: auto; 162 | } 163 | .markdown tbody tr:nth-child(odd) { 164 | background-color: #eee; 165 | } 166 | .markdown th, 167 | .markdown td { 168 | padding: 0.5em; 169 | } 170 | .markdown th { 171 | color: white; 172 | background-color: #111; 173 | } 174 | .markdown td { 175 | vertical-align: top; 176 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/modern.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:400,700|Roboto+Slab:300,400'); 2 | .markdown { 3 | color: #333; 4 | font-family: 'Roboto Slab', sans-serif; 5 | font-weight: 400; 6 | font-size: 16px; 7 | line-height: 1.8em; 8 | text-align: justify; 9 | } 10 | .markdown a { 11 | color: #0645ad; 12 | text-decoration: none; 13 | } 14 | .markdown a:visited { 15 | color: #0b0080; 16 | } 17 | .markdown a:hover { 18 | color: #06e; 19 | } 20 | .markdown a:active { 21 | color: #faa700; 22 | } 23 | .markdown a:focus { 24 | outline: thin dotted; 25 | } 26 | .markdown a:hover, 27 | .markdown a:active { 28 | outline: 0; 29 | } 30 | .markdown p { 31 | margin: 8px; 32 | -ms-hyphens: auto; 33 | -moz-hyphens: auto; 34 | -webkit-hyphens: auto; 35 | hyphens: auto; 36 | } 37 | .markdown img { 38 | max-width: 100%; 39 | } 40 | .markdown h1, 41 | .markdown h2, 42 | .markdown h3, 43 | .markdown h4, 44 | .markdown h5, 45 | .markdown h6 { 46 | font-weight: normal; 47 | color: #111; 48 | line-height: 1.1em; 49 | text-align: left; 50 | clear: right; 51 | } 52 | .markdown h1 { 53 | margin-top: 0; 54 | border-bottom: solid; 55 | border-bottom-width: thick; 56 | border-bottom-color: #eee; 57 | } 58 | .markdown h2, 59 | .markdown h3 { 60 | margin-top: 1.5em; 61 | background-color: #eee; 62 | padding: 0.25em; 63 | border-radius: 4px; 64 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.19); 65 | } 66 | .markdown blockquote { 67 | color: #444; 68 | font-weight: 300; 69 | text-align: right; 70 | margin-left: 30%; 71 | max-width: 70%; 72 | padding: 1em; 73 | border: none; 74 | } 75 | .markdown hr { 76 | display: block; 77 | height: 2px; 78 | border: 0; 79 | border-top: 1px solid #aaa; 80 | border-bottom: 1px solid #eee; 81 | margin: 1em 0; 82 | padding: 0; 83 | } 84 | .markdown code, 85 | .markdown pre { 86 | font-family: 'Roboto Mono', monospace; 87 | background-color: transparent; 88 | font-size: 98%; 89 | tab-size: 4; 90 | overflow-x: auto; 91 | overflow-y: hidden; 92 | hyphens: none; 93 | } 94 | .markdown pre { 95 | white-space: pre-wrap; 96 | word-wrap: break-word; 97 | } 98 | .markdown p em { 99 | font-style: normal; 100 | font-weight: 600; 101 | } 102 | .markdown b, 103 | .markdown strong { 104 | font-weight: bold; 105 | } 106 | .markdown ins { 107 | background: #ff9; 108 | color: #000; 109 | text-decoration: none; 110 | } 111 | .markdown mark { 112 | background: #ff0; 113 | color: #000; 114 | font-style: italic; 115 | font-weight: bold; 116 | } 117 | .markdown sub, 118 | .markdown sup { 119 | font-size: 75%; 120 | line-height: 0; 121 | position: relative; 122 | vertical-align: baseline; 123 | } 124 | .markdown sup { 125 | top: -0.5em; 126 | } 127 | .markdown sub { 128 | bottom: -0.25em; 129 | } 130 | .markdown ul, 131 | .markdown ol { 132 | margin: 8px 0; 133 | padding: 0 3em 0 3em; 134 | } 135 | .markdown ul { 136 | list-style: circle; 137 | } 138 | .markdown li { 139 | padding-left: 8px; 140 | margin-bottom: 8px; 141 | } 142 | .markdown li p:last-child { 143 | margin: 0; 144 | } 145 | .markdown dd { 146 | margin: 0 0 0 2em; 147 | } 148 | .markdown img, 149 | .markdown svg { 150 | border: 0; 151 | -ms-interpolation-mode: bicubic; 152 | vertical-align: middle; 153 | float: right; 154 | margin: 0 0 12px 12px; 155 | display: block; 156 | } 157 | .markdown table { 158 | border: none; 159 | box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.19); 160 | margin-left: auto; 161 | margin-right: auto; 162 | } 163 | .markdown tbody tr:nth-child(odd) { 164 | background-color: #eee; 165 | } 166 | .markdown th, 167 | .markdown td { 168 | padding: 0.5em; 169 | } 170 | .markdown th { 171 | color: white; 172 | background-color: #111; 173 | } 174 | .markdown td { 175 | vertical-align: top; 176 | } -------------------------------------------------------------------------------- /LiterateCS/Macro.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Macros 3 | 4 | Macros are sequences of blocks that can be inserted inside markdown files. They 5 | correspond to C# [regions](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-region). 6 | To create a macro, a block of code should be surrounded with the `#region` 7 | directive. The name of the region is used as the macro name. Since macro names 8 | should be unique, it is disallowed to have two regions with the same name. 9 | 10 | The Macro class defines the data structure that is used to store macros. It 11 | implements the `IEnumerable<BlockList>` interface to allow iterating though 12 | the blocks belonging to a macro. 13 | */ 14 | namespace LiterateCS 15 | { 16 | using LiterateCS.Theme; 17 | using System; 18 | using System.Collections; 19 | using System.Collections.Generic; 20 | 21 | public class Macro : IEnumerable<BlockList> 22 | { 23 | /* 24 | ## Fields of a Macro 25 | Macros are stored in a linked list in the same way as [BlockList](BlockList.html) 26 | data structures. The only pieces of data we need to store for a macro are 27 | its name, the first block belonging to it `Start`, and the end marker block 28 | `End`. The end marker is the first block that does _not_ belong to the macro. 29 | If the end marker is `null`, then the macro includes all the blocks until 30 | the end of a file. 31 | */ 32 | public string Name { get; private set; } 33 | public BlockList Start { get; set; } 34 | public BlockList End { get; set; } 35 | public string DefinedInFile { get; set; } 36 | /* 37 | Macros are stored in a static dictionary, whose keys are macro names. 38 | */ 39 | private static Dictionary<string, Macro> _macros = 40 | new Dictionary<string, Macro> (); 41 | /* 42 | The constructor is private. Macros should be created with the static 43 | `Add` method. 44 | */ 45 | private Macro (string name, BlockList start, BlockList end, 46 | string definedInFile) 47 | { 48 | Name = name; 49 | Start = start; 50 | End = end; 51 | DefinedInFile = definedInFile; 52 | } 53 | /* 54 | ## IEnumerable Implementation 55 | Iterator is used to implement `IEnumerable<BlockList>` interface. 56 | */ 57 | public IEnumerator<BlockList> GetEnumerator () 58 | { 59 | for (var block = Start; 60 | block != null & block != End; 61 | block = block.Next) 62 | yield return block; 63 | } 64 | 65 | IEnumerator IEnumerable.GetEnumerator () 66 | { 67 | return GetEnumerator (); 68 | } 69 | /* 70 | ## Creating a Macro 71 | The `Add` method is used to create a new macro. The method throws an 72 | exception if a macro with the given name is already registered. 73 | */ 74 | public static Macro Add (string name, BlockList start, BlockList end, 75 | string definedInFile) 76 | { 77 | name = name.Trim (); 78 | if (_macros.TryGetValue (name, out var macro)) 79 | throw new LiterateException ( 80 | string.Format ("Macro '{0}' is already defined in file: {1}\n" + 81 | "You cannot have two macros/regions with the same name.", name, 82 | macro.DefinedInFile), definedInFile, 83 | "https://johtela.github.io/LiterateCS/LiterateCS/Macro.html"); 84 | var result = new Macro (name, start, end, definedInFile); 85 | _macros.Add (name, result); 86 | return result; 87 | } 88 | /* 89 | ## Retrieving a Macro 90 | The `Get` method is used to find and return a macro. It throws 91 | an exception, if a macro with the given name is not found. 92 | */ 93 | public static Macro Get (string name, string usedInFile) 94 | { 95 | name = name.Trim (); 96 | if (!_macros.ContainsKey (name)) 97 | throw new LiterateException (string.Format ( 98 | "Macro '{0}' is not defined. " + 99 | "Make sure you have a region with that name defined in your source\n" + 100 | "file and that you have included it in the input filters.", name), 101 | usedInFile, "https://johtela.github.io/LiterateCS/LiterateCS/Macro.html"); 102 | return _macros[name]; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /LiterateCS.Theme/Toc.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Table of Contents Data Structure 3 | 4 | TOC is provided by the user in a YAML file. When it is read, a data structure 5 | is created that represents the TOC data. This data structure is defined below. 6 | It is a basic hierarchical list structure that consist of nodes that correspond 7 | to sections in the documentation. 8 | */ 9 | namespace LiterateCS.Theme 10 | { 11 | using System.Collections.Generic; 12 | /* 13 | ## Table of Contents Class 14 | 15 | Table of contents has two lists inside it. The first one contains the 16 | top-level sections in a hierarchical structure. The second one is a computed 17 | field that contains the same sections in a flat list. The flattened list 18 | helps us find quickly the previous and next entry for a given section. 19 | */ 20 | public class Toc 21 | { 22 | private List<Section> _contents; 23 | private List<Section> _flattened; 24 | /* 25 | The method that flattens the contents traverses the data structure 26 | recursively and add each section to the flat list. 27 | */ 28 | private void FlattenContents (List<Section> sections, List<Section> flattened) 29 | { 30 | foreach (var section in sections) 31 | { 32 | if (section.File != null) 33 | flattened.Add (section); 34 | if (section.Subs != null) 35 | FlattenContents (section.Subs, flattened); 36 | } 37 | } 38 | /* 39 | The Contents property can be set outside the class. When it is set, 40 | the flattened list is recomputed. The Flattened property is read-only. 41 | */ 42 | public List<Section> Contents 43 | { 44 | get { return _contents; } 45 | set 46 | { 47 | _contents = value; 48 | _flattened = new List<Section> (); 49 | FlattenContents (_contents, _flattened); 50 | } 51 | } 52 | 53 | public List<Section> Flattened 54 | { 55 | get { return _flattened; } 56 | } 57 | /* 58 | When we have the flattened list of topics available, we can find 59 | the next and previous section in the list easily. We by just search for 60 | the index of the section and return the next or previous based on the 61 | index. If we cannot find the section, or we are at the beginning or end 62 | of the list, we return `null`. 63 | */ 64 | public Section NextSection (Section current) 65 | { 66 | var i = _flattened.IndexOf (current); 67 | return i < 0 || i >= _flattened.Count - 1 ? 68 | null : 69 | _flattened[i + 1]; 70 | } 71 | 72 | public Section PreviousSection (Section current) 73 | { 74 | var i = _flattened.IndexOf (current); 75 | return i <= 0 ? null : _flattened[i - 1]; 76 | } 77 | } 78 | /* 79 | ## Section Class 80 | 81 | The Section object represents an individual entry in TOC. There might be a 82 | file that corresponds to the section, but not necessarily. A section can be 83 | used also to logically group pages under a same topic without providing a 84 | separate page for it. In this case you cannot jump to the section, but you 85 | can still see it in TOC. 86 | */ 87 | public class Section 88 | { 89 | /* 90 | The Page property is the title of the section. It is a short string 91 | containing usually the first heading in the file. 92 | */ 93 | public string Page { get; set; } 94 | /* 95 | The relative path to the _source_ file is stored in the File property. 96 | It is naturally unique within TOC. There cannot be two sections pointing 97 | to the same file. It can be `null`, though. As explained above, there 98 | can be sections without files. 99 | */ 100 | public string File { get; set; } 101 | /* 102 | You can provide additional description about the section. This data is 103 | optional and may be omitted when showing the TOC. 104 | */ 105 | public string Desc { get; set; } 106 | /* 107 | Subsections are stored in a list. If there are no subsections under the 108 | current section the property is `null`. 109 | */ 110 | public List<Section> Subs { get; set; } 111 | /* 112 | Custom string conversion is provided mainly for debugging purposes. 113 | */ 114 | public override string ToString () 115 | { 116 | return string.Format ("{0} -> {1}", Page, File); 117 | } 118 | } 119 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status](https://ci.appveyor.com/api/projects/status/ah34q0i74rjanqpf?svg=true)](https://ci.appveyor.com/project/johtela/literatecs) 2 | [![NuGet Version](https://img.shields.io/nuget/v/LiterateCS.svg)](https://www.nuget.org/packages/LiterateCS) 3 | 4 | # Literate Programming in C# and .NET Core 5 | 6 | LiterateCS is a [Literate Programming] tool that produces clear, 7 | professional-looking documentation automatically from your C# projects. 8 | It parses C# code files and extracts [markdown] documentation from 9 | comments. Alternatively you can write your documentation in separate 10 | markdown files and interleave pieces of code in them by referring to 11 | C# regions. LiterateCS can then create either a simple markdown output 12 | that you can upload to your project's [wiki] pages, or it can generate a 13 | full-blown static web site that you can host in [GitHub Pages]. 14 | 15 | The idea of literate programming differs from the usual way of thinking 16 | about technical documentation. Instead of documentation being an afterthough 17 | which is taken care of after the project is done, literate programming encourages 18 | you to document your code while you are writing it. Also, you don't write your 19 | documentation as an API reference like with [xmldoc comments], but rather 20 | like text of an essay, explaining the things that need explaining and skipping 21 | the obvious parts. 22 | 23 | To get an idea about how this works in practice, refer to the literate 24 | documentation created from this project. It can be found at: 25 | 26 | **<https://johtela.github.io/LiterateCS/>** 27 | 28 | Other examples of documentation created with LiterateCS can be found at: 29 | * <https://johtela.github.io/ExtensionCord/> 30 | * <https://johtela.github.io/LinqCheck/> 31 | 32 | ## Quickstart 33 | 34 | To create your first literate program install first the `literatecs` tool 35 | with command line: 36 | 37 | > dotnet tool install -g literatecs 38 | 39 | Then install the project template. 40 | 41 | > dotnet new -i LiterateCS.Templates.LiterateLib.CSharp 42 | 43 | After that create a new directory and the project skeleton. 44 | 45 | > mkdir MyLiteratePony 46 | > cd MyLiteratePony 47 | > dotnet new literatelib 48 | 49 | You should now have files for your class library created. You can 50 | build the project with. 51 | 52 | > dotnet build 53 | 54 | To check what you got, you can open your project in [Visual Studio Code] 55 | (this step is optional). 56 | 57 | > code . 58 | 59 | You should see the following project structure. 60 | 61 | ![...VSCode screenshot...](docs/images/LiterateLibInVSCode.png) 62 | 63 | Finally you can create the documentation from your project with: 64 | 65 | > literatecs 66 | 67 | To see the generated documentation open the `docs/index.html` page in a web browser. 68 | 69 | ![...Generated docs in browser...](docs/images/DocsForLiterateLib.png) 70 | 71 | 72 | ## Download and Installation 73 | 74 | The project was initially written for .NET Framework. Now it targets [.NET 6.0][]. 75 | It is available in <https://nuget.org> as an [.NET Core global tool]. 76 | 77 | See the [installation instructions] for more details. Documentation of the 78 | command line options and usage examples can be found [here][options]. 79 | 80 | ## Bug Reports & Feedback 81 | 82 | If you find a bug or want to suggest a feature, you can submit an [issue]. 83 | 84 | If you want to contribute to the development, let me know. All help is appreciated. 85 | 86 | [Literate Programming]: https://en.wikipedia.org/wiki/Literate_programming 87 | [markdown]: https://en.wikipedia.org/wiki/Markdown 88 | [wiki]: https://help.github.com/articles/about-github-wikis/ 89 | [xmldoc comments]: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/xml-documentation-comments 90 | [GitHub Pages]: https://pages.github.com/ 91 | [Visual Studio Code]: https://code.visualstudio.com/ 92 | [.NET 6.0]: https://dotnet.microsoft.com/en-us/download/dotnet/6.0 93 | [.NET Core global tool]: https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools 94 | [installation instructions]: https://johtela.github.io/LiterateCS/Installation.html 95 | [options]: https://johtela.github.io/LiterateCS/LiterateCS/Options.html 96 | [issue]: https://github.com/johtela/LiterateCS/issues -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | Template: landing 3 | _Jumbotron: > 4 | # Literate Programming in C# 5 | 6 | Produce stylish, interactive documentation for your C# projects using 7 | [literate programming](https://en.wikipedia.org/wiki/Literate_programming). 8 | Write your documentation using [markdown](https://en.wikipedia.org/wiki/Markdown) 9 | and compile it to a fully functional web site that can be published on 10 | [GitHub](https://github.com). 11 | --- 12 | 13 | <div class="row"> 14 | <div class="col-md-6"> 15 | 16 | ## Step 1: Write Your Documentation 17 | 18 | Embed your documentation inside code comments or put it into separate markdown 19 | files. All the formatting features of markdown are available to you. The [Markdig] 20 | library is used to convert the markdown to HTML. It offers a lot of useful extensions 21 | from [MathJax] formulas to [mermaid] diagrams. 22 | 23 | </div> 24 | <div class="col-md-6"> 25 | <p><img src="images/Diagram.png" class="img-responsive center-block" /></p> 26 | </div> 27 | </div> 28 | 29 | <div class="row"> 30 | <div class="col-md-6"> 31 | <p><img src="images/FrontMatter.png" class="img-responsive center-block" /></p> 32 | </div> 33 | <div class="col-md-6"> 34 | 35 | ## Step 2: Customize the Output 36 | 37 | Generate either raw markdown files or standalone, static web sites. Using themes 38 | and styles you can customize the appearance of the pages. Include a [YAML] 39 | front matter in your source files to pass parameters to the site generator. 40 | 41 | </div> 42 | </div> 43 | 44 | <div class="row"> 45 | <div class="col-md-6"> 46 | 47 | ## Step 3: Add Table of Contents 48 | 49 | A table of contents file defines the structure of your documentation. A TOC 50 | file can be automatically generated and updated. The outputted web pages 51 | include a navigation pane and navigation buttons to jump from one page to 52 | another. 53 | 54 | </div> 55 | <div class="col-md-6"> 56 | <p><img src="images/Navigation.png" class="img-responsive center-block" /></p> 57 | </div> 58 | </div> 59 | 60 | <div class="row"> 61 | <div class="col-md-6"> 62 | <p><img src="images/Code.png" class="img-responsive center-block" /></p> 63 | </div> 64 | <div class="col-md-6"> 65 | 66 | ## Step 4: Generate the Documentation 67 | 68 | The documentation "weaver" uses [Roslyn] to parse and analyze your source code. 69 | Syntactic and semantic information provided by Roslyn is used for syntax-highlighting, 70 | and for adding cross-references and type information to the code blocks. You can jump 71 | to the definition of a symbol by clicking it, or inspect its type by hovering over it. 72 | 73 | </div> 74 | </div> 75 | 76 | <div class="row"> 77 | <div class="col-md-6"> 78 | 79 | ## Step 5: Publish Your Docs 80 | 81 | If your code resides under GitHub, you can publish it on [GitHub Pages] by turning on 82 | a single option in the project settings. Just generate your documentation under the 83 | `docs` folder, and switch it on. Done! 84 | 85 | </div> 86 | <div class="col-md-6"> 87 | <p><img src="images/GitHubPages.png" class="img-responsive center-block" /></p> 88 | </div> 89 | </div> 90 | 91 | <div class="row"> 92 | <div class="col-md-3"> 93 | <i class="fa fa-cloud-download fa-5x pull-right"></i> 94 | </div> 95 | <div class="col-md-6"> 96 | 97 | ## Give It a Try! 98 | 99 | The tool targets the [.NET Core] framework, so it works on Windows, Mac, and Linux. 100 | It is distributed as a [NuGet] package and is installed as a [global tool]. Installation 101 | instructions can be found [here](Installation.html). You can also clone the [source repository] 102 | and build the tool from the sources. 103 | 104 | <a class="btn btn-default" href="https://www.nuget.org/packages/LiterateCS/" role="button">Download »</a> 105 | </div> 106 | </div> 107 | 108 | [Markdig]: https://github.com/lunet-io/markdig 109 | [MathJax]: https://www.mathjax.org/ 110 | [mermaid]: https://knsv.github.io/mermaid/ 111 | [YAML]: http://yaml.org/ 112 | [Roslyn]: https://github.com/dotnet/roslyn 113 | [GitHub Pages]: https://pages.github.com/ 114 | [.NET Core]: https://www.microsoft.com/net/learn/get-started/ 115 | [global tool]: https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools 116 | [Nuget]: https://www.nuget.org/ 117 | [source repository]: https://github.com/johtela/LiterateCS -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/book.less: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Libre+Baskerville:400,400i,700|Roboto+Mono:400,700'); 2 | @bordercolor: #EEE; 3 | @darkborder: #CCC; 4 | 5 | .markdown { 6 | color: #444; 7 | font-family: 'Libre Baskerville', serif; 8 | font-size: 16px; 9 | line-height: 1.8em; 10 | 11 | a { 12 | color: #0645ad; 13 | text-decoration: none; 14 | 15 | &:visited { 16 | color: #0b0080; 17 | } 18 | 19 | &:hover { 20 | color: #06e; 21 | } 22 | 23 | &:active { 24 | color: #faa700; 25 | } 26 | 27 | &:focus { 28 | outline: thin dotted; 29 | } 30 | 31 | &:hover, &:active { 32 | outline: 0; 33 | } 34 | } 35 | 36 | p { 37 | margin: 1em 0; 38 | -ms-hyphens: auto; 39 | -moz-hyphens: auto; 40 | -webkit-hyphens: auto; 41 | hyphens: auto; 42 | } 43 | 44 | img { 45 | max-width: 100%; 46 | } 47 | 48 | h1, h2, h3, h4, h5, h6 { 49 | font-weight: normal; 50 | color: #111; 51 | line-height: 1em; 52 | } 53 | 54 | h1 { 55 | margin-top: 0; 56 | } 57 | 58 | h2, h3 { 59 | margin-top: 1.5em; 60 | border-bottom: 0.1em @bordercolor solid; 61 | } 62 | 63 | blockquote { 64 | color: #666; 65 | font-style: italic; 66 | font-size: 17px; 67 | margin: 0 0 0 5%; 68 | text-align: justify; 69 | border-left: 5px solid #ffa258; 70 | padding: 10px 25px 10px 35px; 71 | box-shadow: 2px 2px 15px #ccc; 72 | background-color: #f9f4ee; 73 | max-width: 90%; 74 | 75 | &:before { 76 | display: block; 77 | padding-left: 10px; 78 | content: "\201C"; 79 | font-size: 50px; 80 | color: #ccc; 81 | position: relative; 82 | left: -40px; 83 | top: 20px; 84 | height: 0; 85 | } 86 | } 87 | 88 | hr { 89 | display: block; 90 | height: 2px; 91 | border: 0; 92 | border-top: 1px solid #aaa; 93 | border-bottom: 1px solid #eee; 94 | margin: 1em 0; 95 | padding: 0; 96 | } 97 | 98 | code, pre { 99 | font-family: 'Roboto Mono', monospace; 100 | font-size: 95%; 101 | tab-size: 4; 102 | overflow-x: auto; 103 | overflow-y: hidden; 104 | hyphens: none; 105 | } 106 | 107 | pre { 108 | white-space: pre-wrap; 109 | word-wrap: break-word; 110 | } 111 | 112 | b, strong { 113 | font-weight: bold; 114 | } 115 | 116 | ins { 117 | background: #ff9; 118 | color: #000; 119 | text-decoration: none; 120 | } 121 | 122 | mark { 123 | background: #ff0; 124 | color: #000; 125 | font-style: italic; 126 | font-weight: bold; 127 | } 128 | 129 | sub, sup { 130 | font-size: 75%; 131 | line-height: 0; 132 | position: relative; 133 | vertical-align: baseline; 134 | } 135 | 136 | sup { 137 | top: -0.5em; 138 | } 139 | 140 | sub { 141 | bottom: -0.25em; 142 | } 143 | 144 | ul, ol { 145 | margin: 1em 0; 146 | padding: 0 0 0 2em; 147 | } 148 | 149 | li p:last-child { 150 | margin: 0; 151 | } 152 | 153 | dd { 154 | margin: 0 0 0 2em; 155 | } 156 | 157 | img { 158 | border: 0; 159 | -ms-interpolation-mode: bicubic; 160 | vertical-align: middle; 161 | } 162 | 163 | table { 164 | border: 1px @darkborder solid; 165 | border-collapse: collapse; 166 | margin-left: 2em; 167 | margin-right: 2em; 168 | } 169 | 170 | tbody tr:nth-child(odd) { 171 | background-color: #f2f2f2; 172 | } 173 | 174 | th, td { 175 | padding: 0.5em; 176 | border-right: 1px @darkborder solid; 177 | } 178 | 179 | th { 180 | background-color: #DDD; 181 | } 182 | 183 | td { 184 | vertical-align: top; 185 | } 186 | 187 | svg { 188 | display: block; 189 | margin-left: auto; 190 | margin-right: auto; 191 | } 192 | } -------------------------------------------------------------------------------- /DefaultTheme/default_assets/css/modern.less: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Roboto+Mono:400,700|Roboto+Slab:300,400'); 2 | @heading-color: #eee; 3 | @border-radius: 4px; 4 | @shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.19); 5 | 6 | .markdown { 7 | color: #333; 8 | font-family: 'Roboto Slab', sans-serif; 9 | font-weight: 400; 10 | font-size: 16px; 11 | line-height: 1.8em; 12 | text-align: justify; 13 | 14 | a { 15 | color: #0645ad; 16 | text-decoration: none; 17 | 18 | &:visited { 19 | color: #0b0080; 20 | } 21 | 22 | &:hover { 23 | color: #06e; 24 | } 25 | 26 | &:active { 27 | color: #faa700; 28 | } 29 | 30 | &:focus { 31 | outline: thin dotted; 32 | } 33 | 34 | &:hover, &:active { 35 | outline: 0; 36 | } 37 | } 38 | 39 | p { 40 | margin: 8px; 41 | -ms-hyphens: auto; 42 | -moz-hyphens: auto; 43 | -webkit-hyphens: auto; 44 | hyphens: auto; 45 | } 46 | 47 | img { 48 | max-width: 100%; 49 | } 50 | 51 | h1, h2, h3, h4, h5, h6 { 52 | font-weight: normal; 53 | color: #111; 54 | line-height: 1.1em; 55 | text-align: left; 56 | clear: right; 57 | } 58 | 59 | h1 { 60 | margin-top: 0; 61 | border-bottom: solid; 62 | border-bottom-width: thick; 63 | border-bottom-color: @heading-color; 64 | } 65 | 66 | h2, h3 { 67 | margin-top: 1.5em; 68 | background-color: @heading-color; 69 | padding: 0.25em; 70 | border-radius: @border-radius; 71 | box-shadow: @shadow; 72 | } 73 | 74 | blockquote { 75 | color: #444; 76 | font-weight: 300; 77 | text-align: right; 78 | margin-left: 30%; 79 | max-width: 70%; 80 | padding: 1em; 81 | border: none; 82 | } 83 | 84 | hr { 85 | display: block; 86 | height: 2px; 87 | border: 0; 88 | border-top: 1px solid #aaa; 89 | border-bottom: 1px solid #eee; 90 | margin: 1em 0; 91 | padding: 0; 92 | } 93 | 94 | code, pre { 95 | font-family: 'Roboto Mono', monospace; 96 | background-color: transparent; 97 | font-size: 98%; 98 | tab-size: 4; 99 | overflow-x: auto; 100 | overflow-y: hidden; 101 | hyphens: none; 102 | } 103 | 104 | pre { 105 | white-space: pre-wrap; 106 | word-wrap: break-word; 107 | } 108 | p em { 109 | font-style: normal; 110 | font-weight: 600; 111 | } 112 | b, strong { 113 | font-weight: bold; 114 | } 115 | 116 | ins { 117 | background: #ff9; 118 | color: #000; 119 | text-decoration: none; 120 | } 121 | 122 | mark { 123 | background: #ff0; 124 | color: #000; 125 | font-style: italic; 126 | font-weight: bold; 127 | } 128 | 129 | sub, sup { 130 | font-size: 75%; 131 | line-height: 0; 132 | position: relative; 133 | vertical-align: baseline; 134 | } 135 | 136 | sup { 137 | top: -0.5em; 138 | } 139 | 140 | sub { 141 | bottom: -0.25em; 142 | } 143 | 144 | ul, ol { 145 | margin: 8px 0; 146 | padding: 0 3em 0 3em; 147 | } 148 | 149 | ul { 150 | list-style: circle; 151 | } 152 | 153 | li { 154 | padding-left: 8px; 155 | margin-bottom: 8px; 156 | } 157 | 158 | li p:last-child { 159 | margin: 0; 160 | } 161 | 162 | dd { 163 | margin: 0 0 0 2em; 164 | } 165 | 166 | img, svg { 167 | border: 0; 168 | -ms-interpolation-mode: bicubic; 169 | vertical-align: middle; 170 | float: right; 171 | margin: 0 0 12px 12px; 172 | display: block; 173 | } 174 | 175 | table { 176 | border: none; 177 | box-shadow: @shadow; 178 | margin-left: auto; 179 | margin-right: auto; 180 | } 181 | 182 | tbody tr:nth-child(odd) { 183 | background-color: @heading-color; 184 | } 185 | 186 | th, td { 187 | padding: 0.5em; 188 | } 189 | 190 | th { 191 | color: white; 192 | background-color: #111; 193 | } 194 | 195 | td { 196 | vertical-align: top; 197 | } 198 | } -------------------------------------------------------------------------------- /LiterateCS/HtmlWeaver.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # HTML Weaver 3 | 4 | On high level, weaving source files into web pages resembles the markdown 5 | generation process. The biggest difference is that HTML weaver has to manage 6 | the table of contents when working with input files. Also, two special classes 7 | are used to produce the actual HTML output: 8 | 9 | * [HtmlBlockBuilder](HtmlBlockBuilder.html) which decorates the code blocks 10 | with styling information. 11 | * [HtmlGenerator](HtmlGenerator.html) which converts the markdown to HTML, and loads 12 | the theme assembly, which in turn renders the HTML into a fully functional website. 13 | 14 | But first, let's focus on how the source files are processed when HTML output is 15 | selected. 16 | */ 17 | namespace LiterateCS 18 | { 19 | using Microsoft.CodeAnalysis; 20 | using System.IO; 21 | 22 | public class HtmlWeaver : Weaver 23 | { 24 | /* 25 | ## Initialization 26 | Constructor loads the TOC manager and creates the HTML generator. After that, 27 | it loads the default settings. 28 | */ 29 | private HtmlGenerator _generateHtml; 30 | protected TocManager _tocManager; 31 | 32 | public HtmlWeaver (Options options) 33 | : base (options) 34 | { 35 | LoadToc (); 36 | _generateHtml = new HtmlGenerator (_options, _tocManager.Toc); 37 | LoadDefaultFrontMatter (); 38 | } 39 | /* 40 | A customized version of BlockBuilder is employed by overriding the virtual 41 | method that creates it. 42 | */ 43 | protected override BlockBuilder CreateBlockBuilder () 44 | { 45 | return new HtmlBlockBuilder (_options); 46 | } 47 | /* 48 | Generation methods process the input files and update the TOC while 49 | looping through them. Finally they copy the auxiliary files (CSS, 50 | Javascript, fonts, etc.) that are required by the generated HTML 51 | files. Auxiliary files reside in a theme assembly, and themes are 52 | responsible for copying them to the output folder. The weaver just 53 | invokes the copy method through the HTML generator object. 54 | */ 55 | protected override void GenerateFromFiles () 56 | { 57 | foreach (var file in SourceFiles ()) 58 | { 59 | WeaveFromCodeFile (file); 60 | AddToToc (file); 61 | } 62 | foreach (var file in MarkdownFiles ()) 63 | { 64 | WeaveFromMarkdown (file); 65 | AddToToc (file); 66 | } 67 | ConsoleOut ("Copying auxiliary HTML files..."); 68 | _generateHtml.CopyAuxiliaryFiles (); 69 | _tocManager.Save (); 70 | } 71 | 72 | protected override void GenerateFromSolution () 73 | { 74 | foreach (var doc in CSharpDocumentsInSolution ()) 75 | { 76 | WeaveFromCSharpDocument (doc.Item1, doc.Item2); 77 | AddToToc (doc.Item1); 78 | } 79 | foreach (var inputFile in MarkdownFiles ()) 80 | { 81 | WeaveFromMarkdown (inputFile); 82 | AddToToc (inputFile); 83 | } 84 | ConsoleOut ("Copying auxiliary HTML files..."); 85 | _generateHtml.CopyAuxiliaryFiles (); 86 | _tocManager.Save (); 87 | } 88 | /* 89 | The rest of the methods are helper functions that process a single file 90 | at a time; first they split it to blocks, and then call HTMLGenerator 91 | to convert it to a HTML page. 92 | */ 93 | private void WeaveFromCodeFile (SplitPath codeFile) 94 | { 95 | _generateHtml.Execute (BlockListFromCode (!codeFile), codeFile, 96 | CreateOutputPath (codeFile, ".html")); 97 | } 98 | 99 | private void WeaveFromCSharpDocument (SplitPath codeFile, Document document) 100 | { 101 | _generateHtml.Execute (BlockListFromDocument (document), codeFile, 102 | CreateOutputPath (codeFile, ".html")); 103 | } 104 | 105 | private void WeaveFromMarkdown (SplitPath mdFile) 106 | { 107 | _generateHtml.Execute (BlockListFromMarkdown (!mdFile), mdFile, 108 | CreateOutputPath (mdFile, ".html")); 109 | } 110 | /* 111 | ## Loading Defaults 112 | To load the default front matter we call the `ParseFrontMatter` method in the 113 | HTML generator. 114 | */ 115 | private void LoadDefaultFrontMatter () 116 | { 117 | var defaults = !_options.InputPath.WithFile (Options.DefaultsFile); 118 | if (File.Exists (defaults)) 119 | { 120 | ConsoleOut ("Reading default front matter from '{0}'", defaults); 121 | _generateHtml.ParseFrontMatter (File.ReadAllText (defaults), 122 | defaults); 123 | } 124 | } 125 | /* 126 | ## TOC Management 127 | Loading and updating table of contents is handled by the 128 | [TocManager](TocManager.html) class. We can add new entries to 129 | TOC using the `AddToToc`method. Updating is performed only, if 130 | `-u` switch is specified in the options. 131 | */ 132 | private void LoadToc () 133 | { 134 | var tocFile = !_options.InputPath.WithFile (Options.TocFile); 135 | if (File.Exists (tocFile)) 136 | { 137 | ConsoleOut ("Reading TOC from file '{0}'", tocFile); 138 | _tocManager = TocManager.Load (tocFile); 139 | } 140 | else 141 | _tocManager = new TocManager (); 142 | } 143 | 144 | private void AddToToc (SplitPath path) 145 | { 146 | if (_options.UpdateToc) 147 | _tocManager.AddToToc (path); 148 | } 149 | } 150 | } -------------------------------------------------------------------------------- /LiterateCS.Theme/PageParams.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Page Parameters 3 | 4 | All the data LiterateCS will pass to the theme is contained inside a 5 | PageParams object. This class defines the built-in parameters that are 6 | always available, and the custom parameters specified in front matter. 7 | */ 8 | namespace LiterateCS.Theme 9 | { 10 | using System.Collections.Generic; 11 | using System.IO; 12 | 13 | public class PageParams 14 | { 15 | /* 16 | ## Custom Parameters 17 | 18 | You can specify any parameters inside front matter. How these will 19 | be used is up to the theme. The parameters are simple key-value pairs 20 | with string both as the key and value type. The parameters are stored 21 | in a dictionary that is initialized when a PageParams object is created. 22 | */ 23 | private Dictionary<string, string> _parameters; 24 | 25 | public PageParams () 26 | { 27 | _parameters = new Dictionary<string, string> (); 28 | } 29 | /* 30 | The parameters are converted to lowercase before they are added to the 31 | dictionary. Parameter names are case-insensitive, so we need to do this 32 | in all the methods accessing the dictionary. If a parameter with the 33 | same name already exists in the dictionary, its value is updated. 34 | */ 35 | public void Add (string name, string value) 36 | { 37 | name = name.ToLower (); 38 | if (_parameters.ContainsKey (name)) 39 | _parameters[name] = value; 40 | else 41 | _parameters.Add (name, value); 42 | } 43 | /* 44 | Removing a parameter is also possible, although themes should not 45 | generally do so. 46 | */ 47 | public void Remove (string name) 48 | { 49 | _parameters.Remove (name.ToLower ()); 50 | } 51 | /* 52 | Two indexer methods can be used to access the custom parameters. The 53 | first one takes two arguments: name and default value. If a parameter 54 | with a given name is not found, the default value is returned. 55 | */ 56 | public string this[string name, string defaultValue] 57 | { 58 | get 59 | { 60 | return _parameters.TryGetValue (name.ToLower (), out string result) ? 61 | result : defaultValue; 62 | } 63 | } 64 | /* 65 | The second version takes just name of the parameter, and returns it back, 66 | if the parameter is not found. 67 | */ 68 | public string this[string name] => 69 | this[name, name]; 70 | /* 71 | ## Built-in Properties 72 | 73 | The rest of the properties defined in the PageParams class are updated 74 | for each generated page. These are page-level parameters which are always 75 | available. 76 | 77 | The Root property gives the relative path from the page location to the 78 | root directory of the website. For example, if the page we are generating 79 | resides under directory `source\code\`, then Root would contain path 80 | `..\..\`. Say you want to add a link to another page which resides under 81 | directory `doc\`. Now you can to refer to it by adding the value of the 82 | Root property at the beginning of the path. The resulting path would be 83 | `..\..\doc\`. 84 | 85 | So, the Root property allows us to create relative links between pages 86 | that work regardless of where the site resides on disk. This is 87 | quite handy since now the links work correctly when pages are viewed 88 | locally from disk as well as when they are accessed from a web server. 89 | */ 90 | public string Root { get; set; } 91 | /* 92 | The name of the currently processed file is stored in the property 93 | below. The name does not include a file extension. 94 | */ 95 | public string Filename { get; set; } 96 | /* 97 | Perhaps the most important data passed to the theme is the contents 98 | of the page which is provided in the property below. The property 99 | contains the documentation extracted from the source file in HTML 100 | format. Typically the theme will just insert this in the appropriate 101 | place on a page. 102 | */ 103 | public string Contents { get; set; } 104 | /* 105 | ### TOC Related Properties 106 | 107 | The table of contents object is accessible through the Toc property. 108 | This object is always initialized, even when the user does not provide 109 | a TOC file. In that case the TOC is empty, and there are no sections 110 | in it. 111 | */ 112 | public Toc Toc { get; set; } 113 | /* 114 | When a TOC file is provided, and the current page can be found in it, 115 | then the following property contains a reference to the Section object 116 | we are on currently. This information can be used to highlight which 117 | section in the TOC we are viewing. 118 | */ 119 | public Section CurrentSection { get; set; } 120 | /* 121 | The SectionPath helper function returns the relative path to section in 122 | the TOC from the current page. It is handy in generating links to TOC. 123 | The method also changes the source file path to a relative URL by 124 | changing the extension to "html" and replacing backslashes with 125 | forward slashes. 126 | */ 127 | public string SectionPath (Section entry) => 128 | entry.File == null ? 129 | null : 130 | Path.Combine (Root, Path.ChangeExtension (entry.File, "html")) 131 | .Replace ('\\', '/'); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /docs/mermaid/mermaid.css: -------------------------------------------------------------------------------- 1 | /* Flowchart variables */ 2 | /* Sequence Diagram variables */ 3 | /* Gantt chart variables */ 4 | .mermaid .label { 5 | color: #333; 6 | } 7 | .node rect, 8 | .node circle, 9 | .node ellipse, 10 | .node polygon { 11 | fill: #ECECFF; 12 | stroke: #CCCCFF; 13 | stroke-width: 1px; 14 | } 15 | .edgePath .path { 16 | stroke: #333333; 17 | } 18 | .edgeLabel { 19 | background-color: #e8e8e8; 20 | } 21 | .cluster rect { 22 | fill: #ffffde !important; 23 | rx: 4 !important; 24 | stroke: #aaaa33 !important; 25 | stroke-width: 1px !important; 26 | } 27 | .cluster text { 28 | fill: #333; 29 | } 30 | .actor { 31 | stroke: #CCCCFF; 32 | fill: #ECECFF; 33 | } 34 | text.actor { 35 | fill: black; 36 | stroke: none; 37 | } 38 | .actor-line { 39 | stroke: grey; 40 | } 41 | .messageLine0 { 42 | stroke-width: 1.5; 43 | stroke-dasharray: "2 2"; 44 | marker-end: "url(#arrowhead)"; 45 | stroke: #333; 46 | } 47 | .messageLine1 { 48 | stroke-width: 1.5; 49 | stroke-dasharray: "2 2"; 50 | stroke: #333; 51 | } 52 | #arrowhead { 53 | fill: #333; 54 | } 55 | #crosshead path { 56 | fill: #333 !important; 57 | stroke: #333 !important; 58 | } 59 | .messageText { 60 | fill: #333; 61 | stroke: none; 62 | } 63 | .labelBox { 64 | stroke: #CCCCFF; 65 | fill: #ECECFF; 66 | } 67 | .labelText { 68 | fill: black; 69 | stroke: none; 70 | } 71 | .loopText { 72 | fill: black; 73 | stroke: none; 74 | } 75 | .loopLine { 76 | stroke-width: 2; 77 | stroke-dasharray: "2 2"; 78 | marker-end: "url(#arrowhead)"; 79 | stroke: #CCCCFF; 80 | } 81 | .note { 82 | stroke: #aaaa33; 83 | fill: #fff5ad; 84 | } 85 | .noteText { 86 | fill: black; 87 | stroke: none; 88 | font-family: 'trebuchet ms', verdana, arial; 89 | font-size: 14px; 90 | } 91 | /** Section styling */ 92 | .section { 93 | stroke: none; 94 | opacity: 0.2; 95 | } 96 | .section0 { 97 | fill: rgba(102, 102, 255, 0.49); 98 | } 99 | .section2 { 100 | fill: #fff400; 101 | } 102 | .section1, 103 | .section3 { 104 | fill: white; 105 | opacity: 0.2; 106 | } 107 | .sectionTitle0 { 108 | fill: #333; 109 | } 110 | .sectionTitle1 { 111 | fill: #333; 112 | } 113 | .sectionTitle2 { 114 | fill: #333; 115 | } 116 | .sectionTitle3 { 117 | fill: #333; 118 | } 119 | .sectionTitle { 120 | text-anchor: start; 121 | font-size: 11px; 122 | text-height: 14px; 123 | } 124 | /* Grid and axis */ 125 | .grid .tick { 126 | stroke: lightgrey; 127 | opacity: 0.3; 128 | shape-rendering: crispEdges; 129 | } 130 | .grid path { 131 | stroke-width: 0; 132 | } 133 | /* Today line */ 134 | .today { 135 | fill: none; 136 | stroke: red; 137 | stroke-width: 2px; 138 | } 139 | /* Task styling */ 140 | /* Default task */ 141 | .task { 142 | stroke-width: 2; 143 | } 144 | .taskText { 145 | text-anchor: middle; 146 | font-size: 11px; 147 | } 148 | .taskTextOutsideRight { 149 | fill: black; 150 | text-anchor: start; 151 | font-size: 11px; 152 | } 153 | .taskTextOutsideLeft { 154 | fill: black; 155 | text-anchor: end; 156 | font-size: 11px; 157 | } 158 | /* Specific task settings for the sections*/ 159 | .taskText0, 160 | .taskText1, 161 | .taskText2, 162 | .taskText3 { 163 | fill: white; 164 | } 165 | .task0, 166 | .task1, 167 | .task2, 168 | .task3 { 169 | fill: #8a90dd; 170 | stroke: #534fbc; 171 | } 172 | .taskTextOutside0, 173 | .taskTextOutside2 { 174 | fill: black; 175 | } 176 | .taskTextOutside1, 177 | .taskTextOutside3 { 178 | fill: black; 179 | } 180 | /* Active task */ 181 | .active0, 182 | .active1, 183 | .active2, 184 | .active3 { 185 | fill: #bfc7ff; 186 | stroke: #534fbc; 187 | } 188 | .activeText0, 189 | .activeText1, 190 | .activeText2, 191 | .activeText3 { 192 | fill: black !important; 193 | } 194 | /* Completed task */ 195 | .done0, 196 | .done1, 197 | .done2, 198 | .done3 { 199 | stroke: grey; 200 | fill: lightgrey; 201 | stroke-width: 2; 202 | } 203 | .doneText0, 204 | .doneText1, 205 | .doneText2, 206 | .doneText3 { 207 | fill: black !important; 208 | } 209 | /* Tasks on the critical line */ 210 | .crit0, 211 | .crit1, 212 | .crit2, 213 | .crit3 { 214 | stroke: #ff8888; 215 | fill: red; 216 | stroke-width: 2; 217 | } 218 | .activeCrit0, 219 | .activeCrit1, 220 | .activeCrit2, 221 | .activeCrit3 { 222 | stroke: #ff8888; 223 | fill: #bfc7ff; 224 | stroke-width: 2; 225 | } 226 | .doneCrit0, 227 | .doneCrit1, 228 | .doneCrit2, 229 | .doneCrit3 { 230 | stroke: #ff8888; 231 | fill: lightgrey; 232 | stroke-width: 2; 233 | cursor: pointer; 234 | shape-rendering: crispEdges; 235 | } 236 | .doneCritText0, 237 | .doneCritText1, 238 | .doneCritText2, 239 | .doneCritText3 { 240 | fill: black !important; 241 | } 242 | .activeCritText0, 243 | .activeCritText1, 244 | .activeCritText2, 245 | .activeCritText3 { 246 | fill: black !important; 247 | } 248 | .titleText { 249 | text-anchor: middle; 250 | font-size: 18px; 251 | fill: black; 252 | } 253 | /* 254 | 255 | 256 | */ 257 | .node text { 258 | font-family: 'trebuchet ms', verdana, arial; 259 | font-size: 14px; 260 | } 261 | div.mermaidTooltip { 262 | position: absolute; 263 | text-align: center; 264 | max-width: 200px; 265 | padding: 2px; 266 | font-family: 'trebuchet ms', verdana, arial; 267 | font-size: 12px; 268 | background: #ffffde; 269 | border: 1px solid #aaaa33; 270 | border-radius: 2px; 271 | pointer-events: none; 272 | z-index: 100; 273 | } 274 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/mermaid/mermaid.css: -------------------------------------------------------------------------------- 1 | /* Flowchart variables */ 2 | /* Sequence Diagram variables */ 3 | /* Gantt chart variables */ 4 | .mermaid .label { 5 | color: #333; 6 | } 7 | .node rect, 8 | .node circle, 9 | .node ellipse, 10 | .node polygon { 11 | fill: #ECECFF; 12 | stroke: #CCCCFF; 13 | stroke-width: 1px; 14 | } 15 | .edgePath .path { 16 | stroke: #333333; 17 | } 18 | .edgeLabel { 19 | background-color: #e8e8e8; 20 | } 21 | .cluster rect { 22 | fill: #ffffde !important; 23 | rx: 4 !important; 24 | stroke: #aaaa33 !important; 25 | stroke-width: 1px !important; 26 | } 27 | .cluster text { 28 | fill: #333; 29 | } 30 | .actor { 31 | stroke: #CCCCFF; 32 | fill: #ECECFF; 33 | } 34 | text.actor { 35 | fill: black; 36 | stroke: none; 37 | } 38 | .actor-line { 39 | stroke: grey; 40 | } 41 | .messageLine0 { 42 | stroke-width: 1.5; 43 | stroke-dasharray: "2 2"; 44 | marker-end: "url(#arrowhead)"; 45 | stroke: #333; 46 | } 47 | .messageLine1 { 48 | stroke-width: 1.5; 49 | stroke-dasharray: "2 2"; 50 | stroke: #333; 51 | } 52 | #arrowhead { 53 | fill: #333; 54 | } 55 | #crosshead path { 56 | fill: #333 !important; 57 | stroke: #333 !important; 58 | } 59 | .messageText { 60 | fill: #333; 61 | stroke: none; 62 | } 63 | .labelBox { 64 | stroke: #CCCCFF; 65 | fill: #ECECFF; 66 | } 67 | .labelText { 68 | fill: black; 69 | stroke: none; 70 | } 71 | .loopText { 72 | fill: black; 73 | stroke: none; 74 | } 75 | .loopLine { 76 | stroke-width: 2; 77 | stroke-dasharray: "2 2"; 78 | marker-end: "url(#arrowhead)"; 79 | stroke: #CCCCFF; 80 | } 81 | .note { 82 | stroke: #aaaa33; 83 | fill: #fff5ad; 84 | } 85 | .noteText { 86 | fill: black; 87 | stroke: none; 88 | font-family: 'trebuchet ms', verdana, arial; 89 | font-size: 14px; 90 | } 91 | /** Section styling */ 92 | .section { 93 | stroke: none; 94 | opacity: 0.2; 95 | } 96 | .section0 { 97 | fill: rgba(102, 102, 255, 0.49); 98 | } 99 | .section2 { 100 | fill: #fff400; 101 | } 102 | .section1, 103 | .section3 { 104 | fill: white; 105 | opacity: 0.2; 106 | } 107 | .sectionTitle0 { 108 | fill: #333; 109 | } 110 | .sectionTitle1 { 111 | fill: #333; 112 | } 113 | .sectionTitle2 { 114 | fill: #333; 115 | } 116 | .sectionTitle3 { 117 | fill: #333; 118 | } 119 | .sectionTitle { 120 | text-anchor: start; 121 | font-size: 11px; 122 | text-height: 14px; 123 | } 124 | /* Grid and axis */ 125 | .grid .tick { 126 | stroke: lightgrey; 127 | opacity: 0.3; 128 | shape-rendering: crispEdges; 129 | } 130 | .grid path { 131 | stroke-width: 0; 132 | } 133 | /* Today line */ 134 | .today { 135 | fill: none; 136 | stroke: red; 137 | stroke-width: 2px; 138 | } 139 | /* Task styling */ 140 | /* Default task */ 141 | .task { 142 | stroke-width: 2; 143 | } 144 | .taskText { 145 | text-anchor: middle; 146 | font-size: 11px; 147 | } 148 | .taskTextOutsideRight { 149 | fill: black; 150 | text-anchor: start; 151 | font-size: 11px; 152 | } 153 | .taskTextOutsideLeft { 154 | fill: black; 155 | text-anchor: end; 156 | font-size: 11px; 157 | } 158 | /* Specific task settings for the sections*/ 159 | .taskText0, 160 | .taskText1, 161 | .taskText2, 162 | .taskText3 { 163 | fill: white; 164 | } 165 | .task0, 166 | .task1, 167 | .task2, 168 | .task3 { 169 | fill: #8a90dd; 170 | stroke: #534fbc; 171 | } 172 | .taskTextOutside0, 173 | .taskTextOutside2 { 174 | fill: black; 175 | } 176 | .taskTextOutside1, 177 | .taskTextOutside3 { 178 | fill: black; 179 | } 180 | /* Active task */ 181 | .active0, 182 | .active1, 183 | .active2, 184 | .active3 { 185 | fill: #bfc7ff; 186 | stroke: #534fbc; 187 | } 188 | .activeText0, 189 | .activeText1, 190 | .activeText2, 191 | .activeText3 { 192 | fill: black !important; 193 | } 194 | /* Completed task */ 195 | .done0, 196 | .done1, 197 | .done2, 198 | .done3 { 199 | stroke: grey; 200 | fill: lightgrey; 201 | stroke-width: 2; 202 | } 203 | .doneText0, 204 | .doneText1, 205 | .doneText2, 206 | .doneText3 { 207 | fill: black !important; 208 | } 209 | /* Tasks on the critical line */ 210 | .crit0, 211 | .crit1, 212 | .crit2, 213 | .crit3 { 214 | stroke: #ff8888; 215 | fill: red; 216 | stroke-width: 2; 217 | } 218 | .activeCrit0, 219 | .activeCrit1, 220 | .activeCrit2, 221 | .activeCrit3 { 222 | stroke: #ff8888; 223 | fill: #bfc7ff; 224 | stroke-width: 2; 225 | } 226 | .doneCrit0, 227 | .doneCrit1, 228 | .doneCrit2, 229 | .doneCrit3 { 230 | stroke: #ff8888; 231 | fill: lightgrey; 232 | stroke-width: 2; 233 | cursor: pointer; 234 | shape-rendering: crispEdges; 235 | } 236 | .doneCritText0, 237 | .doneCritText1, 238 | .doneCritText2, 239 | .doneCritText3 { 240 | fill: black !important; 241 | } 242 | .activeCritText0, 243 | .activeCritText1, 244 | .activeCritText2, 245 | .activeCritText3 { 246 | fill: black !important; 247 | } 248 | .titleText { 249 | text-anchor: middle; 250 | font-size: 18px; 251 | fill: black; 252 | } 253 | /* 254 | 255 | 256 | */ 257 | .node text { 258 | font-family: 'trebuchet ms', verdana, arial; 259 | font-size: 14px; 260 | } 261 | div.mermaidTooltip { 262 | position: absolute; 263 | text-align: center; 264 | max-width: 200px; 265 | padding: 2px; 266 | font-family: 'trebuchet ms', verdana, arial; 267 | font-size: 12px; 268 | background: #ffffde; 269 | border: 1px solid #aaaa33; 270 | border-radius: 2px; 271 | pointer-events: none; 272 | z-index: 100; 273 | } 274 | -------------------------------------------------------------------------------- /docs/mermaid/mermaid.dark.css: -------------------------------------------------------------------------------- 1 | /* Flowchart variables */ 2 | /* Sequence Diagram variables */ 3 | /* Gantt chart variables */ 4 | .mermaid .label { 5 | color: #323D47; 6 | } 7 | .node rect, 8 | .node circle, 9 | .node ellipse, 10 | .node polygon { 11 | fill: #BDD5EA; 12 | stroke: #81B1DB; 13 | stroke-width: 1px; 14 | } 15 | .edgePath .path { 16 | stroke: lightgrey; 17 | } 18 | .edgeLabel { 19 | background-color: #e8e8e8; 20 | } 21 | .cluster rect { 22 | fill: #6D6D65 !important; 23 | rx: 4 !important; 24 | stroke: rgba(255, 255, 255, 0.25) !important; 25 | stroke-width: 1px !important; 26 | } 27 | .cluster text { 28 | fill: #F9FFFE; 29 | } 30 | .actor { 31 | stroke: #81B1DB; 32 | fill: #BDD5EA; 33 | } 34 | text.actor { 35 | fill: black; 36 | stroke: none; 37 | } 38 | .actor-line { 39 | stroke: lightgrey; 40 | } 41 | .messageLine0 { 42 | stroke-width: 1.5; 43 | stroke-dasharray: "2 2"; 44 | marker-end: "url(#arrowhead)"; 45 | stroke: lightgrey; 46 | } 47 | .messageLine1 { 48 | stroke-width: 1.5; 49 | stroke-dasharray: "2 2"; 50 | stroke: lightgrey; 51 | } 52 | #arrowhead { 53 | fill: lightgrey !important; 54 | } 55 | #crosshead path { 56 | fill: lightgrey !important; 57 | stroke: lightgrey !important; 58 | } 59 | .messageText { 60 | fill: lightgrey; 61 | stroke: none; 62 | } 63 | .labelBox { 64 | stroke: #81B1DB; 65 | fill: #BDD5EA; 66 | } 67 | .labelText { 68 | fill: #323D47; 69 | stroke: none; 70 | } 71 | .loopText { 72 | fill: lightgrey; 73 | stroke: none; 74 | } 75 | .loopLine { 76 | stroke-width: 2; 77 | stroke-dasharray: "2 2"; 78 | marker-end: "url(#arrowhead)"; 79 | stroke: #81B1DB; 80 | } 81 | .note { 82 | stroke: rgba(255, 255, 255, 0.25); 83 | fill: #fff5ad; 84 | } 85 | .noteText { 86 | fill: black; 87 | stroke: none; 88 | font-family: 'trebuchet ms', verdana, arial; 89 | font-size: 14px; 90 | } 91 | /** Section styling */ 92 | .section { 93 | stroke: none; 94 | opacity: 0.2; 95 | } 96 | .section0 { 97 | fill: rgba(255, 255, 255, 0.3); 98 | } 99 | .section2 { 100 | fill: #EAE8B9; 101 | } 102 | .section1, 103 | .section3 { 104 | fill: white; 105 | opacity: 0.2; 106 | } 107 | .sectionTitle0 { 108 | fill: #F9FFFE; 109 | } 110 | .sectionTitle1 { 111 | fill: #F9FFFE; 112 | } 113 | .sectionTitle2 { 114 | fill: #F9FFFE; 115 | } 116 | .sectionTitle3 { 117 | fill: #F9FFFE; 118 | } 119 | .sectionTitle { 120 | text-anchor: start; 121 | font-size: 11px; 122 | text-height: 14px; 123 | } 124 | /* Grid and axis */ 125 | .grid .tick { 126 | stroke: rgba(255, 255, 255, 0.3); 127 | opacity: 0.3; 128 | shape-rendering: crispEdges; 129 | } 130 | .grid .tick text { 131 | fill: lightgrey; 132 | opacity: 0.5; 133 | } 134 | .grid path { 135 | stroke-width: 0; 136 | } 137 | /* Today line */ 138 | .today { 139 | fill: none; 140 | stroke: #DB5757; 141 | stroke-width: 2px; 142 | } 143 | /* Task styling */ 144 | /* Default task */ 145 | .task { 146 | stroke-width: 1; 147 | } 148 | .taskText { 149 | text-anchor: middle; 150 | font-size: 11px; 151 | } 152 | .taskTextOutsideRight { 153 | fill: #323D47; 154 | text-anchor: start; 155 | font-size: 11px; 156 | } 157 | .taskTextOutsideLeft { 158 | fill: #323D47; 159 | text-anchor: end; 160 | font-size: 11px; 161 | } 162 | /* Specific task settings for the sections*/ 163 | .taskText0, 164 | .taskText1, 165 | .taskText2, 166 | .taskText3 { 167 | fill: #323D47; 168 | } 169 | .task0, 170 | .task1, 171 | .task2, 172 | .task3 { 173 | fill: #BDD5EA; 174 | stroke: rgba(255, 255, 255, 0.5); 175 | } 176 | .taskTextOutside0, 177 | .taskTextOutside2 { 178 | fill: lightgrey; 179 | } 180 | .taskTextOutside1, 181 | .taskTextOutside3 { 182 | fill: lightgrey; 183 | } 184 | /* Active task */ 185 | .active0, 186 | .active1, 187 | .active2, 188 | .active3 { 189 | fill: #81B1DB; 190 | stroke: rgba(255, 255, 255, 0.5); 191 | } 192 | .activeText0, 193 | .activeText1, 194 | .activeText2, 195 | .activeText3 { 196 | fill: #323D47 !important; 197 | } 198 | /* Completed task */ 199 | .done0, 200 | .done1, 201 | .done2, 202 | .done3 { 203 | fill: lightgrey; 204 | } 205 | .doneText0, 206 | .doneText1, 207 | .doneText2, 208 | .doneText3 { 209 | fill: #323D47 !important; 210 | } 211 | /* Tasks on the critical line */ 212 | .crit0, 213 | .crit1, 214 | .crit2, 215 | .crit3 { 216 | stroke: #E83737; 217 | fill: #E83737; 218 | stroke-width: 2; 219 | } 220 | .activeCrit0, 221 | .activeCrit1, 222 | .activeCrit2, 223 | .activeCrit3 { 224 | stroke: #E83737; 225 | fill: #81B1DB; 226 | stroke-width: 2; 227 | } 228 | .doneCrit0, 229 | .doneCrit1, 230 | .doneCrit2, 231 | .doneCrit3 { 232 | stroke: #E83737; 233 | fill: lightgrey; 234 | stroke-width: 1; 235 | cursor: pointer; 236 | shape-rendering: crispEdges; 237 | } 238 | .doneCritText0, 239 | .doneCritText1, 240 | .doneCritText2, 241 | .doneCritText3 { 242 | fill: lightgrey !important; 243 | } 244 | .activeCritText0, 245 | .activeCritText1, 246 | .activeCritText2, 247 | .activeCritText3 { 248 | fill: #323D47 !important; 249 | } 250 | .titleText { 251 | text-anchor: middle; 252 | font-size: 18px; 253 | fill: lightgrey; 254 | } 255 | /* 256 | 257 | 258 | */ 259 | .node text { 260 | font-family: 'trebuchet ms', verdana, arial; 261 | font-size: 14px; 262 | } 263 | div.mermaidTooltip { 264 | position: absolute; 265 | text-align: center; 266 | max-width: 200px; 267 | padding: 2px; 268 | font-family: 'trebuchet ms', verdana, arial; 269 | font-size: 12px; 270 | background: #6D6D65; 271 | border: 1px solid rgba(255, 255, 255, 0.25); 272 | border-radius: 2px; 273 | pointer-events: none; 274 | z-index: 100; 275 | } 276 | -------------------------------------------------------------------------------- /DefaultTheme/default_assets/mermaid/mermaid.dark.css: -------------------------------------------------------------------------------- 1 | /* Flowchart variables */ 2 | /* Sequence Diagram variables */ 3 | /* Gantt chart variables */ 4 | .mermaid .label { 5 | color: #323D47; 6 | } 7 | .node rect, 8 | .node circle, 9 | .node ellipse, 10 | .node polygon { 11 | fill: #BDD5EA; 12 | stroke: #81B1DB; 13 | stroke-width: 1px; 14 | } 15 | .edgePath .path { 16 | stroke: lightgrey; 17 | } 18 | .edgeLabel { 19 | background-color: #e8e8e8; 20 | } 21 | .cluster rect { 22 | fill: #6D6D65 !important; 23 | rx: 4 !important; 24 | stroke: rgba(255, 255, 255, 0.25) !important; 25 | stroke-width: 1px !important; 26 | } 27 | .cluster text { 28 | fill: #F9FFFE; 29 | } 30 | .actor { 31 | stroke: #81B1DB; 32 | fill: #BDD5EA; 33 | } 34 | text.actor { 35 | fill: black; 36 | stroke: none; 37 | } 38 | .actor-line { 39 | stroke: lightgrey; 40 | } 41 | .messageLine0 { 42 | stroke-width: 1.5; 43 | stroke-dasharray: "2 2"; 44 | marker-end: "url(#arrowhead)"; 45 | stroke: lightgrey; 46 | } 47 | .messageLine1 { 48 | stroke-width: 1.5; 49 | stroke-dasharray: "2 2"; 50 | stroke: lightgrey; 51 | } 52 | #arrowhead { 53 | fill: lightgrey !important; 54 | } 55 | #crosshead path { 56 | fill: lightgrey !important; 57 | stroke: lightgrey !important; 58 | } 59 | .messageText { 60 | fill: lightgrey; 61 | stroke: none; 62 | } 63 | .labelBox { 64 | stroke: #81B1DB; 65 | fill: #BDD5EA; 66 | } 67 | .labelText { 68 | fill: #323D47; 69 | stroke: none; 70 | } 71 | .loopText { 72 | fill: lightgrey; 73 | stroke: none; 74 | } 75 | .loopLine { 76 | stroke-width: 2; 77 | stroke-dasharray: "2 2"; 78 | marker-end: "url(#arrowhead)"; 79 | stroke: #81B1DB; 80 | } 81 | .note { 82 | stroke: rgba(255, 255, 255, 0.25); 83 | fill: #fff5ad; 84 | } 85 | .noteText { 86 | fill: black; 87 | stroke: none; 88 | font-family: 'trebuchet ms', verdana, arial; 89 | font-size: 14px; 90 | } 91 | /** Section styling */ 92 | .section { 93 | stroke: none; 94 | opacity: 0.2; 95 | } 96 | .section0 { 97 | fill: rgba(255, 255, 255, 0.3); 98 | } 99 | .section2 { 100 | fill: #EAE8B9; 101 | } 102 | .section1, 103 | .section3 { 104 | fill: white; 105 | opacity: 0.2; 106 | } 107 | .sectionTitle0 { 108 | fill: #F9FFFE; 109 | } 110 | .sectionTitle1 { 111 | fill: #F9FFFE; 112 | } 113 | .sectionTitle2 { 114 | fill: #F9FFFE; 115 | } 116 | .sectionTitle3 { 117 | fill: #F9FFFE; 118 | } 119 | .sectionTitle { 120 | text-anchor: start; 121 | font-size: 11px; 122 | text-height: 14px; 123 | } 124 | /* Grid and axis */ 125 | .grid .tick { 126 | stroke: rgba(255, 255, 255, 0.3); 127 | opacity: 0.3; 128 | shape-rendering: crispEdges; 129 | } 130 | .grid .tick text { 131 | fill: lightgrey; 132 | opacity: 0.5; 133 | } 134 | .grid path { 135 | stroke-width: 0; 136 | } 137 | /* Today line */ 138 | .today { 139 | fill: none; 140 | stroke: #DB5757; 141 | stroke-width: 2px; 142 | } 143 | /* Task styling */ 144 | /* Default task */ 145 | .task { 146 | stroke-width: 1; 147 | } 148 | .taskText { 149 | text-anchor: middle; 150 | font-size: 11px; 151 | } 152 | .taskTextOutsideRight { 153 | fill: #323D47; 154 | text-anchor: start; 155 | font-size: 11px; 156 | } 157 | .taskTextOutsideLeft { 158 | fill: #323D47; 159 | text-anchor: end; 160 | font-size: 11px; 161 | } 162 | /* Specific task settings for the sections*/ 163 | .taskText0, 164 | .taskText1, 165 | .taskText2, 166 | .taskText3 { 167 | fill: #323D47; 168 | } 169 | .task0, 170 | .task1, 171 | .task2, 172 | .task3 { 173 | fill: #BDD5EA; 174 | stroke: rgba(255, 255, 255, 0.5); 175 | } 176 | .taskTextOutside0, 177 | .taskTextOutside2 { 178 | fill: lightgrey; 179 | } 180 | .taskTextOutside1, 181 | .taskTextOutside3 { 182 | fill: lightgrey; 183 | } 184 | /* Active task */ 185 | .active0, 186 | .active1, 187 | .active2, 188 | .active3 { 189 | fill: #81B1DB; 190 | stroke: rgba(255, 255, 255, 0.5); 191 | } 192 | .activeText0, 193 | .activeText1, 194 | .activeText2, 195 | .activeText3 { 196 | fill: #323D47 !important; 197 | } 198 | /* Completed task */ 199 | .done0, 200 | .done1, 201 | .done2, 202 | .done3 { 203 | fill: lightgrey; 204 | } 205 | .doneText0, 206 | .doneText1, 207 | .doneText2, 208 | .doneText3 { 209 | fill: #323D47 !important; 210 | } 211 | /* Tasks on the critical line */ 212 | .crit0, 213 | .crit1, 214 | .crit2, 215 | .crit3 { 216 | stroke: #E83737; 217 | fill: #E83737; 218 | stroke-width: 2; 219 | } 220 | .activeCrit0, 221 | .activeCrit1, 222 | .activeCrit2, 223 | .activeCrit3 { 224 | stroke: #E83737; 225 | fill: #81B1DB; 226 | stroke-width: 2; 227 | } 228 | .doneCrit0, 229 | .doneCrit1, 230 | .doneCrit2, 231 | .doneCrit3 { 232 | stroke: #E83737; 233 | fill: lightgrey; 234 | stroke-width: 1; 235 | cursor: pointer; 236 | shape-rendering: crispEdges; 237 | } 238 | .doneCritText0, 239 | .doneCritText1, 240 | .doneCritText2, 241 | .doneCritText3 { 242 | fill: lightgrey !important; 243 | } 244 | .activeCritText0, 245 | .activeCritText1, 246 | .activeCritText2, 247 | .activeCritText3 { 248 | fill: #323D47 !important; 249 | } 250 | .titleText { 251 | text-anchor: middle; 252 | font-size: 18px; 253 | fill: lightgrey; 254 | } 255 | /* 256 | 257 | 258 | */ 259 | .node text { 260 | font-family: 'trebuchet ms', verdana, arial; 261 | font-size: 14px; 262 | } 263 | div.mermaidTooltip { 264 | position: absolute; 265 | text-align: center; 266 | max-width: 200px; 267 | padding: 2px; 268 | font-family: 'trebuchet ms', verdana, arial; 269 | font-size: 12px; 270 | background: #6D6D65; 271 | border: 1px solid rgba(255, 255, 255, 0.25); 272 | border-radius: 2px; 273 | pointer-events: none; 274 | z-index: 100; 275 | } 276 | -------------------------------------------------------------------------------- /LiterateCS/TocManager.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # TOC Manager 3 | 4 | Although the TOC data structure is defined in the [LiterateCS.Theme](../LiterateCS.Theme/Toc.html) 5 | assembly, the code that loads and saves TOC can be found here, under the TocManager class. 6 | Themes only need to read the table of contents; loading and updating it is handled by the 7 | main application. 8 | 9 | ## Dependencies 10 | 11 | TocManager is a helper class that groups together the functionality related 12 | to the file format and serialization. It uses [YamlDotNet](https://github.com/aaubry/YamlDotNet) 13 | library to parse and deserialize the TOC file. The format of the file is described 14 | on a [separate page](../TableOfContents.html). 15 | */ 16 | namespace LiterateCS 17 | { 18 | using LiterateCS.Theme; 19 | using System; 20 | using System.Collections.Generic; 21 | using System.IO; 22 | using System.Linq; 23 | using System.Text; 24 | using YamlDotNet.Serialization; 25 | using YamlDotNet.Serialization.NamingConventions; 26 | 27 | public class TocManager 28 | { 29 | /* 30 | ## TOC Lifespan 31 | 32 | When a TocManager is created, a filename and the actual Toc object are 33 | provided. These are kept in private fields for the other methods to access. 34 | If new sections are added, they are be kept in a separate list to keep the 35 | Toc object immutable during the operation of the program. 36 | */ 37 | private Toc _toc; 38 | private string _filename; 39 | private List<Section> _addedSections; 40 | /* 41 | The users of the class naturally need to access the Toc object. This is 42 | possible through a read-only property. 43 | */ 44 | public Toc Toc => _toc; 45 | /* 46 | ## Constructing TOC Manager 47 | 48 | There are two ways to create a TocManager. When a TOC file already exist, it 49 | is loaded and initialized automatically. 50 | */ 51 | public TocManager (Toc toc, string filename) 52 | { 53 | _toc = toc ?? throw new ArgumentNullException (nameof (toc)); 54 | _filename = filename; 55 | _addedSections = new List<Section> (); 56 | } 57 | /* 58 | If there is no file available, a parameterless constructor can be called to 59 | create an empty TOC. In this case the TOC does not need to be updated, so 60 | the `_addedSections` field can be left uninitialized. 61 | */ 62 | public TocManager () 63 | { 64 | _toc = new Toc (); 65 | _toc.Contents = new List<Section> (); 66 | } 67 | /* 68 | ## Loading TOC 69 | 70 | TOC file is loaded using the deserialization feature provided by YamlDotNet. 71 | We configure the deserializer so that it converts the names of the data items 72 | into camel case and then maps them to the properties of the Toc class. Then 73 | we just open the file and feed it to the deserializer. 74 | */ 75 | public static TocManager Load (string yamlFile) 76 | { 77 | var deserializer = new DeserializerBuilder () 78 | .WithNamingConvention (CamelCaseNamingConvention.Instance) 79 | .Build (); 80 | try 81 | { 82 | using (var input = File.OpenText (yamlFile)) 83 | return new TocManager (deserializer.Deserialize<Toc> (input), 84 | yamlFile); 85 | } 86 | /* 87 | The most complicated part of the loading is the error reporting, 88 | which tries to give as much information for the error as possible. 89 | */ 90 | catch (Exception e) 91 | { 92 | throw new LiterateException ("Could not load TOC file. " + 93 | "Make sure that its format is correct", yamlFile, 94 | "https://johtela.github.io/LiterateCS/TableOfContents.html", e); 95 | } 96 | } 97 | /* 98 | ## Adding New Sections 99 | 100 | Instead of adding a new entry to TOC while the documentation is being 101 | generated, we add it to a temporary list. This list is concatenated 102 | to the TOC before it is saved. If there is no file associated to the 103 | TOC (in which case the temporary list is null), then we don't need to 104 | do anything. 105 | */ 106 | public void AddToToc (SplitPath path) 107 | { 108 | if (_addedSections == null) 109 | return; 110 | var section = FindSectionForFile (path.FilePath, Toc.Contents) ?? 111 | _addedSections.FirstOrDefault (s => s.File == path.FilePath); 112 | if (section == null) 113 | { 114 | _addedSections.Add (new Section () 115 | { 116 | Page = path.FileNameWithoutExtension, 117 | File = path.FilePath, 118 | Desc = "TODO! Add page description." 119 | }); 120 | } 121 | } 122 | /* 123 | ## Saving TOC 124 | 125 | We could use the serialization functionality of YamlDotNet to write the TOC 126 | back to a file, but it is actually simpler just add the new entries as text. 127 | Serialization has its own quirks which we should work around, if we would 128 | like to use it. The new entries are always at the end of the file, so we 129 | can just open the file in the append mode and write the sections into it. 130 | */ 131 | public void Save () 132 | { 133 | if (_filename == null || _addedSections == null || 134 | _addedSections.Count == 0) 135 | return; 136 | using (var output = File.AppendText (_filename)) 137 | foreach (var section in _addedSections) 138 | { 139 | output.WriteLine (); 140 | output.WriteLine (" - page: " + section.Page); 141 | output.WriteLine (" file: " + section.File); 142 | output.WriteLine (" desc: " + section.Desc); 143 | } 144 | } 145 | /* 146 | ## Checking If a Section Exists 147 | 148 | To check whether a file is not in TOC already we need to traverse the TOC tree 149 | recursively. The function below does just that. If a given file is not found 150 | in the tree, `null` is returned. 151 | */ 152 | public static Section FindSectionForFile (string file, List<Section> sections) 153 | { 154 | foreach (var section in sections) 155 | { 156 | if (section.File == file) 157 | return section; 158 | if (section.Subs != null) 159 | { 160 | var subSection = FindSectionForFile (file, section.Subs); 161 | if (subSection != null) 162 | return subSection; 163 | } 164 | } 165 | return null; 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /LiterateCS/BlockList.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # Source Blocks 3 | In order to extract the documentation from the code, LiterateCS needs to split a source file 4 | into blocks which represent either text or code. Blocks capture parts of a source file and 5 | make it easier to process them differently depending on their kind. 6 | */ 7 | namespace LiterateCS 8 | { 9 | using System; 10 | using System.Collections; 11 | using System.Collections.Generic; 12 | using System.Text; 13 | using ExtensionCord; 14 | /* 15 | ## Block Kinds 16 | A block can capture either documentation written in markdown or C# code. The enumeration 17 | below indicates which one we are dealing with. 18 | */ 19 | public enum BlockKind { Markdown, Code } 20 | /* 21 | ## Linked List of Blocks 22 | The block data structure itself is a simple singly-linked list. It implements 23 | `IEnumerable<T>` to make traversing the structure easier. 24 | */ 25 | public class BlockList : IEnumerable<BlockList> 26 | { 27 | /* 28 | The properties below describe the data associated with a block. `Kind` tells the 29 | whether it is a code or text block. `Contents` is the part of the source file 30 | that was extracted. Comment delimiters are excluded from the text, so that 31 | contents is valid markdown. `Next` points to the following block. Obviously 32 | code blocks are in the same order as they appear in the source file. 33 | */ 34 | public BlockKind Kind { get; private set; } 35 | public string Contents { get; private set; } 36 | public BlockList Next { get; internal set; } 37 | /* 38 | The following constants describe how the code blocks are decorated in the outputted 39 | markdown or HTML. In the case of markdown output, the code blocks are surrounded 40 | by standard triple backticks followed by the language designator. In HTML output the 41 | header and footer contain tags which have the required CSS classes in order for the 42 | syntax highlighting to work. 43 | */ 44 | private const string _mdCodeHeader = @"``` csharp"; 45 | private const string _mdCodeFooter = @"```"; 46 | private const string _htmlCodeHeader = @"<pre class=""csharp""><code class=""csharp"">"; 47 | private const string _htmlCodeFooter = @"</code></pre>"; 48 | /* 49 | The string builder is used to construct contents of a block. It is discarded after 50 | its content is extracted. 51 | */ 52 | internal StringBuilder _builder; 53 | /* 54 | ### Creating a Block 55 | Blocks are constructed dynamically as the source file is parsed. When creating a new 56 | block only the kind of the block and the output format needs to be specified. Based 57 | on those the constructor initializes a new block and inserts a correct header to it. 58 | 59 | In markdown output whitespace is a bit more important than in HTML. That is why 60 | we sometimes need to add additional line breaks to the output. 61 | */ 62 | public BlockList (BlockKind kind, OutputFormat format) 63 | { 64 | Kind = kind; 65 | _builder = new StringBuilder (); 66 | } 67 | /* 68 | Create a new markdown block. 69 | */ 70 | public BlockList (string contents) 71 | { 72 | Kind = BlockKind.Markdown; 73 | Contents = contents; 74 | } 75 | /* 76 | Cloning a single block. 77 | */ 78 | public BlockList (BlockList block) 79 | { 80 | Kind = block.Kind; 81 | Contents = block.Contents; 82 | } 83 | /* 84 | ### Closing a Block 85 | After a block is filled with its content it can be closed. Closing involves 86 | adding the correct header and footer to the output. Code blocks are trimmed 87 | before these are added. If they do not contain any text after trimming, then we 88 | don't add the header and footer at all. After the `StringBuilder` object has 89 | converted the contents to string, it can be disposed by assigning `null` to the 90 | field. 91 | */ 92 | public void Close (OutputFormat format) 93 | { 94 | if (Kind == BlockKind.Code) 95 | { 96 | TrimStart (); 97 | TrimEnd (); 98 | if (_builder.Length > 0) 99 | { 100 | _builder.Insert (0, format == OutputFormat.html ? 101 | _htmlCodeHeader : 102 | _mdCodeHeader + Environment.NewLine); 103 | _builder.Append (Environment.NewLine); 104 | _builder.AppendLine (format == OutputFormat.html ? 105 | _htmlCodeFooter : 106 | _mdCodeFooter); 107 | } 108 | } 109 | Contents = _builder.ToString (); 110 | _builder = null; 111 | } 112 | /* 113 | Code blocks are trimmed to get rid of extra white space at the beginning and 114 | end of them. This makes the verbatim output more compact and readable. The 115 | following methods trim all whitespace from the beginning and from the end 116 | of the block. Note that we don't remove the whitespace before the first 117 | non-empty line, so indentation is preserved. 118 | */ 119 | private void TrimStart () 120 | { 121 | while (RemoveFirstEmptyLine ()); 122 | } 123 | 124 | private void TrimEnd () 125 | { 126 | var last = _builder.Length - 1; 127 | var i = last; 128 | while (i >= 0 && char.IsWhiteSpace (_builder[i])) 129 | i--; 130 | if (i < last) 131 | _builder.Remove (i + 1, last - i); 132 | } 133 | /* 134 | The method below removes the first line of a block, if it contains just 135 | whitespace. It handles both Windows and Unix style line delimiters. The 136 | method returns true, if it removed a line, and false if it did not. 137 | */ 138 | private bool RemoveFirstEmptyLine () 139 | { 140 | var i = 0; 141 | while (i < _builder.Length && char.IsWhiteSpace (_builder[i]) && 142 | !_builder[i].In ('\r', '\n')) 143 | i++; 144 | if (i == _builder.Length || !_builder[i].In ('\r', '\n')) 145 | return false; 146 | _builder.Remove (0, i + 1); 147 | return true; 148 | } 149 | /* 150 | ### IEnumerable Implementation 151 | Iterator is used to implement `IEnumerable<BlockList>` interface. 152 | */ 153 | public IEnumerator<BlockList> GetEnumerator () 154 | { 155 | for (var block = this; block != null; block = block.Next) 156 | yield return block; 157 | } 158 | 159 | IEnumerator IEnumerable.GetEnumerator () 160 | { 161 | return GetEnumerator (); 162 | } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /LiterateCS/SplitPath.cs: -------------------------------------------------------------------------------- 1 | /* 2 | # SplitPath Structure 3 | 4 | LiterateCS operates on three base directories: 5 | 6 | * input directory which contains the files to be processed, 7 | * output directory where the generated documentation will be placed, and 8 | * theme directory which stores the HTML rendering library and its auxiliary files. 9 | 10 | When accessing files in these directories it is often necessary to segregate 11 | the base directory and the relative path inside that directory. For this purpose, 12 | we define a helper data structure that encapsulates a file path, but stores it in 13 | two parts: base path and file path. We call this data structure SplitPath and 14 | define it as follows. 15 | */ 16 | namespace LiterateCS 17 | { 18 | using System; 19 | using System.IO; 20 | using System.Linq; 21 | using System.Text; 22 | 23 | public struct SplitPath 24 | { 25 | public readonly string BasePath; 26 | public readonly string FilePath; 27 | /* 28 | ## Two Parts of SplitPath 29 | 30 | One benefit of splitting a path is that we can make sure that the parts 31 | are always in correct format. The base part is extended so that it contains 32 | an absolute folder path, and it is ensured that the last character is a 33 | backslash. Conversely, the file path is checked to be relative path without 34 | a root folder. If that is not the case, the constructor throws an exception. 35 | */ 36 | public SplitPath (string basePath, string filePath) 37 | { 38 | if (filePath != null && Path.IsPathRooted (filePath)) 39 | throw new ArgumentException ("filePath has to be a relative path."); 40 | BasePath = WithLastBackslash ( 41 | string.IsNullOrEmpty (basePath) ? 42 | Environment.CurrentDirectory : 43 | Path.GetFullPath (basePath)); 44 | FilePath = filePath; 45 | } 46 | 47 | private static string WithLastBackslash (string dirPath) => 48 | dirPath[dirPath.Length - 1] != Path.DirectorySeparatorChar ? 49 | dirPath + Path.DirectorySeparatorChar : dirPath; 50 | /* 51 | ## Constructing a SplitPath 52 | 53 | There is a handful of constructor methods that help building a 54 | SplitPath in various ways. 55 | 56 | First of all, it is possible to create a partial SplitPath by omitting 57 | either part of the path. Partial paths can be later glued together to 58 | create a valid path. The following two methods create a SplitPath given 59 | either just a base path or a file path. 60 | */ 61 | public static SplitPath Base (string basePath) => 62 | new SplitPath (basePath, null); 63 | 64 | public static SplitPath File (string file) => 65 | new SplitPath (null, file); 66 | /* 67 | Another way to construct a SplitPath is to give a complete file path 68 | and a base path. The base path will be excluded from the full path to 69 | create the relative file path. 70 | */ 71 | public static SplitPath Split (string basePath, string fullPath) => 72 | new SplitPath (basePath, fullPath.Substring (basePath.Length)); 73 | /* 74 | Changing either part is also easy. Note that the structure is immutable, 75 | so it is never modified in-place. Instead a new structure is returned. 76 | */ 77 | public SplitPath WithBase (string basePath) => 78 | new SplitPath (basePath, FilePath); 79 | 80 | public SplitPath WithFile (string filePath) => 81 | new SplitPath (BasePath, filePath); 82 | /* 83 | It is possible to change the file extension as well. 84 | */ 85 | public SplitPath ChangeExtension (string newExtension) => 86 | new SplitPath (BasePath, Path.ChangeExtension (FilePath, newExtension)); 87 | /* 88 | ## SplitPath Features 89 | 90 | If both parts of a SplitPath are null, it is considered to be empty. 91 | */ 92 | public bool IsEmpty => 93 | BasePath == null && FilePath == null; 94 | /* 95 | The following properties can be used to test if one part of the path 96 | is missing. 97 | */ 98 | public bool IsBase => 99 | BasePath != null && FilePath == null; 100 | 101 | public bool IsFile => 102 | BasePath == null && FilePath != null; 103 | /* 104 | We are also wrapping some of the methods defined in `System.IO.Path` class 105 | to access other parts of the path: file name, extension, or directory name. 106 | */ 107 | public string FileName => 108 | Path.GetFileName (FilePath); 109 | 110 | public string FileNameWithoutExtension => 111 | Path.GetFileNameWithoutExtension (FilePath); 112 | 113 | public string Extension => 114 | Path.GetExtension (FilePath); 115 | 116 | public string DirectoryName => 117 | Path.GetDirectoryName (ToString ()); 118 | /* 119 | In some cases it is necessary to know how deep the file path part is; 120 | for example, to create a relative file path inside a base directory. 121 | The method below counts how many directory separator characters there 122 | are in a file path, thus returning its depth. 123 | */ 124 | public int FilePathDepth => 125 | FilePath.Count (c => c == Path.DirectorySeparatorChar); 126 | /* 127 | When we know the depth of a file path, we can construct a relative 128 | path pointing from the file to the base directory. This comes in handy 129 | when we are creating links between generated HTML files. 130 | 131 | The following code just concatenates as many parent directory pointers 132 | (`../`) together as the depth of the file path indicates to construct 133 | a relative path to the base directory. 134 | */ 135 | public string RelativePathToRoot 136 | { 137 | get 138 | { 139 | var depth = FilePathDepth; 140 | var result = new StringBuilder (); 141 | for (int i = 0; i < depth; i++) 142 | result.Append (@"../"); 143 | return result.ToString (); 144 | } 145 | } 146 | /* 147 | The overloaded `!` operator is a shorthand to the `ToString` method 148 | which concatenates the two parts of a SplitPath to form a full path 149 | as a string. 150 | */ 151 | public override string ToString () => 152 | BasePath + FilePath; 153 | 154 | public static string operator ! (SplitPath splitPath) => 155 | splitPath.ToString (); 156 | /* 157 | Finally, we can combine two SplitPaths by taking the base path from the 158 | first one and the file path from the second one. To make this operation 159 | more convenient to use it is implemented as the `+` operator. 160 | */ 161 | public static SplitPath operator + (SplitPath basePath, SplitPath filePath) 162 | { 163 | return new SplitPath (basePath.BasePath, filePath.FilePath); 164 | } 165 | } 166 | } 167 | --------------------------------------------------------------------------------