Compare commits

..

1 Commits

Author SHA1 Message Date
Alexandre Mutel
62907f9314 Example API doc generation 2022-06-29 07:00:28 +02:00
17 changed files with 1119 additions and 197 deletions

3
.gitignore vendored
View File

@@ -242,3 +242,6 @@ _Pvt_Extensions
# Remove artifacts produced by dotnet-releaser
artifacts-dotnet-releaser/
# Remove .lunet temp folder
.lunet/build

162
site/.lunet/css/main.css Normal file
View File

@@ -0,0 +1,162 @@
/* main */
:root {
--base-html-font-size: 62.5%;
--base-font-size: 1.65rem;
--container-xl-max-width: 160rem;
--site-logo-size: 45px;
--site-logo-url: url("/img/markdig.png");
}
/* make tocbot working with halfmoon */
html, body, .page-wrapper, .content-wrapper {
position: static;
}
.page-wrapper {
overflow: visible;
}
/* disable any box around active headers with tocbot */
h1:focus, h1:active,
h2:focus, h2:active,
h3:focus, h3:active,
h4:focus, h4:active,
h5:focus, h5:active,
h6:focus, h6:active
{
outline: none;
}
.nav-item.active {
border-bottom-width: 2px;
border-bottom-style: solid;
border-bottom-color: var(--lm-navbar-link-active-text-color);
}
.main-row {
min-height: 92vh;
}
.nav-item.active .nav-link {
color: var(--lm-navbar-link-active-text-color);
background-color: var(--lm-navbar-link-active-bg-color);
}
.site-logo {
background: transparent var(--site-logo-url) no-repeat scroll 0px 0px / var(--site-logo-size) var(--site-logo-size);
display: block;
width: var(--site-logo-size);
height: var(--site-logo-size);
}
.in-this-article-nav {
position: fixed;
margin-right: 2rem;
z-index: 20;
padding: 0.5rem;
border-radius: 0.4rem;
}
.in-this-article-nav .title {
font-weight: bold;
font-size: 1em;
padding-bottom: 1em;
}
.content .is-active-link::before {
background-color: var(--primary-color);
}
.heading-anchor-hidden {
display: none !important;
}
@media (min-width: 1600px) {
html {
font-size: var(--base-html-font-size);
}
}
@media (min-width: 1920px) {
html {
font-size: var(--base-html-font-size);
}
}
table.api-dotnet-inherit, table.api-dotnet-implements, table.api-dotnet-derived {
margin-bottom: 1em;
}
.api-dotnet-inherit td, .api-dotnet-implements td, .api-dotnet-derived td {
vertical-align: top;
}
.api-dotnet-inherit div:not(:first-child):before {
content: " ᐅ ";
white-space: pre;
}
/*.api-dotnet-inherit td, .api-dotnet-inherit tr, .api-dotnet-implements td, .api-dotnet-implements tr, .api-dotnet-derived tr {
display: flex;
}
*/
.api-dotnet-inherit div, .api-dotnet-implements div
{
display: inline-block;
}
.api-dotnet-inherit td:not(:first-child), .api-dotnet-implements td:not(:first-child), .api-dotnet-derived td:not(:first-child) {
padding-left: 1em;
}
.api-dotnet-implements div:not(:first-child):before {
content: ", ";
white-space: pre;
}
.api-dotnet-parameter-list {
display: flex;
}
.api-dotnet-parameter-list dd {
margin-left: 1em;
}
dl.api-dotnet-parameter-list {
margin-bottom: 0px;
}
table.api-dotnet-members-table {
width: 100%;
}
table.api-dotnet-members-table p {
margin-top: 0px;
margin-bottom: 0px;
}
.api-dotnet-members-table tr td:first-child {
width: 33%;
}
div.api-dotnet {
width: 100%;
}
.api-dotnet-members-table tr:not(:first-child) {
border-top: 1px solid #ddd;
}
.api-dotnet-members-table td {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
}
@media (prefers-color-scheme: dark) {
.api-dotnet-members-table tr:not(:first-child) {
border-top: 1px solid #777;
}
}

701
site/.lunet/css/prism.css Normal file
View File

@@ -0,0 +1,701 @@
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism-coy&languages=markup+clike+c+csharp+cpp+fsharp+markdown&plugins=line-highlight+line-numbers+toolbar+show-language */
/**
* prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML
* Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics);
* @author Tim Shedor
*/
@media (prefers-color-scheme: light) {
code[class*="language-"],
pre[class*="language-"] {
color: #393A34;
background: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre-wrap;
word-spacing: normal;
word-break: break-word;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre[class*="language-"] {
position: relative;
margin: .5em 0;
overflow: visible;
padding: 0;
}
pre[class*="language-"]>code {
position: relative;
border-left: 4px solid #358ccb;
box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
background-color: #fdfdfd;
background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
background-size: 3em 3em;
background-origin: content-box;
background-attachment: local;
}
code[class*="language"] {
max-height: inherit;
height: inherit;
padding: 0 1em;
display: block;
overflow: auto;
}
/* Margin bottom to accommodate shadow */
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background-color: #fdfdfd;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin-bottom: 1em;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
position: relative;
padding: .2em;
border-radius: 0.3em;
color: #c92c2c;
border: 1px solid #dddddd;
display: inline;
white-space: normal;
}
pre[class*="language-"]:before,
pre[class*="language-"]:after {
content: '';
z-index: -2;
display: block;
position: absolute;
bottom: 0.75em;
left: 0.18em;
width: 40%;
height: 20%;
max-height: 13em;
}
:not(pre) > code[class*="language-"]:after,
pre[class*="language-"]:after {
right: 0.75em;
left: auto;
-webkit-transform: rotate(2deg);
-moz-transform: rotate(2deg);
-ms-transform: rotate(2deg);
-o-transform: rotate(2deg);
transform: rotate(2deg);
}
.token.comment,
.token.block-comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #008000; font-style: italic;
}
.token.char,
.token.string {
color: #A31515;
}
.token.punctuation {
color: #393A34; /* no highlight */
}
.token.deleted {
color: #c92c2c;
}
.token.function-name,
.token.function {
color: #393A34;
}
.token.tag,
.token.selector {
color: #800000;
}
.token.attr-name,
.token.regex,
.token.entity {
color: #ff0000;
}
.token.builtin,
.token.url,
.token.symbol,
.token.number,
.token.boolean,
.token.variable,
.token.constant,
.token.inserted {
color: #36acaa;
}
.token.operator,
.token.variable {
color: #a67f59;
background: rgba(255, 255, 255, 0.5);
}
.token.atrule,
.token.attr-value,
.token.keyword,
.token.class-name {
color: #0000ff;
}
.token.directive.tag .tag {
background: #ffff00;
color: #393A34;
}
.token.class-name,
.token.property {
color: #2B91AF;
}
.token.important {
color: #e90;
}
.language-css .token.string,
.style .token.string {
color: #a67f59;
background: rgba(255, 255, 255, 0.5);
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.namespace {
opacity: .7;
}
@media screen and (max-width: 767px) {
pre[class*="language-"]:before,
pre[class*="language-"]:after {
bottom: 14px;
box-shadow: none;
}
}
/* Plugin styles */
.token.tab:not(:empty):before,
.token.cr:before,
.token.lf:before {
color: #e0d7d1;
}
/* Plugin styles: Line Numbers */
pre[class*="language-"].line-numbers.line-numbers {
padding-left: 0;
}
pre[class*="language-"].line-numbers.line-numbers code {
padding-left: 3.8em;
}
pre[class*="language-"].line-numbers.line-numbers .line-numbers-rows {
left: 0;
}
/* Plugin styles: Line Highlight */
pre[class*="language-"][data-line] {
padding-top: 0;
padding-bottom: 0;
padding-left: 0;
}
pre[data-line] code {
position: relative;
padding-left: 4em;
}
pre .line-highlight {
margin-top: 0;
}
pre[data-line] {
position: relative;
padding: 1em 0 1em 3em;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em; /* Same as .prisms padding-top */
background: hsla(24, 20%, 50%,.08);
background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
pointer-events: none;
line-height: inherit;
white-space: pre;
}
.line-highlight:before,
.line-highlight[data-end]:after {
content: attr(data-start);
position: absolute;
top: .4em;
left: .6em;
min-width: 1em;
padding: 0 .5em;
background-color: hsla(24, 20%, 50%,.4);
color: hsl(24, 20%, 95%);
font: bold 65%/1.5 sans-serif;
text-align: center;
vertical-align: .3em;
border-radius: 999px;
text-shadow: none;
box-shadow: 0 1px white;
}
.line-highlight[data-end]:after {
content: attr(data-end);
top: auto;
bottom: .4em;
}
.line-numbers .line-highlight:before,
.line-numbers .line-highlight:after {
content: none;
}
pre[class*="language-"].line-numbers {
position: relative;
padding-left: 3.8em;
counter-reset: linenumber;
}
pre[class*="language-"].line-numbers > code {
position: relative;
white-space: inherit;
}
.line-numbers .line-numbers-rows {
position: absolute;
pointer-events: none;
top: 0;
font-size: 100%;
left: -3.8em;
width: 3em; /* works for line-numbers below 1000 lines */
letter-spacing: -1px;
border-right: 1px solid #a5a5a5;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.line-numbers-rows > span {
pointer-events: none;
display: block;
counter-increment: linenumber;
}
.line-numbers-rows > span:before {
content: counter(linenumber);
color: #2B91AF;
display: block;
padding-right: 0.8em;
text-align: right;
}
div.code-toolbar {
position: relative;
}
div.code-toolbar > .toolbar {
position: absolute;
top: .3em;
right: .2em;
transition: opacity 0.3s ease-in-out;
opacity: 0;
}
div.code-toolbar:hover > .toolbar {
opacity: 1;
}
div.code-toolbar > .toolbar .toolbar-item {
display: inline-block;
}
div.code-toolbar > .toolbar a {
cursor: pointer;
}
div.code-toolbar > .toolbar button {
background: none;
border: 0;
color: inherit;
font: inherit;
line-height: normal;
overflow: visible;
padding: 0;
-webkit-user-select: none; /* for button */
-moz-user-select: none;
-ms-user-select: none;
}
div.code-toolbar > .toolbar a,
div.code-toolbar > .toolbar button,
div.code-toolbar > .toolbar span {
color: #bbb;
font-size: .8em;
padding: 0 .5em;
background: #f5f2f0;
background: rgba(224, 224, 224, 0.2);
box-shadow: 0 2px 0 0 rgba(0,0,0,0.2);
border-radius: .5em;
}
div.code-toolbar > .toolbar a:hover,
div.code-toolbar > .toolbar a:focus,
div.code-toolbar > .toolbar button:hover,
div.code-toolbar > .toolbar button:focus,
div.code-toolbar > .toolbar span:hover,
div.code-toolbar > .toolbar span:focus {
color: inherit;
text-decoration: none;
}
}
@media (prefers-color-scheme: dark) {
/* https://github.com/PrismJS/prism-themes/blob/master/themes/prism-vsc-dark-plus.css */
pre[class*="language-"],
code[class*="language-"] {
color: #d4d4d4;
font-size: 13px;
text-shadow: none;
font-family: Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace;
direction: ltr;
text-align: left;
white-space: pre-wrap;
word-spacing: normal;
word-break: break-word;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"] {
position: relative;
margin: .5em 0;
overflow: visible;
background: #1e1e1e;
}
pre[class*="language-"]>code {
border-left: 4px solid #358ccb;
}
code[class*="language"] {
max-height: inherit;
height: inherit;
padding: 0.5em 1em;
display: block;
overflow: auto;
}
pre[class*="language-"]::selection,
code[class*="language-"]::selection,
pre[class*="language-"] *::selection,
code[class*="language-"] *::selection {
text-shadow: none;
background: #75a7ca;
}
@media print {
pre[class*="language-"],
code[class*="language-"] {
text-shadow: none;
}
}
:not(pre) > code[class*="language-"] {
padding: .1em .3em;
border-radius: .3em;
color: #db4c69;
background: #f9f2f4;
}
/*********************************************************
* Tokens
*/
.namespace {
opacity: .7;
}
.token.doctype .token.doctype-tag {
color: #569CD6;
}
.token.doctype .token.name {
color: #9cdcfe;
}
.token.comment,
.token.prolog {
color: #6a9955;
}
.token.punctuation,
.language-html .language-css .token.punctuation,
.language-html .language-javascript .token.punctuation {
color: #d4d4d4;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.inserted,
.token.unit {
color: #b5cea8;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.deleted {
color: #ce9178;
}
.language-css .token.string.url {
text-decoration: underline;
}
.token.operator,
.token.entity {
color: #d4d4d4;
}
.token.operator.arrow {
color: #569CD6;
}
.token.atrule {
color: #ce9178;
}
.token.atrule .token.rule {
color: #c586c0;
}
.token.atrule .token.url {
color: #9cdcfe;
}
.token.atrule .token.url .token.function {
color: #dcdcaa;
}
.token.atrule .token.url .token.punctuation {
color: #d4d4d4;
}
.token.keyword {
color: #569CD6;
}
.token.keyword.module,
.token.keyword.control-flow {
color: #c586c0;
}
.token.function,
.token.function .token.maybe-class-name {
color: #dcdcaa;
}
.token.regex {
color: #d16969;
}
.token.important {
color: #569cd6;
}
.token.italic {
font-style: italic;
}
.token.constant {
color: #9cdcfe;
}
.token.class-name,
.token.maybe-class-name {
color: #4ec9b0;
}
.token.console {
color: #9cdcfe;
}
.token.parameter {
color: #9cdcfe;
}
.token.interpolation {
color: #9cdcfe;
}
.token.punctuation.interpolation-punctuation {
color: #569cd6;
}
.token.boolean {
color: #569cd6;
}
.token.property,
.token.variable,
.token.imports .token.maybe-class-name,
.token.exports .token.maybe-class-name {
color: #9cdcfe;
}
.token.selector {
color: #d7ba7d;
}
.token.escape {
color: #d7ba7d;
}
.token.tag {
color: #569cd6;
}
.token.tag .token.punctuation {
color: #808080;
}
.token.cdata {
color: #808080;
}
.token.attr-name {
color: #9cdcfe;
}
.token.attr-value,
.token.attr-value .token.punctuation {
color: #ce9178;
}
.token.attr-value .token.punctuation.attr-equals {
color: #d4d4d4;
}
.token.entity {
color: #569cd6;
}
.token.namespace {
color: #4ec9b0;
}
/*********************************************************
* Language Specific
*/
pre[class*="language-javascript"],
code[class*="language-javascript"],
pre[class*="language-jsx"],
code[class*="language-jsx"],
pre[class*="language-typescript"],
code[class*="language-typescript"],
pre[class*="language-tsx"],
code[class*="language-tsx"] {
color: #9cdcfe;
}
pre[class*="language-css"],
code[class*="language-css"] {
color: #ce9178;
}
pre[class*="language-html"],
code[class*="language-html"] {
color: #d4d4d4;
}
.language-regex .token.anchor {
color: #dcdcaa;
}
.language-html .token.punctuation {
color: #808080;
}
/*********************************************************
* Line highlighting
*/
pre[data-line] {
position: relative;
}
pre[class*="language-"] > code[class*="language-"] {
position: relative;
z-index: 1;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em;
background: #f7ebc6;
box-shadow: inset 5px 0 0 #f7d87c;
z-index: 0;
pointer-events: none;
line-height: inherit;
white-space: pre;
}
}

24
site/.lunet/js/xoofx.js Normal file
View File

@@ -0,0 +1,24 @@
anchors.add();
var jstoc = document.getElementsByClassName("js-toc");
if (jstoc.length > 0)
{
tocbot.init({
// Which headings to grab inside of the contentSelector element.
headingSelector: 'h2, h3, h4, h5',
collapseDepth: 3,
orderedList: true,
hasInnerContainers: true,
});
}
(function () {
const InitLunetTheme = function (e) {
if (halfmoon.darkModeOn != e.matches) {
halfmoon.toggleDarkMode();
}
}
let colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)')
InitLunetTheme(colorSchemeQueryList);
colorSchemeQueryList.addListener(InitLunetTheme);
})();

View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en" itemscope itemtype="http://schema.org/WebPage" class="my-html-setup">
<head>
{{~ Head ~}}
</head>
<body class="with-custom-webkit-scrollbars with-custom-css-scrollbars">
<div class="page-wrapper with-transitions">
<div class="sticky-alerts"></div>
<div class="content-wrapper bg-light-lm bg-dark-dm">
<div class="container-xl bg-white-lm bg-dark-light-dm">
<div class="row">
<div class="col-xl-12">
<nav class="navbar">
<a class="site-logo navbar-brand" href="/"></a>
<div id="navbarSupportedContent" class="collapse navbar-collapse justify-content-between">
{{~ site.menu.home.render {
depth: 1,
kind: "nav",
list_class: "w-100"
}
~}}
</div>
</nav>
</div>
</div>
<div class="row main-row">
{{~ $main_content_col_size = 8 ~}}
{{~ if page.nomenu; $main_content_col_size = $main_content_col_size + 2; end }}
{{~ if page.notoc; $main_content_col_size = $main_content_col_size + 2; end }}
{{~ if !page.nomenu ~}}
<div class="col-xl-2 ">
<div class="content">
Menu
</div>
</div>
{{~ end ~}}
<div class="col-xl-{{ $main_content_col_size }} ">
<div class="content js-toc-content">
{{ content }}
</div>
</div>
{{~ if !page.notoc ~}}
<div class="col-xl-2 ">
<div class="content">
<div class="in-this-article-nav">
<div class="title">In this article</div>
<nav class="js-toc toc"></nav>
</div>
</div>
</div>
{{~ end ~}}
</div>
<div class="row">
<div class="col-xl-12">
<nav class="navbar navbar-fixed-bottom justify-content-center">
<footer>Copyright &copy; 2009 - {{ date.now.year }}, Alexandre Mutel - Blog content licensed under the Creative Commons <a href="http://creativecommons.org/licenses/by/2.5/">CC BY 2.5</a> | Site powered by <a href="https://github.com/lunet-io/lunet">lunet</a></footer>
</nav>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,5 @@
---
layout: _default
---
<h1 class="title">{{ page.title_html ?? page.title }}</h1>
{{ content }}

70
site/config.scriban Normal file
View File

@@ -0,0 +1,70 @@
# Site Settings
author = "Alexandre Mutel"
title = "markdig"
description = "markdig website"
html.head.title = do; ret page.title + " | " + site.title; end
basepath = ""
baseurl = baseurl ?? "https://markdig.net"
# Github repository
github_user = "xoofx"
github_repo_url = "https://github.com/lunet-io/markdig/"
with cards.twitter
enable = true
card = "summary_large_image"
user = "markdig"
image = "/images/twitter-banner.png"
end
# Resources bundle
with bundle
fontawesome = resource "npm:font-awesome" "4.7.0"
halfmoon = resource "npm:halfmoon" "1.1.0"
tocbot = resource "npm:tocbot" "4.12.1"
anchorjs = resource "npm:anchor-js" "4.2.2"
prismjs = resource "npm:prismjs" "1.20.0"
# scss.includes.add fontawesome.path + "/scss"
# css files
css halfmoon "/css/halfmoon-variables.min.css"
css tocbot "/dist/tocbot.css"
css fontawesome "/css/font-awesome.min.css"
css "/css/prism.css"
css "/css/main.css"
# js files
js anchorjs "/anchor.min.js"
js halfmoon "/js/halfmoon.min.js"
js tocbot "/dist/tocbot.min.js"
js prismjs "/prism.js"
js prismjs "/components/prism-shell-session.min.js"
js prismjs "/components/prism-clike.min.js"
js prismjs "/components/prism-c.min.js"
js prismjs "/components/prism-cpp.min.js"
js prismjs "/components/prism-csharp.min.js"
js "/js/prism-stark.js"
js "/js/xoofx.js"
# copy font files
content fontawesome "/fonts/fontawesome-webfont.*" "/fonts/"
# concatenate css/js files
concat = true
minify = true
end
with attributes
# match "/blog/**/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]*.md" {
# url: "/:section/:year/:month/:day/:title:output_ext"
#}
end
with api.dotnet
title = "Markdig .NET API Reference"
projects = ["../src/Markdig/Markdig.csproj"]
properties = {TargetFramework: "netstandard2.0"}
end

BIN
site/img/markdig.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

3
site/menu.yml Normal file
View File

@@ -0,0 +1,3 @@
home:
- {path: readme.md}
- {path: api/readme.md, title: "Markdig API"}

10
site/readme.md Normal file
View File

@@ -0,0 +1,10 @@
---
layout: simple
title: Home
title_html: Hi and Welcome!
---
Hello World!
Test: <xref:system.object>

8
site/system.md Normal file
View File

@@ -0,0 +1,8 @@
---
uid: system.object
layout: simple
title: Home
title_html: Hi and Welcome!
---
Hello World from system.object!

View File

@@ -1,92 +0,0 @@
using System.Collections.Generic;
using System.Globalization;
using Markdig.Helpers;
using NUnit.Framework;
namespace Markdig.Tests
{
public class TestCharHelper
{
// An ASCII punctuation character is
// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., / (U+00212F),
// :, ;, <, =, >, ?, @ (U+003A0040),
// [, \, ], ^, _, ` (U+005B0060),
// {, |, }, or ~ (U+007B007E).
private static readonly HashSet<char> s_asciiPunctuation = new()
{
'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/',
':', ';', '<', '=', '>', '?', '@',
'[', '\\', ']', '^', '_', '`',
'{', '|', '}', '~'
};
// A Unicode punctuation character is an ASCII punctuation character or anything in the general Unicode categories
// Pc, Pd, Pe, Pf, Pi, Po, or Ps.
private static readonly HashSet<UnicodeCategory> s_punctuationCategories = new()
{
UnicodeCategory.ConnectorPunctuation,
UnicodeCategory.DashPunctuation,
UnicodeCategory.ClosePunctuation,
UnicodeCategory.FinalQuotePunctuation,
UnicodeCategory.InitialQuotePunctuation,
UnicodeCategory.OtherPunctuation,
UnicodeCategory.OpenPunctuation
};
private static bool ExpectedIsPunctuation(char c)
{
return c <= 127
? s_asciiPunctuation.Contains(c)
: s_punctuationCategories.Contains(CharUnicodeInfo.GetUnicodeCategory(c));
}
private static bool ExpectedIsWhitespace(char c)
{
// A Unicode whitespace character is any code point in the Unicode Zs general category,
// or a tab (U+0009), line feed (U+000A), form feed (U+000C), or carriage return (U+000D).
return c == '\t' || c == '\n' || c == '\u000C' || c == '\r' ||
CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.SpaceSeparator;
}
[Test]
public void IsWhitespace()
{
for (int i = char.MinValue; i <= char.MaxValue; i++)
{
char c = (char)i;
Assert.AreEqual(ExpectedIsWhitespace(c), CharHelper.IsWhitespace(c));
}
}
[Test]
public void CheckUnicodeCategory()
{
for (int i = char.MinValue; i <= char.MaxValue; i++)
{
char c = (char)i;
bool expectedSpace = c == 0 || ExpectedIsWhitespace(c);
bool expectedPunctuation = c == 0 || ExpectedIsPunctuation(c);
CharHelper.CheckUnicodeCategory(c, out bool spaceActual, out bool punctuationActual);
Assert.AreEqual(expectedSpace, spaceActual);
Assert.AreEqual(expectedPunctuation, punctuationActual);
}
}
[Test]
public void IsSpaceOrPunctuation()
{
for (int i = char.MinValue; i <= char.MaxValue; i++)
{
char c = (char)i;
bool expected = c == 0 || ExpectedIsWhitespace(c) || ExpectedIsPunctuation(c);
Assert.AreEqual(expected, CharHelper.IsSpaceOrPunctuation(c));
}
}
}
}

View File

@@ -10,7 +10,9 @@ namespace Markdig.Tests
{
[TestCase("| S | T |\r\n|---|---| \r\n| G | H |")]
[TestCase("| S | T |\r\n|---|---|\t\r\n| G | H |")]
[TestCase("| S | T |\r\n|---|---|\v\r\n| G | H |")]
[TestCase("| S | T |\r\n|---|---|\f\r\n| G | H |")]
[TestCase("| S | T |\r\n|---|---|\f\v\t \r\n| G | H |")]
[TestCase("| S | \r\n|---|\r\n| G |\r\n\r\n| D | D |\r\n| ---| ---| \r\n| V | V |", 2)]
public void TestTableBug(string markdown, int tableCount = 1)
{

View File

@@ -53,7 +53,7 @@ namespace Markdig.Helpers
// A right-flanking delimiter run is a delimiter run that is
// (1) not preceded by Unicode whitespace, and either
// (2a) not preceded by a punctuation character, or
// (1a) not preceded by a punctuation character, or
// (2b) preceded by a punctuation character and followed by Unicode whitespace or a punctuation character.
// For purposes of this definition, the beginning and the end of the line count as Unicode whitespace.
canClose = !prevIsWhiteSpace &&
@@ -144,37 +144,9 @@ namespace Markdig.Helpers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsWhitespace(this char c)
{
// 2.1 Characters and lines
// A Unicode whitespace character is any code point in the Unicode Zs general category,
// or a tab (U+0009), line feed (U+000A), form feed (U+000C), or carriage return (U+000D).
if (c <= ' ')
{
const long Mask =
(1L << ' ') |
(1L << '\t') |
(1L << '\n') |
(1L << '\f') |
(1L << '\r');
return (Mask & (1L << c)) != 0;
}
return c >= '\u00A0' && IsWhitespaceRare(c);
static bool IsWhitespaceRare(char c)
{
// return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.SpaceSeparator;
if (c < 5760)
{
return c == '\u00A0';
}
else
{
return c <= 12288 &&
(c == 5760 || IsInInclusiveRange(c, 8192, 8202) || c == 8239 || c == 8287 || c == 12288);
}
}
// 2.1 Characters and lines
// A whitespace character is a space(U + 0020), tab(U + 0009), newline(U + 000A), line tabulation (U + 000B), form feed (U + 000C), or carriage return (U + 000D).
return c <= ' ' && (c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r');
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -199,47 +171,46 @@ namespace Markdig.Helpers
// Check if a char is a space or a punctuation
public static void CheckUnicodeCategory(this char c, out bool space, out bool punctuation)
{
if (IsWhitespace(c))
// Credits: code from CommonMark.NET
// Copyright (c) 2014, Kārlis Gaņģis All rights reserved.
// See license for details: https://github.com/Knagis/CommonMark.NET/blob/master/LICENSE.md
if (c <= 'ÿ')
{
space = true;
punctuation = false;
}
else if (c <= 127)
{
space = c == '\0';
punctuation = c == '\0' || IsAsciiPunctuation(c);
space = c == '\0' || c == ' ' || (c >= '\t' && c <= '\r') || c == '\u00a0' || c == '\u0085';
punctuation = c == '\0' || (c >= 33 && c <= 47) || (c >= 58 && c <= 64) || (c >= 91 && c <= 96) || (c >= 123 && c <= 126);
}
else
{
// A Unicode punctuation character is an ASCII punctuation character
// or anything in the general Unicode categories Pc, Pd, Pe, Pf, Pi, Po, or Ps.
space = false;
UnicodeCategory category = CharUnicodeInfo.GetUnicodeCategory(c);
punctuation = category == UnicodeCategory.ConnectorPunctuation
var category = CharUnicodeInfo.GetUnicodeCategory(c);
space = category == UnicodeCategory.SpaceSeparator
|| category == UnicodeCategory.LineSeparator
|| category == UnicodeCategory.ParagraphSeparator;
punctuation = !space &&
(category == UnicodeCategory.ConnectorPunctuation
|| category == UnicodeCategory.DashPunctuation
|| category == UnicodeCategory.OpenPunctuation
|| category == UnicodeCategory.ClosePunctuation
|| category == UnicodeCategory.InitialQuotePunctuation
|| category == UnicodeCategory.FinalQuotePunctuation
|| category == UnicodeCategory.OtherPunctuation;
|| category == UnicodeCategory.OtherPunctuation);
}
}
// Same as CheckUnicodeCategory
internal static bool IsSpaceOrPunctuation(this char c)
{
if (IsWhitespace(c))
if (c <= 'ÿ')
{
return true;
}
else if (c <= 127)
{
return c == '\0' || IsAsciiPunctuation(c);
return c == '\0' || c == ' ' || (c >= '\t' && c <= '\r') || c == '\u00a0' || c == '\u0085' ||
(c >= 33 && c <= 47 && c != 38) || (c >= 58 && c <= 64) || (c >= 91 && c <= 96) || (c >= 123 && c <= 126);
}
else
{
var category = CharUnicodeInfo.GetUnicodeCategory(c);
return category == UnicodeCategory.ConnectorPunctuation
return category == UnicodeCategory.SpaceSeparator
|| category == UnicodeCategory.LineSeparator
|| category == UnicodeCategory.ParagraphSeparator
|| category == UnicodeCategory.ConnectorPunctuation
|| category == UnicodeCategory.DashPunctuation
|| category == UnicodeCategory.OpenPunctuation
|| category == UnicodeCategory.ClosePunctuation
@@ -318,16 +289,44 @@ namespace Markdig.Helpers
public static bool IsAsciiPunctuation(this char c)
{
// 2.1 Characters and lines
// An ASCII punctuation character is
// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., / (U+00212F),
// :, ;, <, =, >, ?, @ (U+003A0040),
// [, \, ], ^, _, ` (U+005B0060),
// {, |, }, or ~ (U+007B007E).
return c <= 127 && (
IsInInclusiveRange(c, 33, 47) ||
IsInInclusiveRange(c, 58, 64) ||
IsInInclusiveRange(c, 91, 96) ||
IsInInclusiveRange(c, 123, 126));
// An ASCII punctuation character is !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~.
switch (c)
{
case '!':
case '"':
case '#':
case '$':
case '%':
case '&':
case '\'':
case '(':
case ')':
case '*':
case '+':
case ',':
case '-':
case '.':
case '/':
case ':':
case ';':
case '<':
case '=':
case '>':
case '?':
case '@':
case '[':
case '\\':
case ']':
case '^':
case '_':
case '`':
case '{':
case '|':
case '}':
case '~':
return true;
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -4,7 +4,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Markdig.Helpers
{
@@ -194,7 +193,7 @@ namespace Markdig.Helpers
{
return false;
}
if (IsSpaceOrSpecialHtmlChar(c))
if (c == ' ' || c == '\n' || c == '"' || c == '\'' || c == '=' || c == '<' || c == '>' || c == '`')
{
break;
}
@@ -203,26 +202,6 @@ namespace Markdig.Helpers
c = text.NextChar();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool IsSpaceOrSpecialHtmlChar(char c)
{
if (c > '>')
{
return c == '`';
}
const long BitMask =
(1L << ' ')
| (1L << '\n')
| (1L << '"')
| (1L << '\'')
| (1L << '=')
| (1L << '<')
| (1L << '>');
return (BitMask & (1L << c)) != 0;
}
// We need at least one char after '='
if (matchCount == 0)
{
@@ -248,7 +227,7 @@ namespace Markdig.Helpers
while (true)
{
c = text.NextChar();
if (c.IsAlphaNumeric() || IsCharToAppend(c))
if (c.IsAlphaNumeric() || c == '_' || c == ':' || c == '.' || c == '-')
{
builder.Append(c);
}
@@ -256,23 +235,6 @@ namespace Markdig.Helpers
{
break;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool IsCharToAppend(char c)
{
if ((uint)(c - '-') > '_' - '-')
{
return false;
}
const long BitMask =
(1L << '_')
| (1L << ':')
| (1L << '.')
| (1L << '-');
return (BitMask & (1L << c)) != 0;
}
}
hasAttribute = true;

View File

@@ -55,7 +55,7 @@ namespace Markdig.Helpers
public static void ArgumentOutOfRangeException(string paramName) => throw new ArgumentOutOfRangeException(paramName);
[DoesNotReturn]
public static void ArgumentOutOfRangeException(string message, string paramName) => throw new ArgumentOutOfRangeException(paramName, message);
public static void ArgumentOutOfRangeException(string message, string paramName) => throw new ArgumentOutOfRangeException(message, paramName);
[DoesNotReturn]
public static void ArgumentOutOfRangeException_index() => throw new ArgumentOutOfRangeException("index");

View File

@@ -33,7 +33,7 @@ namespace Markdig.Parsers.Inlines
/// <summary>
/// The character of this emphasis.
/// </summary>
public char Character { get; }
public char Character { get; }
/// <summary>
/// The minimum number of character this emphasis is expected to have (must be >=1)