0
0
mirror of https://github.com/naturalcrit/homebrewery.git synced 2025-12-24 20:42:43 +00:00

Merge pull request #1433 from naturalcrit/moreV3Snippets

More v3 snippets
This commit is contained in:
Trevor Buckner
2021-07-11 16:59:13 -04:00
committed by GitHub
4 changed files with 169 additions and 78 deletions

View File

@@ -27,18 +27,34 @@ module.exports = [
},
{
name : 'Vertical Spacing',
icon : 'fas fa-times-circle',
gen : ''
icon : 'fas fa-arrows-alt-v',
gen : '\n::::\n'
},
{
name : 'Horizontal Spacing',
icon : 'fas fa-arrows-alt-h',
gen : ' {{width="100px"}} '
},
{
name : 'Wide Block',
icon : 'fas fa-times-circle',
gen : ''
icon : 'fas fa-window-maximize',
gen : dedent`\n
{{wide
Everything in here will be extra wide. Tables, text, everything!
Beware though, CSS columns can behave a bit weird sometimes. You may
have to rely on the automatic column-break rather than \`\column\` if
you mix columns and wide blocks on the same page.
}}
\n`
},
{
name : 'Image',
icon : 'fas fa-times-circle',
gen : ''
icon : 'fas fa-image',
gen : dedent`
<img
src='https://s-media-cache-ak0.pinimg.com/736x/4a/81/79/4a8179462cfdf39054a418efd4cb743e.jpg'
style='width:325px'/>
Credit: Kyounghwan Kim`
},
{
name : 'Background Image',

View File

@@ -1,4 +1,5 @@
const _ = require('lodash');
const dedent = require('dedent-tabs').default;
const getTOC = (pages)=>{
const add1 = (title, page)=>{
@@ -51,13 +52,13 @@ module.exports = function(brew){
const pages = brew.text.split('\\page');
const TOC = getTOC(pages);
const markdown = _.reduce(TOC, (r, g1, idx1)=>{
r.push(`- **[${idx1 + 1} ${g1.title}](#p${g1.page})**`);
r.push(`\t\t- ### [{{ ${g1.title}}}{{ ${g1.page}}}](#p${g1.page})`);
if(g1.children.length){
_.each(g1.children, (g2, idx2)=>{
r.push(` - [${idx1 + 1}.${idx2 + 1} ${g2.title}](#p${g2.page})`);
r.push(`\t\t - #### [{{ ${g2.title}}}{{ ${g2.page}}}](#p${g2.page})`);
if(g2.children.length){
_.each(g2.children, (g3, idx3)=>{
r.push(` - [${idx1 + 1}.${idx2 + 1}.${idx3 + 1} ${g3.title}](#p${g3.page})`);
r.push(`\t\t - [{{ ${g3.title}}}{{ ${g3.page}}}](#p${g3.page})`);
});
}
});
@@ -65,8 +66,11 @@ module.exports = function(brew){
return r;
}, []).join('\n');
return `<div class='toc'>
##### Table Of Contents
return dedent`
{{toc
# Table Of Contents
${markdown}
</div>\n`;
}}
\n`;
};

View File

@@ -505,19 +505,60 @@ body {
-webkit-column-break-inside : avoid;
page-break-inside : avoid;
break-inside : avoid;
h1 {
text-align : center;
margin-bottom : 0.1cm;
}
a{
color : black;
display : table;
color : inherit;
text-decoration : none;
&:hover{
text-decoration : underline;
}
}
h4 {
margin-top : 0.1cm;
}
ul{
padding-left : 0;
list-style-type : none;
}
&>ul>li{
margin-bottom : 10px;
li + li h3 {
margin-top : 0.26cm;
line-height : 1em
}
h3 span:first-child::after {
border : none;
}
span {
display : table-cell;
&:first-child {
position : relative;
overflow : hidden;
&::after {
content : "";
position : absolute;
bottom : 0.08cm; /* Set as you want */
margin-left : 0.06cm; /* Spacing before dot leaders */
width : 100%;
border-bottom : 0.05cm dotted #000;
}
}
&:last-child {
font-family : BookInsanityRemake;
font-size : 0.34cm;
font-weight : normal;
color : black;
text-align : right;
vertical-align : bottom; /* Keep Price text bottom-aligned */
width : 1%;
padding-left : 0.06cm; /* Spacing after dot leaders */
/*white-space: nowrap; /* Uncomment if needed */
}
}
ul { /*List indent*/
margin-left : 1em;
}
}
}
@@ -528,8 +569,8 @@ body {
.block {
break-inside : avoid;
}
.inline-block {
display : block;
.inline {
display : inline-block;
}
div {
column-gap : 0.5cm; //Default spacing if a div uses multicolumns

View File

@@ -19,74 +19,105 @@ renderer.paragraph = function(text){
let match;
if(text.startsWith('<div') || text.startsWith('</div'))
return `${text}`;
else if(match = text.match(/(^|^.*?\n)<span class="inline([^>]*><\/span>)$/))
return `<p>${match[1]}</p><span class="inline-block"${match[2]}`;
else
else if(match = text.match(/(^|^.*?\n)<span class="inline(.*?<\/span>)$/)) {
return `${match[1].trim() ? `<p>${match[1]}</p>` : ''}<span class="inline-block${match[2]}`;
} else
return `<p>${text}</p>\n`;
};
// Mustache-style Divs {{class \n content ... \n}}
let blockCount = 0;
const blockRegex = /^ *{{(?:="[\w,\-. ]*"|[^"'\s])*$|^ *}}$/gm;
const inlineFullRegex = /{{[^\n]*}}/g;
const inlineRegex = /{{(?:="[\w,\-. ]*"|[^"'{}}\s])*\s*|}}/g;
renderer.text = function(text){
const newText = text.replaceAll('&quot;', '"');
let matches;
if(matches = newText.match(inlineFullRegex)) {
//SPAN - INLINE
matches = newText.match(inlineRegex);
let matchIndex = 0;
const res = _.reduce(newText.split(inlineRegex), (r, splitText)=>{
if(splitText) r.push(Markdown.parseInline(splitText, { renderer: renderer }));
const block = matches[matchIndex] ? matches[matchIndex].trimLeft() : '';
if(block && block.startsWith('{{')) {
const values = processStyleTags(block.substring(2));
r.push(`<span class="inline ${values}>`);
blockCount++;
} else if(block == '}}' && blockCount !== 0){
r.push('</span>');
blockCount--;
const mustacheSpans = {
name : 'mustacheSpans',
level : 'inline', // Is this a block-level or inline-level tokenizer?
start(src) { return src.match(/{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const completeSpan = /^{{[^\n]*}}/; // Regex for the complete token
const inlineRegex = /{{(?:="[\w,\-. ]*"|[^"'{}\s])*\s*|}}/g;
const match = completeSpan.exec(src);
if(match) {
//Find closing delimiter
let blockCount = 0;
let tags = '';
let endIndex = 0;
let delim;
while (delim = inlineRegex.exec(match[0])) {
if(delim[0].startsWith('{{')) {
tags = tags || ` ${processStyleTags(delim[0].substring(2))}`;
blockCount++;
} else if(delim[0] == '}}' && blockCount !== 0) {
blockCount--;
if(blockCount == 0) {
endIndex = inlineRegex.lastIndex;
break;
}
}
}
matchIndex++;
if(endIndex) {
const raw = src.slice(0, endIndex);
const text = raw.slice((raw.indexOf(' ')+1) || -2, -2);
return r;
}, []).join('');
return `${res}`;
} else if(matches = newText.match(blockRegex)) {
//DIV - BLOCK-LEVEL
let matchIndex = 0;
const res = _.reduce(newText.split(blockRegex), (r, splitText)=>{
if(splitText) r.push(Markdown.parseInline(splitText, { renderer: renderer }));
const block = matches[matchIndex] ? matches[matchIndex].trimLeft() : '';
if(block && block.startsWith('{')) {
const values = processStyleTags(block.substring(2));
r.push(`<div class="block ${values}">`);
blockCount++;
} else if(block == '}}' && blockCount !== 0){
r.push('</div>');
blockCount--;
}
matchIndex++;
return r;
}, []).join('');
return res;
} else {
if(!matches) {
return `${text}`;
return { // Token to generate
type : 'mustacheSpans', // Should match "name" above
raw : raw, // Text to consume from the source
text : text, // Additional custom properties
tags : tags,
tokens : this.inlineTokens(text) // inlineTokens to process **bold**, *italics*, etc.
};
}
}
},
renderer(token) {
return `<span class="inline${token.tags}>${this.parseInline(token.tokens)}</span>`; // parseInline to turn child tokens into HTML
}
};
const mustacheDivs = {
name : 'mustacheDivs',
level : 'block',
start(src) { return src.match(/^ *{{[^{]/)?.index; }, // Hint to Marked.js to stop and check for a match
tokenizer(src, tokens) {
const completeBlock = /^ *{{.*\n *}}/s; // Regex for the complete token
const blockRegex = /^ *{{(?:="[\w,\-. ]*"|[^"'{}\s])*$|^ *}}$/gm;
const match = completeBlock.exec(src);
if(match) {
//Find closing delimiter
let blockCount = 0;
let tags = '';
let endIndex = 0;
let delim;
while (delim = blockRegex.exec(match[0])?.[0].trim()) {
if(delim.startsWith('{{')) {
tags = tags || ` ${processStyleTags(delim.substring(2))}`;
blockCount++;
} else if(delim == '}}' && blockCount !== 0) {
blockCount--;
if(blockCount == 0) {
endIndex = blockRegex.lastIndex;
break;
}
}
}
if(endIndex) {
const raw = src.slice(0, endIndex);
const text = raw.slice((raw.indexOf('\n')+1) || -2, -2);
return { // Token to generate
type : 'mustacheDivs', // Should match "name" above
raw : raw, // Text to consume from the source
text : text, // Additional custom properties
tags : tags,
tokens : this.inline(this.blockTokens(text))
};
}
}
},
renderer(token) {
return `<div class="block${token.tags}>${this.parse(token.tokens)}</div>`; // parseInline to turn child tokens into HTML
}
};
Markdown.use({ extensions: [mustacheSpans, mustacheDivs] });
//Fix local links in the Preview iFrame to link inside the frame
renderer.link = function (href, title, text) {
let self = false;
@@ -177,13 +208,12 @@ const processStyleTags = (string)=>{
const id = _.remove(tags, (tag)=>tag.startsWith('#')).map((tag)=>tag.slice(1))[0];
const classes = _.remove(tags, (tag)=>!tag.includes('"'));
const styles = tags.map((tag)=>tag.replace(/="(.*)"/g, ':$1;'));
return `${classes.join(' ')}" ${id ? `id="${id}"` : ''} ${styles ? `style="${styles.join(' ')}"` : ''}`;
return `${classes.join(' ')}" ${id ? `id="${id}"` : ''} ${styles.length ? `style="${styles.join(' ')}"` : ''}`;
};
module.exports = {
marked : Markdown,
render : (rawBrewText)=>{
blockCount = 0;
rawBrewText = rawBrewText.replace(/^\\column$/gm, `<div class='columnSplit'></div>`)
.replace(/^(:+)$/gm, (match)=>`${`<div class='blank'></div>`.repeat(match.length)}\n`)
.replace(/(?:^|>) *:([^:\n]*):([^\n]*)\n/gm, (match, term, def)=>`<dt>${Markdown.parseInline(term)}</dt><dd>${def}</dd>`)