Got independent scroll behavior that I wanted.
The good news is that I have the independent scroll behavior that I wanted. There are two bits of bad news. The first is that I don't UNDERSTAND why this particular configuration, with an extra level of nesting, made any difference. The bigger problem is that I still don't see the scroll bars showing up at all. And that annoys me. I should see them, right?
This commit is contained in:
parent
58cf0c9cbd
commit
bfb15b0f19
|
@ -0,0 +1,40 @@
|
||||||
|
+++
|
||||||
|
title = "Scala"
|
||||||
|
description = "Learning Scala"
|
||||||
|
date = 2022-06-09T14:45:57-0700
|
||||||
|
updated = 2022-06-09T14:45:57-0700
|
||||||
|
template = "section.html"
|
||||||
|
sort_by = "weight"
|
||||||
|
weight = 6
|
||||||
|
draft = false
|
||||||
|
[taxonomies]
|
||||||
|
documentation=["Reference"]
|
||||||
|
categories=["Scala", "Coursier", "Work-Related"]
|
||||||
|
+++
|
||||||
|
|
||||||
|
[Scala](https://scala-long.org) is a programming language. It has strong
|
||||||
|
typing, but is built on top of the JVM, so it has access to all of the JVM's
|
||||||
|
libraries.
|
||||||
|
|
||||||
|
## Installing
|
||||||
|
|
||||||
|
The easiest way to install Scala is to install
|
||||||
|
[Coursier](https://get-coursier.io/docs/overview), the Scala "artifact manager."
|
||||||
|
It installs versions of the Scala language, toolset, and even specific versions
|
||||||
|
of the JVM. Coursier is installed with a CURL command and, when that is
|
||||||
|
complete, your Scala environment can be initialized with
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ cs setup
|
||||||
|
```
|
||||||
|
|
||||||
|
## Emacs Tools
|
||||||
|
|
||||||
|
So far, I've installed:
|
||||||
|
|
||||||
|
- lsp-metal
|
||||||
|
- scala-mode
|
||||||
|
- sbt-mode
|
||||||
|
|
||||||
|
## Hello World
|
||||||
|
|
|
@ -2,42 +2,42 @@
|
||||||
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--step--2: calc(clamp(0.52rem, calc(0.43rem + 0.45vw), 0.72rem));
|
--step--2: clamp(0.52rem, calc(0.47rem + 0.23vw), 0.64rem);
|
||||||
--step--1: calc(clamp(0.63rem, calc(0.50rem + 0.63vw), 0.90rem));
|
--step--1: clamp(0.63rem, calc(0.56rem + 0.34vw), 0.80rem);
|
||||||
--step-0: calc(clamp(0.75rem, calc(0.58rem + 0.85vw), 1.13rem));
|
--step-0: clamp(0.75rem, calc(0.65rem + 0.49vw), 1.00rem);
|
||||||
--step-1: calc(clamp(0.90rem, calc(0.67rem + 1.15vw), 1.41rem));
|
--step-1: clamp(0.90rem, calc(0.76rem + 0.68vw), 1.25rem);
|
||||||
--step-2: calc(clamp(1.08rem, calc(0.77rem + 1.54vw), 1.76rem));
|
--step-2: clamp(1.08rem, calc(0.89rem + 0.94vw), 1.56rem);
|
||||||
--step-3: calc(clamp(1.30rem, calc(0.89rem + 2.05vw), 2.20rem));
|
--step-3: clamp(1.30rem, calc(1.04rem + 1.28vw), 1.95rem);
|
||||||
--step-4: calc(clamp(1.56rem, calc(1.01rem + 2.71vw), 2.75rem));
|
--step-4: clamp(1.56rem, calc(1.21rem + 1.73vw), 2.44rem);
|
||||||
--step-5: calc(clamp(1.87rem, calc(1.15rem + 3.56vw), 3.43rem));
|
--step-5: clamp(1.87rem, calc(1.40rem + 2.31vw), 3.05rem);
|
||||||
--half-step-0: calc(clamp(0.75rem, calc(0.58rem + 0.85vw), 1.13rem) / 2);
|
--half-step-0: calc(clamp(0.75rem, calc(0.58rem + 0.85vw), 1.13rem) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @link https://utopia.fyi/space/calculator?c=320,12,1.2,1024,24,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l|xs-m */
|
/* @link https://utopia.fyi/space/calculator?c=320,12,1.2,1024,24,1.25,5,2,&s=0.75|0.5|0.25,1.5|2|3|4|6,s-l|xs-m */
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--space-3xs: calc(clamp(0.19rem, calc(0.1rem + 0.43vw), 0.38rem));
|
--space-3xs: clamp(0.19rem, calc(0.16rem + 0.12vw), 0.25rem);
|
||||||
--space-2xs: calc(clamp(0.38rem, calc(0.2rem + 0.85vw), 0.75rem));
|
--space-2xs: clamp(0.38rem, calc(0.33rem + 0.24vw), 0.50rem);
|
||||||
--space-xs: calc(clamp(0.56rem, calc(0.31rem + 1.28vw), 1.13rem));
|
--space-xs: clamp(0.56rem, calc(0.49rem + 0.37vw), 0.75rem);
|
||||||
--space-s: calc(clamp(0.75rem, calc(0.41rem + 1.7vw), 1.5rem));
|
--space-s: clamp(0.75rem, calc(0.65rem + 0.49vw), 1.00rem);
|
||||||
--space-m: calc(clamp(1.13rem, calc(0.61rem + 2.56vw), 2.25rem));
|
--space-m: clamp(1.13rem, calc(0.98rem + 0.73vw), 1.50rem);
|
||||||
--space-l: calc(clamp(1.5rem, calc(0.82rem + 3.41vw), 3rem));
|
--space-l: clamp(1.50rem, calc(1.30rem + 0.98vw), 2.00rem);
|
||||||
--space-xl: calc(clamp(2.25rem, calc(1.23rem + 5.11vw), 4.5rem));
|
--space-xl: clamp(2.25rem, calc(1.96rem + 1.46vw), 3.00rem);
|
||||||
--space-2xl: calc(clamp(3rem, calc(1.64rem + 6.82vw), 6rem));
|
--space-2xl: clamp(3.00rem, calc(2.61rem + 1.95vw), 4.00rem);
|
||||||
--space-3xl: calc(clamp(4.5rem, calc(2.45rem + 10.23vw), 9rem));
|
--space-3xl: clamp(4.50rem, calc(3.91rem + 2.93vw), 6.00rem);
|
||||||
|
|
||||||
/* One-up pairs */
|
/* One-up pairs */
|
||||||
--space-3xs-2xs: calc(clamp(0.19rem, calc(-0.07rem + 1.28vw), 0.75rem));
|
--space-3xs-2xs: clamp(0.19rem, calc(0.07rem + 0.61vw), 0.50rem);
|
||||||
--space-2xs-xs: calc(clamp(0.38rem, calc(0.03rem + 1.7vw), 1.13rem));
|
--space-2xs-xs: clamp(0.38rem, calc(0.23rem + 0.73vw), 0.75rem);
|
||||||
--space-xs-s: calc(clamp(0.56rem, calc(0.14rem + 2.13vw), 1.5rem));
|
--space-xs-s: clamp(0.56rem, calc(0.39rem + 0.85vw), 1.00rem);
|
||||||
--space-s-m: calc(clamp(0.75rem, calc(0.07rem + 3.41vw), 2.25rem));
|
--space-s-m: clamp(0.75rem, calc(0.46rem + 1.46vw), 1.50rem);
|
||||||
--space-m-l: calc(clamp(1.13rem, calc(0.27rem + 4.26vw), 3rem));
|
--space-m-l: clamp(1.13rem, calc(0.78rem + 1.71vw), 2.00rem);
|
||||||
--space-l-xl: calc(clamp(1.5rem, calc(0.14rem + 6.82vw), 4.5rem));
|
--space-l-xl: clamp(1.50rem, calc(0.91rem + 2.93vw), 3.00rem);
|
||||||
--space-xl-2xl: calc(clamp(2.25rem, calc(0.55rem + 8.52vw), 6rem));
|
--space-xl-2xl: clamp(2.25rem, calc(1.57rem + 3.41vw), 4.00rem);
|
||||||
--space-2xl-3xl: calc(clamp(3rem, calc(0.27rem + 13.64vw), 9rem));
|
--space-2xl-3xl: clamp(3.00rem, calc(1.83rem + 5.85vw), 6.00rem);
|
||||||
|
|
||||||
/* Custom pairs */
|
/* Custom pairs */
|
||||||
--space-s-l: calc(clamp(0.75rem, calc(-0.27rem + 5.11vw), 3rem));
|
--space-s-l: clamp(0.75rem, calc(0.26rem + 2.44vw), 2.00rem);
|
||||||
--space-xs-m: calc(clamp(0.56rem, calc(-0.2rem + 3.84vw), 2.25rem));
|
--space-xs-m: clamp(0.56rem, calc(0.20rem + 1.83vw), 1.50rem);
|
||||||
--space-3xs-l: clamp(0.19rem, calc(-1.09rem + 6.39vw), 3.00rem);
|
--space-3xs-l: clamp(0.19rem, calc(-0.52rem + 3.54vw), 2.00rem);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,12 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
height: 100%;
|
||||||
padding-top: var(--header-size);
|
padding-top: var(--header-size);
|
||||||
font-size: var(--default-font-size);
|
font-size: var(--default-font-size);
|
||||||
font-family: "Nunito", sans-serif;
|
font-family: "Nunito", sans-serif;
|
||||||
|
@ -148,29 +153,22 @@ body {
|
||||||
|
|
||||||
@mixin toc-sticky {
|
@mixin toc-sticky {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
top: var(--header-size);
|
||||||
|
height: calc(100vh - var(--header-size));
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: var(--space-xl);
|
|
||||||
height: calc(100vh - var(--space-xl));
|
|
||||||
z-index: 900;
|
z-index: 900;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #fff #fff;
|
||||||
|
|
||||||
&:hover .scrollable-sidebar {
|
&:hover {
|
||||||
scrollbar-color: #e9ecef #fff;
|
scrollbar-color: #e9ecef #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable-sidebar {
|
.scrollable-sidebar {
|
||||||
scrollbar-width: thin;
|
|
||||||
scrollbar-color: #fff #fff;
|
|
||||||
display: block;
|
display: block;
|
||||||
width: auto;
|
width: auto;
|
||||||
overflow-y: scroll;
|
overflow-y: auto;
|
||||||
padding-bottom: 4rem;
|
padding-bottom: 4rem;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
@ -182,25 +180,37 @@ body {
|
||||||
list-style: disc;
|
list-style: disc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
padding-top: var(--space-m);
|
||||||
|
}
|
||||||
|
|
||||||
.left-sidebar {
|
.left-sidebar {
|
||||||
@include toc-sticky();
|
@include toc-sticky();
|
||||||
font-size: 80%;
|
font-size: 95%;
|
||||||
order: 0;
|
order: 0;
|
||||||
flex: 0 1 auto;
|
flex: 0 1 auto;
|
||||||
width: 25%;
|
width: 25%;
|
||||||
padding-right: var(--space-2xs);
|
padding-right: var(--space-s);
|
||||||
border-right: 1px solid var(--border-color);
|
border-right: 1px solid var(--border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-toc {
|
.docs-toc {
|
||||||
@include toc-sticky();
|
@include toc-sticky();
|
||||||
font-size: 66.666%;
|
font-size: 85%;
|
||||||
order: 2;
|
order: 2;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
width: 18.75%;
|
width: 18.75%;
|
||||||
border-left: 1px solid var(--border-color);
|
border-left: 1px solid var(--border-color);
|
||||||
padding-left: var(--space-2xs);
|
padding-left: var(--space-s);
|
||||||
|
|
||||||
nav > ul {
|
nav > ul {
|
||||||
& > li:not(:first-child) {
|
& > li:not(:first-child) {
|
||||||
|
@ -218,9 +228,8 @@ body {
|
||||||
|
|
||||||
article {
|
article {
|
||||||
order: 1;
|
order: 1;
|
||||||
padding: 0 var(--space-s) var(--space-m-l) var(--space-s);
|
padding: var(--space-m) var(--space-s) var(--space-m-l) var(--space-s);
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
width: 56.25%;
|
width: 56.25%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Set darkmode
|
||||||
|
document.getElementById('mode').addEventListener('click', () => {
|
||||||
|
|
||||||
|
document.body.classList.toggle('dark');
|
||||||
|
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// enforce local storage setting but also fallback to user-agent preferences
|
||||||
|
if (localStorage.getItem('theme') === 'dark' || (!localStorage.getItem('theme') && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
||||||
|
|
||||||
|
document.body.classList.add('dark');
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,309 @@
|
||||||
|
var suggestions = document.getElementById("suggestions");
|
||||||
|
var userinput = document.getElementById("userinput");
|
||||||
|
|
||||||
|
document.addEventListener("keydown", inputFocus);
|
||||||
|
|
||||||
|
function inputFocus(e) {
|
||||||
|
if (
|
||||||
|
e.keyCode === 191 &&
|
||||||
|
document.activeElement.tagName !== "INPUT" &&
|
||||||
|
document.activeElement.tagName !== "TEXTAREA"
|
||||||
|
) {
|
||||||
|
e.preventDefault();
|
||||||
|
userinput.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.keyCode === 27) {
|
||||||
|
userinput.blur();
|
||||||
|
suggestions.classList.add("d-none");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("click", function(event) {
|
||||||
|
var isClickInsideElement = suggestions.contains(event.target);
|
||||||
|
|
||||||
|
if (!isClickInsideElement) {
|
||||||
|
suggestions.classList.add("d-none");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source:
|
||||||
|
- https://dev.to/shubhamprakash/trap-focus-using-javascript-6a3
|
||||||
|
*/
|
||||||
|
|
||||||
|
document.addEventListener("keydown", suggestionFocus);
|
||||||
|
|
||||||
|
function suggestionFocus(e) {
|
||||||
|
const focusableSuggestions = suggestions.querySelectorAll("a");
|
||||||
|
if (suggestions.classList.contains("d-none") || focusableSuggestions.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const focusable = [...focusableSuggestions];
|
||||||
|
const index = focusable.indexOf(document.activeElement);
|
||||||
|
|
||||||
|
let nextIndex = 0;
|
||||||
|
|
||||||
|
if (e.keyCode === 38) {
|
||||||
|
e.preventDefault();
|
||||||
|
nextIndex = index > 0 ? index - 1 : 0;
|
||||||
|
focusableSuggestions[nextIndex].focus();
|
||||||
|
} else if (e.keyCode === 40) {
|
||||||
|
e.preventDefault();
|
||||||
|
nextIndex = index + 1 < focusable.length ? index + 1 : index;
|
||||||
|
focusableSuggestions[nextIndex].focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Source:
|
||||||
|
- https://github.com/nextapps-de/flexsearch#index-documents-field-search
|
||||||
|
- https://raw.githack.com/nextapps-de/flexsearch/master/demo/autocomplete.html
|
||||||
|
- http://elasticlunr.com/
|
||||||
|
- https://github.com/getzola/zola/blob/master/docs/static/search.js
|
||||||
|
*/
|
||||||
|
(function() {
|
||||||
|
var index = elasticlunr.Index.load(window.searchIndex);
|
||||||
|
userinput.addEventListener("input", show_results, true);
|
||||||
|
suggestions.addEventListener("click", accept_suggestion, true);
|
||||||
|
|
||||||
|
function show_results() {
|
||||||
|
var value = this.value.trim();
|
||||||
|
var options = {
|
||||||
|
bool: "OR",
|
||||||
|
fields: {
|
||||||
|
title: { boost: 2 },
|
||||||
|
body: { boost: 1 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var results = index.search(value, options);
|
||||||
|
|
||||||
|
var entry,
|
||||||
|
childs = suggestions.childNodes;
|
||||||
|
var i = 0,
|
||||||
|
len = results.length;
|
||||||
|
var items = value.split(/\s+/);
|
||||||
|
suggestions.classList.remove("d-none");
|
||||||
|
|
||||||
|
results.forEach(function(page) {
|
||||||
|
if (page.doc.body !== "") {
|
||||||
|
entry = document.createElement("div");
|
||||||
|
|
||||||
|
entry.innerHTML = "<a href><span></span><span></span></a>";
|
||||||
|
|
||||||
|
(a = entry.querySelector("a")),
|
||||||
|
(t = entry.querySelector("span:first-child")),
|
||||||
|
(d = entry.querySelector("span:nth-child(2)"));
|
||||||
|
a.href = page.ref;
|
||||||
|
t.textContent = page.doc.title;
|
||||||
|
d.innerHTML = makeTeaser(page.doc.body, items);
|
||||||
|
|
||||||
|
suggestions.appendChild(entry);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
while (childs.length > len) {
|
||||||
|
suggestions.removeChild(childs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function accept_suggestion() {
|
||||||
|
while (suggestions.lastChild) {
|
||||||
|
suggestions.removeChild(suggestions.lastChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Taken from mdbook
|
||||||
|
// The strategy is as follows:
|
||||||
|
// First, assign a value to each word in the document:
|
||||||
|
// Words that correspond to search terms (stemmer aware): 40
|
||||||
|
// Normal words: 2
|
||||||
|
// First word in a sentence: 8
|
||||||
|
// Then use a sliding window with a constant number of words and count the
|
||||||
|
// sum of the values of the words within the window. Then use the window that got the
|
||||||
|
// maximum sum. If there are multiple maximas, then get the last one.
|
||||||
|
// Enclose the terms in <b>.
|
||||||
|
function makeTeaser(body, terms) {
|
||||||
|
var TERM_WEIGHT = 40;
|
||||||
|
var NORMAL_WORD_WEIGHT = 2;
|
||||||
|
var FIRST_WORD_WEIGHT = 8;
|
||||||
|
var TEASER_MAX_WORDS = 30;
|
||||||
|
|
||||||
|
var stemmedTerms = terms.map(function(w) {
|
||||||
|
return elasticlunr.stemmer(w.toLowerCase());
|
||||||
|
});
|
||||||
|
var termFound = false;
|
||||||
|
var index = 0;
|
||||||
|
var weighted = []; // contains elements of ["word", weight, index_in_document]
|
||||||
|
|
||||||
|
// split in sentences, then words
|
||||||
|
var sentences = body.toLowerCase().split(". ");
|
||||||
|
for (var i in sentences) {
|
||||||
|
var words = sentences[i].split(/[\s\n]/);
|
||||||
|
var value = FIRST_WORD_WEIGHT;
|
||||||
|
for (var j in words) {
|
||||||
|
var word = words[j];
|
||||||
|
|
||||||
|
if (word.length > 0) {
|
||||||
|
for (var k in stemmedTerms) {
|
||||||
|
if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
|
||||||
|
value = TERM_WEIGHT;
|
||||||
|
termFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
weighted.push([word, value, index]);
|
||||||
|
value = NORMAL_WORD_WEIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
index += word.length;
|
||||||
|
index += 1; // ' ' or '.' if last word in sentence
|
||||||
|
}
|
||||||
|
|
||||||
|
index += 1; // because we split at a two-char boundary '. '
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weighted.length === 0) {
|
||||||
|
if (body.length !== undefined && body.length > TEASER_MAX_WORDS * 10) {
|
||||||
|
return body.substring(0, TEASER_MAX_WORDS * 10) + "...";
|
||||||
|
} else {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var windowWeights = [];
|
||||||
|
var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
|
||||||
|
// We add a window with all the weights first
|
||||||
|
var curSum = 0;
|
||||||
|
for (var i = 0; i < windowSize; i++) {
|
||||||
|
curSum += weighted[i][1];
|
||||||
|
}
|
||||||
|
windowWeights.push(curSum);
|
||||||
|
|
||||||
|
for (var i = 0; i < weighted.length - windowSize; i++) {
|
||||||
|
curSum -= weighted[i][1];
|
||||||
|
curSum += weighted[i + windowSize][1];
|
||||||
|
windowWeights.push(curSum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we didn't find the term, just pick the first window
|
||||||
|
var maxSumIndex = 0;
|
||||||
|
if (termFound) {
|
||||||
|
var maxFound = 0;
|
||||||
|
// backwards
|
||||||
|
for (var i = windowWeights.length - 1; i >= 0; i--) {
|
||||||
|
if (windowWeights[i] > maxFound) {
|
||||||
|
maxFound = windowWeights[i];
|
||||||
|
maxSumIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var teaser = [];
|
||||||
|
var startIndex = weighted[maxSumIndex][2];
|
||||||
|
for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
|
||||||
|
var word = weighted[i];
|
||||||
|
if (startIndex < word[2]) {
|
||||||
|
// missing text from index to start of `word`
|
||||||
|
teaser.push(body.substring(startIndex, word[2]));
|
||||||
|
startIndex = word[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// add <em/> around search terms
|
||||||
|
if (word[1] === TERM_WEIGHT) {
|
||||||
|
teaser.push("<b>");
|
||||||
|
}
|
||||||
|
|
||||||
|
startIndex = word[2] + word[0].length;
|
||||||
|
// Check the string is ascii characters or not
|
||||||
|
var re = /^[\x00-\xff]+$/;
|
||||||
|
if (word[1] !== TERM_WEIGHT && word[0].length >= 12 && !re.test(word[0])) {
|
||||||
|
// If the string's length is too long, it maybe a Chinese/Japance/Korean article
|
||||||
|
// if using substring method directly, it may occur error codes on emoji chars
|
||||||
|
var strBefor = body.substring(word[2], startIndex);
|
||||||
|
var strAfter = substringByByte(strBefor, 12);
|
||||||
|
teaser.push(strAfter);
|
||||||
|
} else {
|
||||||
|
teaser.push(body.substring(word[2], startIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (word[1] === TERM_WEIGHT) {
|
||||||
|
teaser.push("</b>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
teaser.push("…");
|
||||||
|
return teaser.join("");
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
// Get substring by bytes
|
||||||
|
// If using JavaScript inline substring method, it will return error codes
|
||||||
|
// Source: https://www.52pojie.cn/thread-1059814-1-1.html
|
||||||
|
function substringByByte(str, maxLength) {
|
||||||
|
var result = "";
|
||||||
|
var flag = false;
|
||||||
|
var len = 0;
|
||||||
|
var length = 0;
|
||||||
|
var length2 = 0;
|
||||||
|
for (var i = 0; i < str.length; i++) {
|
||||||
|
var code = str.codePointAt(i).toString(16);
|
||||||
|
if (code.length > 4) {
|
||||||
|
i++;
|
||||||
|
if (i + 1 < str.length) {
|
||||||
|
flag = str.codePointAt(i + 1).toString(16) == "200d";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flag) {
|
||||||
|
len += getByteByHex(code);
|
||||||
|
if (i == str.length - 1) {
|
||||||
|
length += len;
|
||||||
|
if (length <= maxLength) {
|
||||||
|
result += str.substr(length2, i - length2 + 1);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (len != 0) {
|
||||||
|
length += len;
|
||||||
|
length += getByteByHex(code);
|
||||||
|
if (length <= maxLength) {
|
||||||
|
result += str.substr(length2, i - length2 + 1);
|
||||||
|
length2 = i + 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
length += getByteByHex(code);
|
||||||
|
if (length <= maxLength) {
|
||||||
|
if (code.length <= 4) {
|
||||||
|
result += str[i];
|
||||||
|
} else {
|
||||||
|
result += str[i - 1] + str[i];
|
||||||
|
}
|
||||||
|
length2 = i + 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the string bytes from binary
|
||||||
|
function getByteByBinary(binaryCode) {
|
||||||
|
// Binary system, starts with `0b` in ES6
|
||||||
|
// Octal number system, starts with `0` in ES5 and starts with `0o` in ES6
|
||||||
|
// Hexadecimal, starts with `0x` in both ES5 and ES6
|
||||||
|
var byteLengthDatas = [0, 1, 2, 3, 4];
|
||||||
|
var len = byteLengthDatas[Math.ceil(binaryCode.length / 8)];
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the string bytes from hexadecimal
|
||||||
|
function getByteByHex(hexCode) {
|
||||||
|
return getByteByBinary(parseInt(hexCode, 16).toString(2));
|
||||||
|
}
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container" role="document">
|
<div class="container" role="document">
|
||||||
|
<div class="content">
|
||||||
<div class="main">
|
<div class="main">
|
||||||
{% include "components/left-sidebar-singleton.html" %}
|
{% include "components/left-sidebar-singleton.html" %}
|
||||||
{% include "components/right-sidebar.html" %}
|
{% include "components/right-sidebar.html" %}
|
||||||
|
@ -12,5 +13,6 @@
|
||||||
<div class="text-center">{{ section.content | safe }}</div>
|
<div class="text-center">{{ section.content | safe }}</div>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
Loading…
Reference in New Issue