Skip to content

Commit 56d2357

Browse files
committed
improving code highlight for blog
1 parent 543f095 commit 56d2357

File tree

8 files changed

+174
-11
lines changed

8 files changed

+174
-11
lines changed

content/blog/wanderlust.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,25 @@ title: Wanderlust
33
date: 2019-08-27T18:44:24.217Z
44
tags: 'travel, philosophy, hobby'
55
---
6-
Sed ut perspiciatis unde omnis iste natus error sit voluptatem #accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
6+
Sed ut perspiciatis unde omnis iste natus error sit voluptatem #accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.
77

88
## Heading 1
99

1010
![](/assets/brett-jordan-1329359-unsplash.jpg)
1111

1212
## Heading 2
1313

14-
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
14+
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.
1515

16-
```
16+
```js
1717
navigator.serviceWorker.register('/sw.js').then(reg => {
1818
reg.onupdatefound = () => {
1919
const w = reg.installing;
2020
w.onstatechange = () => {
2121
if (w.state === 'installed' && navigator.serviceWorker.controller) {
2222
// probably best to avoid reloading if someone has clicked
2323
if (hasInteracted) showUpdateToast();
24-
24+
2525
location.reload();
2626
}
2727
};

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"private": true,
33
"name": "blog",
4-
"version": "0.0.0",
4+
"version": "0.1.0",
55
"license": "MIT",
66
"scripts": {
77
"start": "per-env",
@@ -27,8 +27,9 @@
2727
"jest-preset-preact": "^1.0.0",
2828
"markdown": "^0.5.0",
2929
"per-env": "^1.0.2",
30-
"preact-cli": "^3.0.0-rc.6",
30+
"preact-cli": "^3.0.0-rc.7",
3131
"preact-render-spy": "^1.2.1",
32+
"react-syntax-highlighter": "^12.2.1",
3233
"webpack-bundle-analyzer": "^3.4.1"
3334
},
3435
"dependencies": {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { h } from 'preact';
2+
import { useState } from 'preact/hooks';
3+
4+
import { vs } from 'react-syntax-highlighter/dist/esm/styles/prism';
5+
6+
export function FormattedCodeBlock(props) {
7+
const [component, setComponent] = useState(null);
8+
if (component) {
9+
return component;
10+
}
11+
throw new Promise(resolve => {
12+
let language = null;
13+
const highlighter = import('react-syntax-highlighter/dist/esm/prism-light');
14+
let languageSyntax;
15+
switch (props.class) {
16+
case 'lang-js':
17+
language = 'javascript';
18+
languageSyntax = import('react-syntax-highlighter/dist/esm/languages/prism/javascript');
19+
break;
20+
case 'lang-html':
21+
language = 'html';
22+
languageSyntax = import('react-syntax-highlighter/dist/esm/languages/prism/markup');
23+
break;
24+
case 'lang-css':
25+
language = 'css';
26+
languageSyntax = import('react-syntax-highlighter/dist/esm/languages/prism/css');
27+
break;
28+
case 'lang-ts':
29+
language = 'typescript';
30+
languageSyntax = import('react-syntax-highlighter/dist/esm/languages/prism/typescript');
31+
break;
32+
}
33+
Promise.all([highlighter, languageSyntax]).then(values => {
34+
const [SyntaxHighlighter, languageHighlighter] = values.map(m => m ? m.default: null);
35+
getFormattedCodeBlock(SyntaxHighlighter, languageHighlighter, language, setComponent, resolve, props);
36+
});
37+
});
38+
}
39+
40+
function getFormattedCodeBlock(SyntaxHighlighter, languageHighlighter, language, setState, resolve, props) {
41+
language && SyntaxHighlighter.registerLanguage(language, languageHighlighter);
42+
setState(
43+
<SyntaxHighlighter language={language} style={vs}>
44+
{props.children}
45+
</SyntaxHighlighter>
46+
);
47+
resolve();
48+
}

src/routes/blog/index.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { h } from 'preact';
2+
import { Suspense } from 'preact/compat';
23
import { usePrerenderData } from '@preact/prerender-data-provider';
34
import Markdown from 'markdown-to-jsx';
5+
import { FormattedCodeBlock } from './formatted-code-block';
6+
47
import style from './style';
58

69
const blogs = (props) => {
@@ -12,6 +15,18 @@ const blogs = (props) => {
1215
);
1316
};
1417

18+
function CodeBlock(props) {
19+
const fallback = <pre><code>{props.children}</code></pre>;
20+
if (typeof window === 'undefined') {
21+
return (fallback);
22+
}
23+
return (
24+
<Suspense fallback={fallback}>
25+
<FormattedCodeBlock {...props} />
26+
</Suspense>
27+
);
28+
}
29+
1530
function getBlogBody(data, isLoading) {
1631
if (isLoading) {
1732
return (
@@ -35,7 +50,14 @@ function getBlogBody(data, isLoading) {
3550
{ details.subtitle && <caption class={style.blogsubtitle}>{details.subtitle}</caption> }
3651
{ details.cover && <div class={style.blogcover} style={`background-image:url(${details.cover})`} /> }
3752
<div class={style.blogbody}>
38-
<Markdown>{ content }</Markdown>
53+
<Markdown options={{
54+
overrides: {
55+
code: {
56+
component: CodeBlock
57+
}
58+
}
59+
}}
60+
>{ content }</Markdown>
3961
</div>
4062
</div>
4163
);

src/routes/blog/style.css

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,46 @@
2020
max-width: 100%;
2121
}
2222

23+
.blogbody a {
24+
color: #000;
25+
text-decoration: underline;
26+
}
27+
2328
.blogbody code {
29+
display: block;
2430
max-width: 100%;
31+
color: rgb(57, 58, 52);
32+
font-family: Consolas, "Bitstream Vera Sans Mono", "Courier New", Courier, monospace;
33+
direction: ltr;
34+
text-align: left;
35+
white-space: pre;
36+
word-spacing: normal;
37+
word-break: normal;
38+
font-size: 0.95em;
39+
line-height: 1.2em;
40+
tab-size: 4;
41+
hyphens: none;
2542
}
2643

27-
.blogbody pre {
44+
.blogbody pre pre {
2845
max-width: 100%;
2946
overflow: scroll;
47+
color: rgb(57, 58, 52);
48+
font-family: Consolas, "Bitstream Vera Sans Mono", "Courier New", Courier;
49+
direction: ltr;
50+
text-align: left;
51+
white-space: pre;
52+
word-spacing: normal;
53+
word-break: normal;
54+
font-size: 0.95em;
55+
line-height: 1.2em;
56+
tab-size: 4;
57+
hyphens: none;
58+
padding: 1em;
59+
margin: 0.5em 0px;
60+
overflow: auto;
61+
border: 1px solid rgb(221, 221, 221);
62+
background-color: white;
3063
}
3164

3265
.blogsubtitle {

src/static/admin.html

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,32 @@
99
<body>
1010
<!-- Include the script that builds the page and powers Netlify CMS -->
1111
<script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script>
12+
<script src="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.17.1/build/highlight.min.js"></script>
13+
<script type="module">
14+
import htm from 'https://unpkg.com/htm?module'
15+
const html = htm.bind(h);
16+
const PostPreview = createClass({
17+
render: function() {
18+
const {entry, widgetFor} = this.props;
19+
const image = entry.getIn(['data', 'cover'])
20+
let imageMarkup = '';
21+
if (image) {
22+
imageMarkup = html`<div><img src='${image.toString()}'/></div>`;
23+
}
24+
return (
25+
html`
26+
<div>
27+
<h1 className='blogTitle'>${entry.getIn(['data', 'title'])}</h1>
28+
<caption className='blogSubTitle'>${entry.getIn(['data', 'subtitle'])}</caption>
29+
${imageMarkup}
30+
<div className='text'>${widgetFor('body')}</div>
31+
</div>
32+
`
33+
);
34+
}
35+
});
36+
CMS.registerPreviewStyle("/preview.css");
37+
CMS.registerPreviewTemplate("pages", PostPreview);
38+
</script>
1239
</body>
13-
</html>
40+
</html>

src/static/config.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ collections:
1212
fields:
1313
- { label: "Title", name: "title", widget: "string"}
1414
- { label: "Publish Date", name: "date", widget: "datetime" }
15-
- { label: "Subtitle", name: "subtitle", widget: "string"}
16-
- { label: "Cover", name: "cover", widget: "image"}
15+
- { label: "Subtitle", name: "subtitle", widget: "string", required: false}
16+
- { label: "Cover", name: "cover", widget: "image", required: false}
1717
- { label: "Tags", name: "tags", widget: "string" }
1818
- { label: "Body", name: "body", widget: "markdown"}
19+

src/static/preview.css

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
html {
2+
font-family: Helvetica Neue,arial,sans-serif;
3+
color: #333;
4+
max-width: 728px;
5+
width: 100%;
6+
margin: 0 auto 10em;
7+
line-height: 1.6rem;
8+
}
9+
10+
img {
11+
max-width: 100%;
12+
}
13+
14+
a {
15+
color: #000;
16+
}
17+
18+
.blogTitle {
19+
font-size: 2.2rem;
20+
font-weight: 400;
21+
margin-bottom: 8px;
22+
line-height: 1;
23+
}
24+
25+
.blogSubTitle{
26+
color: #aaa;
27+
display: block;
28+
text-align: left;
29+
font-size: 1.2rem;
30+
margin-bottom: 2rem;
31+
}

0 commit comments

Comments
 (0)