From 14f2dc6f563004f3d1aa57d994733f396dd61045 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isabella=20Sko=C5=99epov=C3=A1?= <isabella@skorepova.info> Date: Wed, 8 Jan 2020 12:33:40 +0100 Subject: [PATCH] Implement article --- theme-source/partials/base.js | 5 +- theme-source/partials/list.js | 81 +------------------ theme-source/templates/article.js | 124 ++++++++++++++++++++++++++++++ theme-source/utils.js | 81 +++++++++++++++++++ 4 files changed, 210 insertions(+), 81 deletions(-) create mode 100644 theme-source/templates/article.js create mode 100644 theme-source/utils.js diff --git a/theme-source/partials/base.js b/theme-source/partials/base.js index 2826a8be..35c75ff0 100644 --- a/theme-source/partials/base.js +++ b/theme-source/partials/base.js @@ -3,17 +3,20 @@ import { SymbolSearch, SymbolMenu, SymbolFacebook } from './svgs' import { Search } from './search' export function Base({ + prehead = null, head = null, metadata = {}, canonicalURL, config, children, footerlink = null, + bodyClassName, }) { return ( <html lang="en"> <head> <meta httpEquiv="Content-Type" content="text/html; charset=UTF-8" /> + {prehead} <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0" @@ -157,7 +160,7 @@ export function Base({ ) : null} {head} </head> - <body> + <body className={bodyClassName}> {/* % block bodyattr %}{% endblock % */} <div id="all"> {/* Top nav */} diff --git a/theme-source/partials/list.js b/theme-source/partials/list.js index 8c250f0b..81c48901 100644 --- a/theme-source/partials/list.js +++ b/theme-source/partials/list.js @@ -2,86 +2,7 @@ import React from 'react' import moment from 'moment' import { Paginator } from './paginator' import { SymbolBackward, SymbolForward } from './svgs' - -function normalize(value, defaultValue) { - if (value === null || value === undefined || value === false) { - return defaultValue - } - return value -} - -function truncate(input_, length_, killwords, end) { - let input = normalize(input_, '') - const length = length_ || 255 - - if (input.length <= length) { - return input - } - - if (killwords) { - input = input.substring(0, length) - } else { - let idx = input.lastIndexOf(' ', length) - if (idx === -1) { - idx = length - } - - input = input.substring(0, idx) - } - - input += end !== undefined && end !== null ? end : '...' - return input -} - -function trim(str) { - return str.replace(/^\s*|\s*$/g, '') -} - -function striptags(input_, preserveLinebreaks) { - const input = normalize(input_, '') - const tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|<!--[\s\S]*?-->/gi - const trimmedInput = trim(input.replace(tags, '')) - let res = '' - if (preserveLinebreaks) { - res = trimmedInput - .replace(/^ +| +$/gm, '') // remove leading and trailing spaces - .replace(/ +/g, ' ') // squash adjacent spaces - .replace(/(\r\n)/g, '\n') // normalize linebreaks (CRLF -> LF) - .replace(/\n\n\n+/g, '\n\n') // squash abnormal adjacent linebreaks - } else { - res = trimmedInput.replace(/\s+/gi, ' ') - } - return res -} - -function dateFilter(date, format) { - let result - const errs = [] - const args = [] - let obj - Array.prototype.push.apply(args, arguments) - try { - obj = moment.utc(date) - } catch (err) { - errs.push(err) - } - if (obj) { - try { - if (obj[format] && typeof obj[format] === 'function') { - result = obj[format].apply(obj, args.slice(2)) - } else { - result = obj.format(format) - } - } catch (err) { - errs.push(err) - } - } - - if (errs.length) { - return errs.join('\n') - } - return result -} +import { dateFilter, truncate, striptags } from '../utils' function relURL(filename, dir_) { let dir = dir_ diff --git a/theme-source/templates/article.js b/theme-source/templates/article.js new file mode 100644 index 00000000..c5b742aa --- /dev/null +++ b/theme-source/templates/article.js @@ -0,0 +1,124 @@ +import React from 'react' +import url from 'url' +import { Base } from '../partials/base' +import { dateFilter, truncate, striptags } from '../utils' + +export default function Article({ + metadata, + content, + config, + file, + canonicalURL, +}) { + return ( + <Base + metadata={metadata} + config={config} + prehead={ + <> + <meta property="og:type" content="article" /> + <meta + property="article:published_time" + content={dateFilter(metadata.published)} + /> + {metadata.image && ( + <meta + property="og:image" + content={url.resolve(metadata.image, canonicalURL)} + /> + )} + <meta + property="og:description" + content={ + metadata.perex + ? metadata.perex + : metadata.perex_e + ? truncate(metadata.perex_e) + : content + ? truncate(striptags(content)) + : undefined + } + /> + </> + } + head={ + <> + <script + type="text/x-mathjax-config" + dangerouslySetInnerHTML={{ + __html: ` + MathJax.Hub.Config({ + extensions: ["tex2jax.js"], + jax: ["input/TeX", "output/HTML-CSS"], + tex2jax: { + inlineMath: [ ['$','$'], ["\\(","\\)"] ], + displayMath: [ ['$$','$$'], ["\\[","\\]"] ], + processEscapes: true + }, + elements: $("#content article"), + "HTML-CSS": { availableFonts: ["TeX"] }, + locale: "cs", + menuSettings: { + zoom: "Hover" + }, + MathEvents: { + hover: 0 + } + });`, + }} + /> + <script + type="text/javascript" + async + src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML&" + ></script> + </> + } + bodyClassName="type-article" + > + <div class="section container" id="content"> + <div class="row"> </div> + <div class="metadata"> + <h2 id="title">{metadata.title}</h2> + {metadata.nodate ? null : ( + <a + class="author" + style={{ color: '#a2a2a2', display: 'block' }} + class="black-text" + target="_blank" + href={`https://git.ok1kvk.cz/ok1kvk.cz/content/tree/master/content/articles/${file + .replace('clanek/', '') + .replace(/\/$/, '')}.md`} + > + {metadata.published ? ( + <> + <span style={{ color: '#626262' }}> + {dateFilter(metadata.published, 'D. M. YYYY')} + </span> + {metadata.author.gender === 'F' ? ' napsala ' : ' napsal '} + <span style={{ color: '#626262' }}> + {metadata.author.name} + </span> + </> + ) : ( + <>Článek nebyl publikován</> + )} + </a> + )} + <div class="tags"> + {metadata.tags.map(tag => + tag.url === 'tag/vse' ? null : ( + <a href={`${config.baseurl}/${tag.url}/1/`}> + <div class="chip">{tag.text}</div> + </a> + ), + )} + </div> + </div> + <article> + <p dangerouslySetInnerHTML={{ __html: content }} /> + </article> + </div> + </Base> + ) +} diff --git a/theme-source/utils.js b/theme-source/utils.js new file mode 100644 index 00000000..b9dc5018 --- /dev/null +++ b/theme-source/utils.js @@ -0,0 +1,81 @@ +import moment from 'moment' + +export function dateFilter(date, format) { + let result + const errs = [] + const args = [] + let obj + Array.prototype.push.apply(args, arguments) + try { + obj = moment.utc(date) + } catch (err) { + errs.push(err) + } + if (obj) { + try { + if (obj[format] && typeof obj[format] === 'function') { + result = obj[format].apply(obj, args.slice(2)) + } else { + result = obj.format(format) + } + } catch (err) { + errs.push(err) + } + } + + if (errs.length) { + return errs.join('\n') + } + return result +} + +function normalize(value, defaultValue) { + if (value === null || value === undefined || value === false) { + return defaultValue + } + return value +} + +export function truncate(input_, length_, killwords, end) { + let input = normalize(input_, '') + const length = length_ || 255 + + if (input.length <= length) { + return input + } + + if (killwords) { + input = input.substring(0, length) + } else { + let idx = input.lastIndexOf(' ', length) + if (idx === -1) { + idx = length + } + + input = input.substring(0, idx) + } + + input += end !== undefined && end !== null ? end : '...' + return input +} + +function trim(str) { + return str.replace(/^\s*|\s*$/g, '') +} + +export function striptags(input_, preserveLinebreaks) { + const input = normalize(input_, '') + const tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>|<!--[\s\S]*?-->/gi + const trimmedInput = trim(input.replace(tags, '')) + let res = '' + if (preserveLinebreaks) { + res = trimmedInput + .replace(/^ +| +$/gm, '') // remove leading and trailing spaces + .replace(/ +/g, ' ') // squash adjacent spaces + .replace(/(\r\n)/g, '\n') // normalize linebreaks (CRLF -> LF) + .replace(/\n\n\n+/g, '\n\n') // squash abnormal adjacent linebreaks + } else { + res = trimmedInput.replace(/\s+/gi, ' ') + } + return res +} -- GitLab