Skip to content

Commit

Permalink
Allow injected special tags to be self-closing
Browse files Browse the repository at this point in the history
Unlike the html script and style special tags, plugin authors may want
injected special tags to be able to be self-closing as well.
This can help unify the syntax used in the plugin, which makes for
better author usability of the plugin.

Let’s allow injected special tags to be self-closing.
  • Loading branch information
ang-zeyu committed Mar 8, 2020
1 parent 1451bd5 commit 441d658
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 8 deletions.
2 changes: 2 additions & 0 deletions docs/userGuide/usingPlugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ you do not wish to be parsed as html or markdown.
You can implement the `getSpecialTags` method to blacklist the content in these special tags from parsing,
removing such potential conflicts.

Unlike `<script>` and `<style>` tags, these special tags are also allowed to be self-closing.

- `getSpecialTags(pluginContext)`: Called during initial site generation to blacklist special tags.
- `pluginContext`: User provided parameters for the plugin. This can be specified in the `site.json`.
- Should return an array of string tag names to be blacklisted, with each tag name being at least 2 characters long.
Expand Down
22 changes: 22 additions & 0 deletions src/lib/markbind/src/patches/htmlparser2.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,28 @@ Tokenizer.prototype._stateBeforeSpecial = function(c) {
this._special = result + 1;
};

/**
* Removes the special state if the special tag was self-closed.
*/
Tokenizer.prototype._stateInSelfClosingTag = function(c) {
if (c === ">") {
this._cbs.onselfclosingtag();
this._state = TEXT;
this._sectionStart = this._index + 1;
if (this._special > 2) {
/*
We intentionally screw up if the special tag in question is script / style,
as per the html5 spec.
We allow injected special tags to be self-closed otherwise.
*/
this._special = SPECIAL_NONE;
}
} else if (!whitespace(c)) {
this._state = BEFORE_ATTRIBUTE_NAME;
this._index--;
}
};

/**
* Processes the _special flag and _nextSpecialTagMatchIndex state variable,
* returning a flag indicating whether the current special tag has finished matching or not.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ code.hljs:hover {
header.header-fixed {
position: fixed;
width: 100%;
z-index: 9999;
z-index: 1000;
}

/* #app is treated as the main container */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ code.hljs:hover {
header.header-fixed {
position: fixed;
width: 100%;
z-index: 9999;
z-index: 1000;
}

/* #app is treated as the main container */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ code.hljs:hover {
header.header-fixed {
position: fixed;
width: 100%;
z-index: 9999;
z-index: 1000;
}

/* #app is treated as the main container */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ code.hljs:hover {
header.header-fixed {
position: fixed;
width: 100%;
z-index: 9999;
z-index: 1000;
}

/* #app is treated as the main container */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ function preRender(content) {

module.exports = {
preRender,
getSpecialTags: () => ['testtag'],
getSpecialTags: () => ['testtag', 'testselfclosingtag'],
};
9 changes: 9 additions & 0 deletions test/functional/test_site_special_tags/expected/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ <h2 id="so-far-as-to-comply-with-the-commonmark-spec">So far as to comply with t
<p>/* ... */
</p>
</abc>
<hr>
<p>There are two self closing special tags below, which should display nothing, but are present in the output. There is then one special tag with both and opening and closing tag with some text in it (<code>lorem ipsum...</code>). Note that script
and style tags are still not allowed to be self-closing, as per the html5 spec.</p>
<testselfclosingtag></testselfclosingtag>
<testselfclosingtag></testselfclosingtag>
<testselfclosingtag>

Lorem ipsum lorem ipsum
</testselfclosingtag>
<hr>
<p>This should pass the htmlparser2 patch but not the markdown-it patch as it violates commonmark.<br> All lines after the first <code>!success</code> wrapping text will be wrapped in a <code>&lt;p&gt;...&lt;/p&gt;</code> tag as it is parsed as a
markdown paragraph.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,36 @@ pre > code.hljs {
counter-reset: line;
}

pre > code.hljs[heading] {
border-top-right-radius: 0;
}

.code-block {
position: relative;
}

.code-block-heading {
background-color: #f2f2ff;
border-radius: 6px 6px 0 0;
color: #8787a5;
float: right;
font-size: 85%;
line-height: 1;
max-width: 85%;
overflow-wrap: break-word;
padding: 0.25em 0.4em;
text-align: right;
}

.code-block-content {
clear: both;
display: block;
}

code > span.highlighted {
background: lavender;
}

kbd {
background-color: #fafbfc;
border: 1px solid #c6cbd1;
Expand Down Expand Up @@ -94,7 +124,7 @@ code.hljs:hover {
header.header-fixed {
position: fixed;
width: 100%;
z-index: 9999;
z-index: 1000;
}

/* #app is treated as the main container */
Expand Down Expand Up @@ -340,3 +370,74 @@ li.footnote-item:target {
top: 0;
width: 3em;
}

/* hide popover, modal, tooltip content */
[data-mb-html-for] {
display: none;
}

/* styles for triggers */
.trigger {
text-decoration: underline dotted;
}

.modal.mb-zoom {
-webkit-transform: scale(0.1);
-moz-transform: scale(0.1);
-ms-transform: scale(0.1);
transform: scale(0.1);
opacity: 0;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
transition: all 0.3s;
}

.modal.mb-zoom.show {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
opacity: 1;
}

/* "Copy" code block button */
pre {
position: relative;
}

.copy-btn {
background-color: #b4b4b9;
border-radius: 0.25rem;
color: #f8f8ff;
display: inline-block;
font-size: 75%;
line-height: 1;
padding: 0.25em 0.4em;
position: absolute;
right: 0.5em;
text-align: center;
top: 0.4em;
white-space: nowrap;
}

.copy-btn:hover {
color: #555;
}

.copy-btn-body {
align-items: center;
display: flex;
}

.copy-btn svg {
fill: currentColor;
margin-right: 0.4em;
}

.copy-btn-label {
font-size: 11px;
}

.copy-btn:focus {
outline: none;
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,39 @@ function setupWithSearch() {
setupSiteNav();
}

function makeInnerGetterFor(attribute) {
return (element) => {
const innerElement = element.querySelector(`[data-mb-html-for="${attribute}"]`);
return innerElement === null ? '' : innerElement.innerHTML;
};
}

function makeHtmlGetterFor(componentType, attribute) {
return (element) => {
const contentWrapper = document.getElementById(element.attributes.for.value);
return contentWrapper.dataset.mbComponentType === componentType
? makeInnerGetterFor(attribute)(contentWrapper) : '';
};
}

/* eslint-disable no-unused-vars */
/*
These getters are used by triggers to get their popover/tooltip content.
We need to create a completely new popover/tooltip for each trigger due to bootstrap-vue's implementation,
so this is how we retrieve our contents.
*/
const popoverContentGetter = makeHtmlGetterFor('popover', 'content');
const popoverHeaderGetter = makeHtmlGetterFor('popover', 'header');
const popoverInnerContentGetter = makeInnerGetterFor('content');
const popoverInnerHeaderGetter = makeInnerGetterFor('header');

const popoverGenerator = { title: popoverHeaderGetter, content: popoverContentGetter };
const popoverInnerGenerator = { title: popoverInnerHeaderGetter, content: popoverInnerContentGetter };

const tooltipContentGetter = makeHtmlGetterFor('tooltip', '_content');
const tooltipInnerContentGetter = makeInnerGetterFor('_content');
/* eslint-enable no-unused-vars */

if (enableSearch) {
setupWithSearch();
} else {
Expand Down
14 changes: 14 additions & 0 deletions test/functional/test_site_special_tags/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ some text

---

There are two self closing special tags below, which should display nothing, but are present in the output.
There is then one special tag with both and opening and closing tag with some text in it (`lorem ipsum...`).
Note that script and style tags are still not allowed to be self-closing, as per the html5 spec.

<testselfclosingtag />
<testselfclosingtag />

<testselfclosingtag>

Lorem ipsum lorem ipsum
</testselfclosingtag>

---

This should pass the htmlparser2 patch but not the markdown-it patch as it violates commonmark.<br>
All lines after the first `!success` wrapping text will be wrapped in a `<p>...</p>` tag as it is
parsed as a markdown paragraph.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ code.hljs:hover {
header.header-fixed {
position: fixed;
width: 100%;
z-index: 9999;
z-index: 1000;
}

/* #app is treated as the main container */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ code.hljs:hover {
header.header-fixed {
position: fixed;
width: 100%;
z-index: 9999;
z-index: 1000;
}

/* #app is treated as the main container */
Expand Down

0 comments on commit 441d658

Please sign in to comment.