diff --git a/TODO b/TODO
index f9736b0..04e4b95 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/server.py b/server.py
index d7ea124..f19f809 100644
--- a/server.py
+++ b/server.py
@@ -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:
diff --git a/www/all_js.txt b/www/all_js.txt
index 4c34244..c6d8a1c 100644
--- a/www/all_js.txt
+++ b/www/all_js.txt
@@ -2,5 +2,6 @@ polyfill.js
i18n-ext.js
i18n.js
image.js
+dash-xml.js
accessibility.js
main.js
diff --git a/www/dash-xml.js b/www/dash-xml.js
new file mode 100644
index 0000000..2ef7859
--- /dev/null
+++ b/www/dash-xml.js
@@ -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 = {
+ "&": "&",
+ "<": "<",
+ ">": ">"
+};
+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 '', 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
diff --git a/www/helps/0-mkcontent.sh b/www/helps/0-mkcontent.sh
new file mode 100755
index 0000000..0449417
--- /dev/null
+++ b/www/helps/0-mkcontent.sh
@@ -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
diff --git a/www/helps/en-US/content.txt b/www/helps/en-US/content.txt
new file mode 100644
index 0000000..010ee9c
--- /dev/null
+++ b/www/helps/en-US/content.txt
@@ -0,0 +1,2 @@
+helps/en-US/frequently-asked-questions-- frequently-asked-questions
+helps/en-US/glossary-- glossary
diff --git a/www/helps/en-US/frequently-asked-questions-- b/www/helps/en-US/frequently-asked-questions--
new file mode 100644
index 0000000..d41ad71
--- /dev/null
+++ b/www/helps/en-US/frequently-asked-questions--
@@ -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. --
diff --git a/www/helps/en-US/glossary-- b/www/helps/en-US/glossary--
new file mode 100644
index 0000000..63ff288
--- /dev/null
+++ b/www/helps/en-US/glossary--
@@ -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 printer’s “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. --
+-
diff --git a/www/index.html b/www/index.html
index e80736f..fb698a0 100644
--- a/www/index.html
+++ b/www/index.html
@@ -70,7 +70,7 @@
+
-
+
diff --git a/www/jslicense.html b/www/jslicense.html
index 14b69e5..3105a1a 100644
--- a/www/jslicense.html
+++ b/www/jslicense.html
@@ -68,6 +68,12 @@
image.js |
For canvas image manipulation |
+
+ dash-xml.js |
+ CC0-1.0 |
+ dash-xml.ts |
+ For translating Help documents to HTML |
+
accessibility.js |
CC0-1.0 |
diff --git a/www/lang/de-DE.json b/www/lang/de-DE.json
index 912bef2..0c9751e 100644
--- a/www/lang/de-DE.json
+++ b/www/lang/de-DE.json
@@ -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",
diff --git a/www/lang/en-US.json b/www/lang/en-US.json
index dfb7224..68d35cf 100644
--- a/www/lang/en-US.json
+++ b/www/lang/en-US.json
@@ -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"
}
\ No newline at end of file
diff --git a/www/lang/lolcat.json b/www/lang/lolcat.json
index 569f9bf..6f752e7 100644
--- a/www/lang/lolcat.json
+++ b/www/lang/lolcat.json
@@ -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"
}
diff --git a/www/lang/zh-CN.json b/www/lang/zh-CN.json
index 78b1f1b..23dd7b0 100644
--- a/www/lang/zh-CN.json
+++ b/www/lang/zh-CN.json
@@ -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": "术语解释"
}
\ No newline at end of file
diff --git a/www/lang/zh-HK.json b/www/lang/zh-HK.json
index f6742ec..3fd104c 100644
--- a/www/lang/zh-HK.json
+++ b/www/lang/zh-HK.json
@@ -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": "術語解釋"
}
\ No newline at end of file
diff --git a/www/lang/zh-Hant-CN.json b/www/lang/zh-Hant-CN.json
index 5cb5de0..faa8249 100644
--- a/www/lang/zh-Hant-CN.json
+++ b/www/lang/zh-Hant-CN.json
@@ -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": "術語解釋"
}
\ No newline at end of file
diff --git a/www/lang/zh-TW.json b/www/lang/zh-TW.json
index 40c29d4..88e0af7 100644
--- a/www/lang/zh-TW.json
+++ b/www/lang/zh-TW.json
@@ -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": "術語解釋"
}
\ No newline at end of file
diff --git a/www/loader.js b/www/loader.js
index 2a8515f..3395cf2 100644
--- a/www/loader.js
+++ b/www/loader.js
@@ -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;
diff --git a/www/main.css b/www/main.css
index a7b759a..bcddb3b 100644
--- a/www/main.css
+++ b/www/main.css
@@ -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);
diff --git a/www/main.js b/www/main.js
index 6dda0d6..8177a85 100644
--- a/www/main.js
+++ b/www/main.js
@@ -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');