initial help docs with dash markup

This commit is contained in:
NaitLee 2023-02-27 21:45:49 +08:00
parent 4fa145459b
commit b48e8cd6ec
20 changed files with 248 additions and 29 deletions

7
TODO
View File

@ -2,7 +2,7 @@
Note: not ordered. do whatever I/you want
+ Cookbook of basic things
+ Write good help/manual
+ Write good help/manual, with Dash Markup/XML
+ Some sort of Wiki
+ Make error notice short while let users see detailed help/manual for what-to-do
+ Even better CUPS/IPP support
@ -16,6 +16,7 @@ Note: not ordered. do whatever I/you want
+ Service for other init systems (a systemd unit file is there)
+ ...
? DOM backend for Dash XML
? Optimize PF2 text printing? It seems a bit slow (in bit processing).
? Use something else as server part of backend? This can boost things up, and build some (essential) image manipulation in, quicker. And strip some way-too-big Python libs away (for smaller Windows/Android dist).
? Built-in PostScript (Even if very basic)
@ -24,6 +25,6 @@ Note: not ordered. do whatever I/you want
It's usually messy. Try forking in your own way, at the moment.
? Process picture with WebAssembly? (Web frontend only)
Tried, Not as efficient as pure JavaScript
? Put Android APP on F-Droid? But it needs automatic build system...
Android guys can help this!
? Put Android APP on F-Droid (official repository)?
But it needs automatic build system... Android guys can help this!
? ... Or put to APKPure? But make frontend well before doing all of these

View File

@ -46,6 +46,7 @@ mime_type = {
'html': 'text/html;charset=utf-8',
'css': 'text/css;charset=utf-8',
'js': 'text/javascript;charset=utf-8',
'mjs': 'text/javascript;charset=utf-8',
'txt': 'text/plain;charset=utf-8',
'json': 'application/json;charset=utf-8',
'png': 'image/png',
@ -55,6 +56,9 @@ mime_type = {
}
def mime(url: str):
'Get pre-defined MIME type of a certain url by extension name'
if url.endswith('--'):
# dash markup / dash xml
return 'text/plain;charset=utf-8'
return mime_type.get(url.rsplit('.', 1)[-1], mime_type['octet-stream'])
def concat_files(*paths, prefix_format='', buffer=4 * 1024 * 1024) -> bytes:

View File

@ -2,5 +2,6 @@ polyfill.js
i18n-ext.js
i18n.js
image.js
dash-xml.js
accessibility.js
main.js

81
www/dash-xml.js Normal file
View File

@ -0,0 +1,81 @@
// @license magnet:?xt=urn:btih:90dc5c0be029de84e523b9b3922520e79e0e6f08&dn=cc0.txt CC0-1.0
// deno-fmt-ignore-file
// deno-lint-ignore-file
var DashXml = (function() {
const SD = "-";
const DD = "--";
const SP = " ";
const SDSP = " - ";
const DDSP = " -- ";
const RE_WORD = "[^ ]+";
const RE_INDENT = "[ \t]*";
const RE_DMX = new RegExp(`^(${RE_INDENT})` + `(${RE_WORD})?` + `((?:${SDSP}.+?)*)?` + `(${DDSP}.+)?` + `(?:${SP}|^)(${SD}|${DD})$`);
const XmlEntities = {
"&": "&",
"<": "&lt;",
">": "&gt;"
};
class DashXml {
tags;
constructor(){
this.tags = [];
}
translateLine(line) {
if (line.endsWith(SD) || /^[ \t]*<.+>$/.test(line)) Object.entries(XmlEntities).forEach(([__char, entity])=>line = line.replaceAll(__char, entity));
if (!line.endsWith(SD)) return line;
const match = line.match(RE_DMX);
if (match === null) {
if (line.match(/^ *!-- (.+) --$/)) {
return line.replace("!", "<!") + ">";
}
console.warn("Warning: failed to match this Dash Markup, probably this line is bad or current regexp is faulty");
console.warn(">", line);
return "";
}
if (!match[2]) {
const tag = this.tags.pop();
if (tag === undefined) {
console.warn("Warning: no more tags to close, probably previous lines closed one too early, or this translator is faulty");
console.warn("will leave out an '</undefined>', please check result");
}
return line.slice(0, -1) + "</" + tag + ">";
}
const tag1 = match[2];
let result = match[1] + "<" + tag1;
if (match[3]) {
const segs = match[3].split(SDSP).map((s)=>s.replaceAll("---", "-"));
segs.shift();
for (const seg of segs){
const space = seg.indexOf(SP);
if (space === -1) {
result += SP + seg;
} else {
result += SP + seg.slice(0, space) + '="' + seg.slice(space + 1) + '"';
}
}
}
if (match[4]) {
result += ">" + match[4].slice(DDSP.length);
}
if (match[5] === SD) {
result += ">";
this.tags.push(tag1);
} else if (match[5] === DD) {
if (match[4]) {
result += "</" + tag1 + ">";
} else if (tag1[0] === "!") {
result += ">";
} else if (tag1[0] === "?") {
result += "?>";
} else {
result += " />";
}
}
return result;
}
}
return DashXml;
})();
// @license-end

9
www/helps/0-mkcontent.sh Executable file
View File

@ -0,0 +1,9 @@
#!/bin/sh
for dir in $(ls); do {
if [ -d $dir ]; then
rm "$dir/content.txt"
for file in $(ls $dir); do {
printf 'helps/%s/%s\t%s\n' $dir $file ${file%--} >> "$dir/content.txt"
}; done
fi
}; done

View File

@ -0,0 +1,2 @@
helps/en-US/frequently-asked-questions-- frequently-asked-questions
helps/en-US/glossary-- glossary

View File

@ -0,0 +1,7 @@
h3 -- How do I scan & connect to a device? --
p -- When you tap “Print”, the application will automatically connect to an available device (that is near you & powered on & waiting for connection), and print directly afterwards. --
p -- The connection will persist until you close either the application or the printer. If the printer is shutdown after a connection, the application will automatically search for another one when requested to print. --
h3 -- What if I have multiple printers available and want to print to a specific one? --
p -- Tap “Show More Options”, an option for manually scanning & selecting devices is there. --

View File

@ -0,0 +1,36 @@
h3 -- Interesting ones: --
dl -
dt -- Cat Face Upward --
dd -- Flip the image data sent to printer, so that after printing both your picture and the printer itself faces upward, natually. --
-
h3 -- “Brightness”, “Strength”, and “Quality” --
dl -
dt -- Brightness --
dd -- directly affect how your picture is processed to pixels that fits the printers “black and white” color; --
-
dl -
dt -- Strength --
dd -- tell the printer how deep to print those resulting pixels, i.e. the thermal energy used; --
-
dl -
dt -- Quality --
dd -- indeed affect paper feeding speed, lower “Quality” means higher speed printing but unstable heating & visual quality. --
-
h3 -- “Picture”, “Pattern”, and “Text” Process --
p -- Since the printer can only print black pixels (not even gray), ordinary pictures should be specifically processed with a algorithm that suits its use best. --
p -- Pictures are first processed to grayscale (in a natual-for-eyes way), then processed as: --
dl -
dt -- Picture --
dd -- use black & white pixels in place of “gray” parts of original image, which is best for ordinary pictures; --
-
dl -
dt -- Pattern --
dd -- use variable sized dots in place of “gray” parts of original image, which may be good for simple shapes; --
-
dl -
dt -- Text --
dd -- simply determine black or white per-pixel by brightness, good for snapshots of text. --
-

View File

@ -70,7 +70,7 @@
</div>
<div class="panel active" id="panel-help">
<div>
<p data-i18n="coming-soon">Coming Soon...</p>
<ul id="help-content"></ul>
<p>
<a href="about.html" target="frame" data-i18n="about" data-key>About</a>
<a href="jslicense.html" data-jslicense="1" target="frame"
@ -88,7 +88,7 @@
</div>
<label class="label-input-span">
<input type="checkbox" name="flip" data-key />
<span data-i18n="cat-face-toward">Cat Face Toward</span>
<span data-i18n="cat-face-upward">Cat Face Upward</span>
</label>
<!-- <hr /> -->
<label class="label-input-span">
@ -225,11 +225,12 @@
</div>
</div>
<iframe id="frame" src="about:blank" name="frame" title="frame" data-key="v"></iframe>
<div id="dashdoc"></div>
</div>
<div id="dialog" class="hidden">
<div class="shade"></div>
<div class="content">
<div id="dialog-content">
<div id="dialog-content" data-key="b">
<!-- Dialog content -->
</div>
<div id="dialog-choices">

View File

@ -68,6 +68,12 @@
<td><a href="image.js">image.js</a></td>
<td data-i18n="javascript-imagejs-description">For canvas image manipulation</td>
</tr>
<tr>
<td><a href="dash-xml.js">dash-xml.js</a></td>
<td><a href="http://creativecommons.org/publicdomain/zero/1.0/legalcode">CC0-1.0</a></td>
<td><a href="https://codeberg.org/NaitLee/dash-xml/src/branch/main/dash-xml.ts">dash-xml.ts</a></td>
<td data-i18n="javascript-imagejs-description">For translating Help documents to HTML</td>
</tr>
<tr>
<td><a href="accessibility.js">accessibility.js</a></td>
<td><a href="http://creativecommons.org/publicdomain/zero/1.0/legalcode">CC0-1.0</a></td>

View File

@ -130,7 +130,7 @@
"javascript-imagejs-description": "Bildbearbeitung",
"javascript-accessibilityjs-description": "Barrierefreiheit",
"javascript-catprinter-description": "Die Hauptskripte von Cat-Printer",
"cat-face-toward": "An Katzengesicht ausrichten",
"cat-face-upward": "An Katzengesicht ausrichten",
"free-software": "Freie Software",
"free-software-description": "Software, die Ihre Freiheit und Gemeinschaft respektiert",
"wrap-words-by-spaces": "Autom. Zeilenumbruch",

View File

@ -96,7 +96,6 @@
"everyone-is-awesome": "Everyone is awesome!",
"license": "License",
"exiting": "Exiting…",
"dark-theme": "Dark Theme",
"high-contrast": "High Contrast",
"welcome": "Welcome!",
@ -126,7 +125,7 @@
"strength-": "Strength:",
"or-drag-file-to-below": "Or drag file to below",
"reset": "Reset",
"cat-face-toward": "Cat Face Toward",
"cat-face-upward": "Cat Face Upward",
"quality-": "Quality:",
"print-quality": "Print quality",
"show-more-options": "Show More Options",
@ -158,5 +157,8 @@
"rotate-image": "Rotate Image",
"test-unknown-device": "Test Unknown Device",
"scan": "Scan",
"now-will-scan-for-all-bluetooth-devices-nearby": "Scan set to search for all bluetooth devides nearby."
"now-will-scan-for-all-bluetooth-devices-nearby": "Scan set to search for all bluetooth devices nearby.",
"frequently-asked-questions": "Frequently Asked Questions",
"glossary": "Glossary"
}

View File

@ -121,7 +121,7 @@
"strength-": "HOW MUCH INK>",
"or-drag-file-to-below": "THRW PIC OR MEOW HERE",
"reset": "STRT OVR",
"cat-face-toward": "WANT KITTE FACE NOT BUTT",
"cat-face-upward": "WANT KITTE FACE NOT BUTT",
"quality-": "CAREFUL STEP>",
"print-quality": "HOW CAREFUL R STEPS",
"show-more-options": "LOT CFGS HERE",
@ -136,5 +136,7 @@
"rotate-image": "ROLL PIC",
"test-unknown-device": "I HAV STRENGE KITTE",
"now-will-scan-for-all-bluetooth-devices-nearby": "WIL FIND ALL THINY KITTE OR NOT",
"scan": "FIND"
"scan": "FIND",
"frequently-asked-questions": "CONFUSED KITTEZ",
"glossary": "WAT DO TIS MEAN"
}

View File

@ -87,7 +87,6 @@
"everyone-is-awesome": "每个人都是好样的!",
"license": "授权",
"exiting": "退出中……",
"dark-theme": "深色主题",
"high-contrast": "高对比度",
"welcome": "欢迎!",
@ -117,7 +116,7 @@
"strength-": "力度:",
"or-drag-file-to-below": "或拖拽文件至下方",
"reset": "重置",
"cat-face-toward": "猫脸朝上",
"cat-face-upward": "猫脸朝上",
"quality-": "质量:",
"print-quality": "打印质量",
"show-more-options": "显示更多选项",
@ -148,5 +147,7 @@
"javascript-accessibilityjs-description": "一些无障碍功能",
"javascript-catprinter-description": "猫咪打印机 (Cat-Printer) 主脚本",
"free-software": "自由软件",
"free-software-description": "尊重您计算自由的软件。"
"free-software-description": "尊重您计算自由的软件。",
"frequently-asked-questions": "常见问题",
"glossary": "术语解释"
}

View File

@ -87,7 +87,6 @@
"everyone-is-awesome": "每個人都是好樣的!",
"license": "授權",
"exiting": "退出中……",
"dark-theme": "深色主題",
"high-contrast": "高對比度",
"welcome": "歡迎!",
@ -117,7 +116,7 @@
"strength-": "力度:",
"or-drag-file-to-below": "或拖拽文件至下方",
"reset": "重置",
"cat-face-toward": "貓臉朝上",
"cat-face-upward": "貓臉朝上",
"quality-": "質量:",
"print-quality": "打印質量",
"show-more-options": "顯示更多選項",
@ -148,5 +147,7 @@
"javascript-accessibilityjs-description": "一些無障礙功能",
"javascript-catprinter-description": "貓咪打印機 (Cat-Printer) 主腳本",
"free-software": "自由軟件",
"free-software-description": "尊重您計算自由的軟件。"
"free-software-description": "尊重您計算自由的軟件。",
"frequently-asked-questions": "常見問題",
"glossary": "術語解釋"
}

View File

@ -87,7 +87,6 @@
"everyone-is-awesome": "每個人都是好樣的!",
"license": "授權",
"exiting": "退出中……",
"dark-theme": "深色主題",
"high-contrast": "高對比度",
"welcome": "歡迎!",
@ -117,7 +116,7 @@
"strength-": "力度:",
"or-drag-file-to-below": "或拖拽文件至下方",
"reset": "重置",
"cat-face-toward": "貓臉朝上",
"cat-face-upward": "貓臉朝上",
"quality-": "質量:",
"print-quality": "打印質量",
"show-more-options": "顯示更多選項",
@ -148,5 +147,7 @@
"javascript-accessibilityjs-description": "一些無障礙功能",
"javascript-catprinter-description": "貓咪打印機 (Cat-Printer) 主腳本",
"free-software": "自由軟件",
"free-software-description": "尊重您計算自由的軟件。"
"free-software-description": "尊重您計算自由的軟件。",
"frequently-asked-questions": "常見問題",
"glossary": "術語解釋"
}

View File

@ -87,7 +87,6 @@
"everyone-is-awesome": "每個人都是好樣的!",
"license": "授權",
"exiting": "退出中……",
"dark-theme": "深色主題",
"high-contrast": "高對比度",
"welcome": "歡迎!",
@ -117,7 +116,7 @@
"strength-": "力度:",
"or-drag-file-to-below": "或拖拽檔案至下方",
"reset": "重置",
"cat-face-toward": "貓臉朝上",
"cat-face-upward": "貓臉朝上",
"quality-": "質量:",
"print-quality": "列印質量",
"show-more-options": "顯示更多選項",
@ -148,5 +147,7 @@
"javascript-accessibilityjs-description": "一些無障礙功能",
"javascript-catprinter-description": "貓咪印表機 (Cat-Printer) 主指令碼",
"free-software": "自由軟體",
"free-software-description": "尊重您計算自由的軟體。"
"free-software-description": "尊重您計算自由的軟體。",
"frequently-asked-questions": "常見問題",
"glossary": "術語解釋"
}

View File

@ -13,7 +13,7 @@ window.exports = {};
var fallbacks;
if (location.href.indexOf('?debug') !== -1)
fallbacks = ['i18n-ext.js', 'i18n.js', 'image.js', 'accessibility.js', 'main.js'];
fallbacks = ['i18n-ext.js', 'i18n.js', 'image.js', 'dash-xml.js', 'accessibility.js', 'main.js'];
else
fallbacks = ['~every.js', 'main.comp.js'];
var trial_count = 0;

View File

@ -365,8 +365,8 @@ dl {
margin: var(--span) 0;
display: block;
}
dt { display: inline-block; min-width: 6em; text-align: end; }
dd { display: inline-block; margin: 0 calc(var(--font-size) / 4); }
.contributors dt { display: inline-block; min-width: 6em; text-align: end; }
.contributors dd { display: inline-block; margin: 0 calc(var(--font-size) / 4); }
.contributors dt {
min-width: 12em;
text-align: center;
@ -465,6 +465,21 @@ iframe#frame {
white-space: nowrap;
margin: 1em;
}
#dashdoc {
text-align: left;
font-size: large;
}
#dashdoc h3 {
font-size: large;
}
#dashdoc p, #dashdoc li, #dashdoc dl {
margin: var(--span) 0;
}
dd {
margin-left: 2em;
}
@keyframes jump {
0% { transform: translateY(0); }
50% { transform: translateY(var(--font-size)); }
@ -605,7 +620,7 @@ iframe#frame {
z-index: 0;
}
#dialog-content {
padding: var(--span) 0;
padding: var(--span);
}
.blank {
height: var(--compact-menu-height);

View File

@ -681,8 +681,9 @@ async function initI18n(current_language) {
}
if (!navigator.languages) {
if (!navigator.language) return;
else navigator.languages = [navigator.language, 'en-US'];
else navigator.languages = [navigator.language];
}
navigator.languages = navigator.languages.concat('en-US');
if (current_language) {
for (let option of language_select.children)
if (option.value === current_language)
@ -708,6 +709,52 @@ async function fakeAndroid(enable) {
await callApi('/set', { 'is_android': enable });
window.location.reload();
}
const dashDoc = (function() {
const dashdoc = document.getElementById('dashdoc');
const dashxml = new DashXml();
return async function(path) {
let html = '';
const t = await fetch(path).then(r => r.ok ? r.text() : '');
if (t === '') return false;
for (const line of t.split('\n'))
html += dashxml.translateLine(line);
dashdoc.innerHTML = html;
if (dashxml.tags.length !== 0) {
console.warn('Warning: there are leftover Dash XML tags, cleaning up')
dashxml.tags.splice(0, dashxml.tags.length);
}
return true;
}
})();
async function initHelp() {
const help_content = document.getElementById('help-content');
for (const lang of navigator.languages) {
const content = await fetch(`/helps/${lang}/content.txt`)
.then(r => r.ok ? r.text() : '')
.catch(_ => '');
if (content === '') continue;
const list = content.split('\n').map(s => s.split('\t'));
for (const [path, title] of list) {
if (!path || !title) continue;
const entry = document.createElement('li');
const a = document.createElement('a');
a.href = 'javascript:';
a.addEventListener('click', () => {
if (dashDoc(path))
Dialog.alert('#dashdoc');
else
Dialog.alert('failed-to-load-this-help');
});
a.setAttribute('data-i18n', title);
a.setAttribute('data-key', '');
a.innerText = i18n(title);
entry.appendChild(a);
help_content.appendChild(entry);
}
break;
}
}
class Main {
promise;
@ -816,6 +863,7 @@ class Main {
await this.loadConfig();
await initI18n(this.settings['language']);
await this.activateConfig();
initHelp();
// one exception
this.conf('#select-language', 'change', 'language');