fix lists

add test
This commit is contained in:
Talon Poole 2021-02-02 22:02:09 +00:00
parent 1bcedc2042
commit 86e9e8b660
7 changed files with 95 additions and 12 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@ node_modules/
capsule/ capsule/
gmi.js gmi.js
gmi.min.js gmi.min.js
example/test.html

View file

@ -14,6 +14,9 @@ format:
./node_modules/prettier/bin-prettier.js --write gmi.css ./node_modules/prettier/bin-prettier.js --write gmi.css
./node_modules/prettier/bin-prettier.js --write *.js !*.min.js ./node_modules/prettier/bin-prettier.js --write *.js !*.min.js
example/test.html: example/test.gmi
./test.sh
clean: clean:
rm -rf gmi.min.* gmi-web.1 node_modules rm -rf gmi.min.* gmi-web.1 node_modules

View file

@ -11,8 +11,8 @@ The generated HTML document must have a `<head>` tag with _at minimum_ the follo
```html ```html
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta language="en" />
<!-- set this accordingly! --> <!-- set this accordingly! -->
<meta language="en" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
</head> </head>
``` ```
@ -84,7 +84,7 @@ Currently approaching a v1 release 🎉 Would you like to help test the RC? _You
Install the binary via npm. Install the binary via npm.
```sh ```sh
npm install --global gmi-web-cli@1.0.4-rc.1 npm install --global gmi-web-cli
``` ```
Render .html for all the .gmi files in the current directory Render .html for all the .gmi files in the current directory

42
example/expected.html Normal file
View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html style="">
<head>
<meta charset="utf-8">
<meta language="en">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="color-scheme" content="dark light">
<style>:root{--foreground:black;--background:white;--p-size:1.25rem;--p-indent:0rem;--p-line-height:1.5;--a-size:var(--p-size);--pre-size:1rem;--pre-line-height:1;--h1-size:3rem;--h2-size:2.25rem;--h3-size:1.5rem;--heading-line-height:1.25;--ul-size:var(--p-size);--ul-line-height:1.25;--blockquote-size:var(--p-size);--blockquote-line-height:1.25;--mono:Consolas,monaco,monospace;--serif:georgia,times,serif;--sans-serif:-apple-system,BlinkMacSystemFont,"avenir next",avenir,helvetica,"helvetica neue",ubuntu,roboto,noto,"segoe ui",arial,sans-serif}body{max-width:48rem;padding:.5rem;margin:0 auto}a,audio,blockquote,h1,h2,h3,img,p,pre,ul,video{display:block;max-width:100%;margin:0;padding:0;overflow-wrap:anywhere}h1,h2,h3{font-family:var(--sans-serif);line-height:var(--heading-line-height)}p{font-size:var(--p-size);font-family:var(--serif);text-indent:var(--p-indent);line-height:var(--p-line-height)}a::before{font-size:var(--p-size);font-family:var(--mono);content:"";padding-right:.25rem;vertical-align:middle}a{font-size:var(--p-size);font-family:var(--serif);text-decoration:none}pre{font-size:var(--pre-size);font-family:var(--mono);line-height:var(--pre-line-height);padding:1.25rem;overflow-y:auto}h1{font-size:var(--h1-size)}h2{font-size:var(--h2-size)}h3{font-size:var(--h3-size)}ul{font-size:var(--p-size);font-family:var(--serif);line-height:var(--ul-line-height);list-style-type:none}li::before{font-size:var(--p-size);font-family:var(--mono);content:"*";vertical-align:middle;padding-right:.5rem}blockquote{font-size:var(--p-size);font-family:var(--serif);line-height:var(--blockquote-line-height);padding-left:.75rem}pre+blockquote{padding-top:.5rem;padding-bottom:.5rem}a,blockquote,body,h1,h2,h3,html,p,pre::-moz-selection,pre::selection,ul{color:var(--foreground);background-color:var(--background)}blockquote{border-left:.5rem solid var(--foreground)}::-moz-selection,::selection,a:hover,pre{color:var(--background);background-color:var(--foreground)}@media (prefers-color-scheme:dark){a,blockquote,body,h1,h2,h3,html,p,pre::-moz-selection,pre::selection,ul{color:var(--background);background-color:var(--foreground)}blockquote{border-left:.5rem solid var(--background)}::-moz-selection,::selection,a:hover,pre{color:var(--foreground);background-color:var(--background)}}
</style>
<title>heading 1</title>
</head>
<body>
<h1>heading 1</h1>
<h2>heading 2</h2>
<h3>heading 3</h3>
<p>checkout this empty line:</p>
<p><br></p>
<ul>
<li>and</li>
<li>this</li>
<li>list</li>
</ul>
<p><br></p>
<blockquote>here&#39;s what a blockquote is like</blockquote>
<p><br></p>
<pre title="pre tags can have alt text">
preformatted text
means that it already has formatting
which means it should show
as is
</pre>
<p><br></p>
<p>&lt;b&gt;watch out!&lt;/b&gt; a gemtext line could have html in it that you&#39;ll need to escape!</p>
<p><br></p>
<img src="https://www.learningcontainer.com/wp-content/uploads/2020/07/Large-Sample-Image-download-for-Testing.jpg" title="JPG image that can render inline!"/>
<audio controls src="https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3" title="MP3 audio that can render inline!"></audio>
<video controls src="https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4" title="MP4 Video that can render inline!"/></video>
</body>
</html>

26
example/test.gmi Normal file
View file

@ -0,0 +1,26 @@
# heading 1
## heading 2
### heading 3
checkout this empty line:
* and
* this
* list
> here's what a blockquote is like
```pre tags can have alt text
preformatted text
means that it already has formatting
which means it should show
as is
```
<b>watch out!</b> a gemtext line could have html in it that you'll need to escape!
=> https://www.learningcontainer.com/wp-content/uploads/2020/07/Large-Sample-Image-download-for-Testing.jpg JPG image that can render inline!
=> https://www.learningcontainer.com/wp-content/uploads/2020/02/Kalimba.mp3 MP3 audio that can render inline!
=> https://www.learningcontainer.com/wp-content/uploads/2020/05/sample-mp4-file.mp4 MP4 Video that can render inline!

9
test.sh Executable file
View file

@ -0,0 +1,9 @@
./cli.js --lang en --images --audio --video "example/*.gmi"
if cmp -s "example/test.html" "example/expected.html"; then
printf "PASS: test.html matches expected.html!\n"
else
printf "FAIL: test.html DOES NOT match expected.html!\n"
cmp "example/test.html" "example/expected.html"
diff "example/test.html" "example/expected.html"
exit 1
fi

View file

@ -9,14 +9,17 @@ const AUDIO_EXT = (exports.AUDIO_EXT = /\.(mp3|wav|aac|aacp|mpeg|off|flac)$/);
const VIDEO_EXT = (exports.VIDEO_EXT = /\.(mp4|webm)$/); const VIDEO_EXT = (exports.VIDEO_EXT = /\.(mp4|webm)$/);
const BASE_STYLE = (exports.BASE_STYLE = const BASE_STYLE = (exports.BASE_STYLE =
"<style>p,a,pre,h1,h2,h3,ul,blockquote,img,audio,video{display:block;max-width:100%;margin:0;padding:0;overflow-wrap:anywhere;}</style>"); "<style>p,a,pre,h1,h2,h3,ul,blockquote,img,audio,video{display:block;max-width:100%;margin:0;padding:0;overflow-wrap:anywhere;}</style>");
const GMI_CSS = fs.readFileSync(
path.resolve(__dirname, "./gmi.min.css"),
"utf8"
);
const toHTML = (exports.toHTML = (file, options) => { const toHTML = (exports.toHTML = (file, options) => {
const tokens = JSON.parse(file.contents.toString("utf8")); const tokens = JSON.parse(file.contents.toString("utf8"));
const title = tokens[0].h1; const title = tokens[0].h1;
return `<!DOCTYPE html> return `<!DOCTYPE html>
<html style="${options.override}"> <html style="${options.override}">
${head(file.path, title, options)} ${head(file.path, title, options)}<body>
<body>
${gemtext(tokens, options)} ${gemtext(tokens, options)}
</body> </body>
</html> </html>
@ -38,10 +41,7 @@ function head(file, title, options) {
<meta name="viewport" content="width=device-width,initial-scale=1">${ <meta name="viewport" content="width=device-width,initial-scale=1">${
!options.css !options.css
? BASE_STYLE ? BASE_STYLE
: `\n<meta name="color-scheme" content="dark light">\n<style>${fs.readFileSync( : `\n<meta name="color-scheme" content="dark light">\n<style>${GMI_CSS}</style>`
path.resolve(__dirname, "./gmi.min.css"),
"utf8"
)}</style>`
}${ }${
!options.canonical !options.canonical
? "" ? ""
@ -68,9 +68,11 @@ function gemtext(tokens, options) {
} else if (cursor.li) { } else if (cursor.li) {
body.push(`<ul>`); body.push(`<ul>`);
const closing = tokens.findIndex((token) => !token.li); const closing = tokens.findIndex((token) => !token.li);
body = body.concat(tokens.slice(0, closing).map(line)); body = body
.concat([line(cursor)])
.concat(tokens.slice(0, closing).map(line));
body.push("</ul>"); body.push("</ul>");
tokens = tokens.slice(closing + 1); tokens = tokens.slice(closing);
} else { } else {
body.push(line(cursor, options)); body.push(line(cursor, options));
} }
@ -82,7 +84,7 @@ function gemtext(tokens, options) {
function line( function line(
{ text, href, title, pre, alt, h1, h2, h3, li, quote }, { text, href, title, pre, alt, h1, h2, h3, li, quote },
{ images, audio, video } { images, audio, video } = {}
) { ) {
if (text) return `<p>${escape(text)}</p>`; if (text) return `<p>${escape(text)}</p>`;
if (href) { if (href) {