Merge branch 'main' into feature/brightspots
This commit is contained in:
+154
-65
@@ -1,69 +1,158 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
|
||||||
var macros = {
|
function formatThousands(input) {
|
||||||
",": (context) => context.future()?.text === " " ? "{\\char`,}" : "\\char`,",
|
|
||||||
"\\qty": "{#1\\,\\mathrm{#2}}",
|
let s = String(input).trim();
|
||||||
"\\qtyrange": "{#1\\text{--}#2\\,\\mathrm{#3}}",
|
|
||||||
"\\unit": "{\\mathrm{#1}}",
|
// Extract exponent (e or E) and convert to \cdot 10^{...}
|
||||||
"\\num": "{#1}",
|
let exponent = "";
|
||||||
"\\squared": "{^{2}}",
|
const expMatch = s.match(/([eE])([+-]?\d+)$/);
|
||||||
"\\cubed": "{^{3}}",
|
if (expMatch) {
|
||||||
"\\per": "/",
|
let expValue = expMatch[2];
|
||||||
"\\percent": "\\%",
|
|
||||||
"\\tera": "\\text{T}",
|
// Remove leading "+"
|
||||||
"\\giga": "\\text{G}",
|
if (expValue[0] === "+") {
|
||||||
"\\mega": "\\text{M}",
|
expValue = expValue.slice(1);
|
||||||
"\\kilo": "\\text{k}",
|
}
|
||||||
"\\dezi": "\\text{d}",
|
|
||||||
"\\centi": "\\text{c}",
|
// Parse exponent as a numeric value
|
||||||
"\\milli": "\\text{m}",
|
const expNum = parseInt(expValue, 10);
|
||||||
"\\micro": "\\text{μ}",
|
|
||||||
"\\nano": "\\text{n}",
|
// Suppress exponent if it is 0 (no \cdot 10^0 shown)
|
||||||
"\\pico": "\\text{p}",
|
if (expNum !== 0) {
|
||||||
"\\kilogram": "\\text{kg}",
|
exponent = "\\cdot 10^{" + expNum + "}";
|
||||||
"\\gram": "\\text{g}",
|
}
|
||||||
"\\meter": "\\text{m}",
|
|
||||||
"\\second": "\\text{s}",
|
s = s.slice(0, -expMatch[0].length);
|
||||||
"\\hour": "\\text{h}",
|
}
|
||||||
"\\ampere": "\\text{A}",
|
|
||||||
"\\kelvin": "\\text{K}",
|
// Sign (+, -, \pm). Also accept "\\pm" (double-escaped backslash) and optional whitespace.
|
||||||
"\\mol": "\\text{mol}",
|
let sign = "";
|
||||||
"\\bel": "\\text{B}",
|
const pmMatch = s.match(/^(?:\\\\pm|\\pm)\s*/);
|
||||||
"\\dezibel": "\\text{dB}",
|
if (pmMatch) {
|
||||||
"\\dB": "\\text{dB}",
|
sign = "\\pm";
|
||||||
"\\dBm": "\\text{dBm}",
|
s = s.slice(pmMatch[0].length);
|
||||||
"\\dBu": "\\text{dBu}",
|
} else if (s[0] === "+" || s[0] === "-") {
|
||||||
"\\dBW": "\\text{dBW}",
|
sign = s[0];
|
||||||
"\\dBi": "\\text{dBi}",
|
s = s.slice(1);
|
||||||
"\\dBd": "\\text{dBd}",
|
}
|
||||||
"\\candela": "\\text{cd}",
|
|
||||||
"\\newton": "\\text{N}",
|
// Find decimal point (last . or ,)
|
||||||
"\\hertz": "\\text{Hz}",
|
let intPart = s;
|
||||||
"\\pascal": "\\text{Pa}",
|
let fracSep = "";
|
||||||
"\\volt": "\\text{V}",
|
let fracDigits = "";
|
||||||
"\\watt": "\\text{W}",
|
const decMatch = s.match(/([.,])(\d+)$/);
|
||||||
"\\joule": "\\text{J}",
|
if (decMatch) {
|
||||||
"\\henry": "\\text{H}",
|
intPart = s.slice(0, decMatch.index);
|
||||||
"\\farad": "\\text{F}",
|
fracSep = decMatch[1];
|
||||||
"\\coulomb": "\\text{C}",
|
fracDigits = decMatch[2];
|
||||||
"\\ohm": "\\Omega",
|
}
|
||||||
"\\Ohm": "\\Omega",
|
|
||||||
"\\weber": "\\text{Wb}",
|
// Thousand grouping in integer part
|
||||||
"\\tesla": "\\text{T}",
|
if (intPart.length >= 5) {
|
||||||
"\\bit": "\\text{b}",
|
intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, "\\,");
|
||||||
"\\baud": "\\text{Bd}",
|
}
|
||||||
"\\degree": "^\\circ",
|
|
||||||
"\\degreeCelsius": "^\\circ\\text{C}",
|
// Thousand grouping in fractional part (from left in 3-digit blocks)
|
||||||
};
|
if (fracDigits.length >= 4) {
|
||||||
|
fracDigits = fracDigits.replace(/(\d{3})(?=\d)/g, "$1\\,");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reassemble
|
||||||
|
return sign + intPart + (fracDigits ? (fracSep + fracDigits) : "") + exponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var macros = {
|
||||||
|
",": (context) => context.future()?.text === " " ? "{\\char`,}" : "\\char`,",
|
||||||
|
"\\num": (context) => {
|
||||||
|
const [arg] = context.consumeArgs(1);
|
||||||
|
const raw = arg.reverse().map(t => t.text).join("");
|
||||||
|
return formatThousands(raw);
|
||||||
|
},
|
||||||
|
"\\qty": (context) => {
|
||||||
|
const [numTok, unitTok] = context.consumeArgs(2);
|
||||||
|
const rawNum = numTok.reverse().map(t => t.text).join("");
|
||||||
|
const unit = unitTok.reverse().map(t => t.text).join("");
|
||||||
|
const formattedNum = formatThousands(rawNum);
|
||||||
|
if (unit.startsWith("\\degree")) {
|
||||||
|
return formattedNum + "\\mathrm{" + unit + "}";
|
||||||
|
} else {
|
||||||
|
return formattedNum + "\\,\\mathrm{" + unit + "}";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"\\qtyrange": (context) => {
|
||||||
|
const [aTok, bTok, unitTok] = context.consumeArgs(3);
|
||||||
|
const aRaw = aTok.reverse().map(t => t.text).join("");
|
||||||
|
const bRaw = bTok.reverse().map(t => t.text).join("");
|
||||||
|
const unit = unitTok.reverse().map(t => t.text).join("");
|
||||||
|
const aFmt = formatThousands(aRaw);
|
||||||
|
const bFmt = formatThousands(bRaw);
|
||||||
|
if (unit.startsWith("\\degree")) {
|
||||||
|
return aFmt + "\\text{--}\\," + bFmt + "\\mathrm{" + unit + "}";
|
||||||
|
} else {
|
||||||
|
return aFmt + "\\,\\text{--}\\," + bFmt + "\\,\\mathrm{" + unit + "}";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"\\unit": "{\\mathrm{#1}}",
|
||||||
|
"\\squared": "{^{2}}",
|
||||||
|
"\\cubed": "{^{3}}",
|
||||||
|
"\\per": "/",
|
||||||
|
"\\percent": "\\%",
|
||||||
|
"\\tera": "\\text{T}",
|
||||||
|
"\\giga": "\\text{G}",
|
||||||
|
"\\mega": "\\text{M}",
|
||||||
|
"\\kilo": "\\text{k}",
|
||||||
|
"\\dezi": "\\text{d}",
|
||||||
|
"\\centi": "\\text{c}",
|
||||||
|
"\\milli": "\\text{m}",
|
||||||
|
"\\micro": "\\text{μ}",
|
||||||
|
"\\nano": "\\text{n}",
|
||||||
|
"\\pico": "\\text{p}",
|
||||||
|
"\\kilogram": "\\text{kg}",
|
||||||
|
"\\gram": "\\text{g}",
|
||||||
|
"\\meter": "\\text{m}",
|
||||||
|
"\\second": "\\text{s}",
|
||||||
|
"\\hour": "\\text{h}",
|
||||||
|
"\\ampere": "\\text{A}",
|
||||||
|
"\\kelvin": "\\text{K}",
|
||||||
|
"\\mol": "\\text{mol}",
|
||||||
|
"\\bel": "\\text{B}",
|
||||||
|
"\\dezibel": "\\text{dB}",
|
||||||
|
"\\dB": "\\text{dB}",
|
||||||
|
"\\dBm": "\\text{dBm}",
|
||||||
|
"\\dBu": "\\text{dBu}",
|
||||||
|
"\\dBW": "\\text{dBW}",
|
||||||
|
"\\dBi": "\\text{dBi}",
|
||||||
|
"\\dBd": "\\text{dBd}",
|
||||||
|
"\\candela": "\\text{cd}",
|
||||||
|
"\\newton": "\\text{N}",
|
||||||
|
"\\hertz": "\\text{Hz}",
|
||||||
|
"\\pascal": "\\text{Pa}",
|
||||||
|
"\\volt": "\\text{V}",
|
||||||
|
"\\watt": "\\text{W}",
|
||||||
|
"\\joule": "\\text{J}",
|
||||||
|
"\\henry": "\\text{H}",
|
||||||
|
"\\farad": "\\text{F}",
|
||||||
|
"\\coulomb": "\\text{C}",
|
||||||
|
"\\ohm": "\\Omega",
|
||||||
|
"\\Ohm": "\\Omega",
|
||||||
|
"\\weber": "\\text{Wb}",
|
||||||
|
"\\tesla": "\\text{T}",
|
||||||
|
"\\bit": "\\text{b}",
|
||||||
|
"\\baud": "\\text{Bd}",
|
||||||
|
"\\degreeCelsius": "\\,\\degree\\text{C}",
|
||||||
|
};
|
||||||
|
|
||||||
|
renderMathInElement(document.body, {
|
||||||
|
delimiters: [
|
||||||
|
{ left: '$$', right: '$$', display: true }, // Note: $$ has to come before $
|
||||||
|
{ left: '$', right: '$', display: false },
|
||||||
|
{ left: '\\[', right: '\\]', display: true },
|
||||||
|
{ left: "\\(", right: "\\)", display: false },
|
||||||
|
],
|
||||||
|
throwOnError: false,
|
||||||
|
macros: macros
|
||||||
|
});
|
||||||
|
|
||||||
renderMathInElement(document.body, {
|
|
||||||
delimiters: [
|
|
||||||
{left: '$$', right: '$$', display: true}, // Note: $$ has to come before $
|
|
||||||
{left: '$', right: '$', display: false},
|
|
||||||
{left: '\\[', right: '\\]', display: true},
|
|
||||||
{left: "\\(", right: "\\)", display: false},
|
|
||||||
],
|
|
||||||
throwOnError : false,
|
|
||||||
macros: macros
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
+11
-3
@@ -1,5 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -124,8 +125,7 @@ class Build:
|
|||||||
page_template = self.env.get_template("html/page.html")
|
page_template = self.env.get_template("html/page.html")
|
||||||
return page_template.render(content=content, course_wrapper=course_wrapper, sidebar=sidebar)
|
return page_template.render(content=content, course_wrapper=course_wrapper, sidebar=sidebar)
|
||||||
|
|
||||||
def __picture_handler(self, id):
|
def __copy_picture(self, id):
|
||||||
self.config.p_build_pictures.mkdir(parents=True, exist_ok=True)
|
|
||||||
file = f"{id}.svg"
|
file = f"{id}.svg"
|
||||||
try:
|
try:
|
||||||
shutil.copyfile(self.config.p_data_pictures / file, self.config.p_build_pictures / file)
|
shutil.copyfile(self.config.p_data_pictures / file, self.config.p_build_pictures / file)
|
||||||
@@ -136,6 +136,10 @@ class Build:
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
tqdm.write(f"\033[31mPicture #{id} not found\033[0m")
|
tqdm.write(f"\033[31mPicture #{id} not found\033[0m")
|
||||||
|
|
||||||
|
def __picture_handler(self, id):
|
||||||
|
self.config.p_build_pictures.mkdir(parents=True, exist_ok=True)
|
||||||
|
return self.__copy_picture(id)
|
||||||
|
|
||||||
def __photo_handler(self, id):
|
def __photo_handler(self, id):
|
||||||
self.config.p_build_photos.mkdir(parents=True, exist_ok=True)
|
self.config.p_build_photos.mkdir(parents=True, exist_ok=True)
|
||||||
file = f"{id}.png"
|
file = f"{id}.png"
|
||||||
@@ -170,7 +174,11 @@ class Build:
|
|||||||
|
|
||||||
def __include_handler(self, include):
|
def __include_handler(self, include):
|
||||||
with (self.config.p_data_html / f"{include}.html").open() as file:
|
with (self.config.p_data_html / f"{include}.html").open() as file:
|
||||||
return file.read()
|
code = file.read()
|
||||||
|
svg_list = re.findall(r"(\d+)\.svg", code or "")
|
||||||
|
for id in svg_list:
|
||||||
|
self.__copy_picture(id)
|
||||||
|
return code
|
||||||
|
|
||||||
def __build_section(
|
def __build_section(
|
||||||
self,
|
self,
|
||||||
|
|||||||
Reference in New Issue
Block a user