Update dependencies, start work on editor, add hidden admin page

This commit is contained in:
octospacc 2024-10-22 00:40:51 +02:00
parent 33a9cdb33a
commit 700d4c872e
13 changed files with 314 additions and 91 deletions

3
.gitignore vendored
View File

@ -14,3 +14,6 @@
tmp.* tmp.*
.env .env
.hugo_build.lock .hugo_build.lock
/static/lib/SpaccDotWeb.Alt.min.js
/static/lib/toastui-editor-all.min.js
/static/lib/toastui-editor.min.css

67
Scripts/Dependencies.Build.sh Executable file
View File

@ -0,0 +1,67 @@
#!/bin/sh
. "$(dirname "$(realpath "$0")")/Lib/Globals.sh"
cd "${swd}/.."
alias asroot=""
if [ "$(whoami)" != root ] && [ "$(uname -o)" != Android ]
then alias asroot=sudo
fi
hugoexternal=true
if [ -n "$(which apt)" ]
then
asroot apt update
asroot apt install -y python3 nodejs findutils git wget tar gzip p7zip-full #zip
if [ "$(uname -o)" != Android ]
then asroot apt install -y npm
else
asroot apt install -y hugo
hugoexternal=false
fi
elif [ -n "$(which apk)" ]
then
asroot apk update
asroot apk add hugo python3 py3-pip nodejs npm findutils git wget tar gzip 7zip #zip
hugoexternal=false
fi
if [ "${hugoexternal}" = true ]
then
exehome="$([ -n "${XDG_DATA_HOME}" ] \
&& echo "${XDG_DATA_HOME}" \
|| echo "${HOME}/.local" \
)/bin"
exedepot="${exehome}/hugo.tmp"
exearchive="${exedepot}/hugo_extended.tar.gz"
sysarch="$(uname -m)"
if [ "${sysarch}" = x86_64 ]
then sysarch=amd64
elif [ "${sysarch}" = aarch64 ]
then sysarch=arm64
fi
mkdir -p "${exedepot}"
wget -O "${exearchive}" "https://github.com/gohugoio/hugo/releases/download/v${HugoVersion}/hugo_extended_${HugoVersion}_linux-${sysarch}.tar.gz"
tar xvf "${exearchive}" --directory "${exedepot}"
mv "${exedepot}/hugo" "${exehome}/hugo"
chmod +x "${exehome}/hugo"
rm -rf "${exedepot}"
if [ -z "$(which hugo)" ]
then
BinaryPath='PATH="${PATH}:'"${BinaryHome}"'"'
eval "${BinaryPath}"
echo >> ~/.profile
echo "${BinaryPath}" >> ~/.profile
fi
fi
cd ./Scripts
PIP_BREAK_SYSTEM_PACKAGES=1 "${Python3}" -m pip install -U -r ./requirements.txt
#npm install
cd ./Lib
wget -O ./translate-shell.bash https://git.io/trans
cd "${owd}"

10
Scripts/Dependencies.Runtime.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
. "$(dirname "$(realpath "$0")")/Lib/Globals.sh"
cd "${swd}/.."
cd ./static/lib
wget --continue "https://spaccinc.gitlab.io/SpaccDotWeb/SpaccDotWeb.Alt.min.js"
wget --continue "https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"
wget --continue "https://uicdn.toast.com/editor/latest/toastui-editor.min.css"
cd "${owd}"

View File

@ -2,66 +2,7 @@
. "$(dirname "$(realpath "$0")")/Lib/Globals.sh" . "$(dirname "$(realpath "$0")")/Lib/Globals.sh"
cd "${swd}/.." cd "${swd}/.."
alias asroot="" sh "${swd}/Dependencies.Build.sh"
if [ "$(whoami)" != root ] && [ "$(uname -o)" != Android ] sh "${swd}/Dependencies.Runtime.sh"
then alias asroot=sudo
fi
hugoexternal=true
if [ -n "$(which apt)" ]
then
asroot apt update
asroot apt install -y python3 nodejs findutils git wget tar gzip p7zip-full #zip
if [ "$(uname -o)" != Android ]
then asroot apt install -y npm
else
asroot apt install -y hugo
hugoexternal=false
fi
elif [ -n "$(which apk)" ]
then
asroot apk update
asroot apk add hugo python3 py3-pip nodejs npm findutils git wget tar gzip 7zip #zip
hugoexternal=false
fi
if [ "${hugoexternal}" = true ]
then
exehome="$([ -n "${XDG_DATA_HOME}" ] \
&& echo "${XDG_DATA_HOME}" \
|| echo "${HOME}/.local" \
)/bin"
exedepot="${exehome}/hugo.tmp"
exearchive="${exedepot}/hugo_extended.tar.gz"
sysarch="$(uname -m)"
if [ "${sysarch}" = x86_64 ]
then sysarch=amd64
elif [ "${sysarch}" = aarch64 ]
then sysarch=arm64
fi
mkdir -p "${exedepot}"
wget -O "${exearchive}" "https://github.com/gohugoio/hugo/releases/download/v${HugoVersion}/hugo_extended_${HugoVersion}_linux-${sysarch}.tar.gz"
tar xvf "${exearchive}" --directory "${exedepot}"
mv "${exedepot}/hugo" "${exehome}/hugo"
chmod +x "${exehome}/hugo"
rm -rf "${exedepot}"
if [ -z "$(which hugo)" ]
then
BinaryPath='PATH="${PATH}:'"${BinaryHome}"'"'
eval "${BinaryPath}"
echo >> ~/.profile
echo "${BinaryPath}" >> ~/.profile
fi
fi
cd ./Scripts
PIP_BREAK_SYSTEM_PACKAGES=1 "${Python3}" -m pip install -U -r ./requirements.txt
#npm install
cd ./Lib
wget -O ./translate-shell.bash https://git.io/trans
cd "${owd}" cd "${owd}"

10
content/it/admin.md Normal file
View File

@ -0,0 +1,10 @@
+++
Hidden = true
+++
<form>
<p><label>Git Instance: &nbsp; <input type="url" name="instance"/></label></p>
<p><label>Repository: &nbsp; <input type="text" name="repo"/></label></p>
<p><label>Branch: &nbsp; <input type="text" name="branch"/></label></p>
<p><label>Access Token: &nbsp; <input type="password" name="token"/></label></p>
</form>
<style> form > p > label > input { float: right; } </style>

View File

@ -1,6 +1,7 @@
{{- $index := slice -}} {{- $index := slice -}}
{{- $pages := .Site.Pages -}} {{- $pages := .Site.Pages -}}
{{- range $pages -}} {{- range $pages -}}
{{- if not .Params.Hidden -}}
{{- $section := .Site.GetPage "section" .Section -}} {{- $section := .Site.GetPage "section" .Section -}}
{{- $page := (dict {{- $page := (dict
"title" (.Title | emojify | safeJS) "title" (.Title | emojify | safeJS)
@ -18,4 +19,5 @@
{{- end -}} {{- end -}}
{{- $index = $index | append $page -}} {{- $index = $index | append $page -}}
{{- end -}} {{- end -}}
{{- end -}}
window.SiteSearchIndex={{- $index | jsonify -}} window.SiteSearchIndex={{- $index | jsonify -}}

View File

@ -2,7 +2,7 @@
id="search-wrapper" id="search-wrapper"
class="fixed flex top-0 w-100 vh-100 inset-0 flex-col pa4 bg-neutral-500/50 p-4 dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]" class="fixed flex top-0 w-100 vh-100 inset-0 flex-col pa4 bg-neutral-500/50 p-4 dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]"
data-url="{{ "" | absLangURL }}" data-url="{{ "" | absLangURL }}"
style="word-break:break-word; visibility:hidden; z-index:500; background-color:rgb(253, 244, 255, 0.9); backdrop-filter:blur(8px);" style="word-break:break-word; display:none; visibility:hidden; z-index:500; background-color:rgb(253, 244, 255, 0.9); backdrop-filter:blur(8px);"
> >
<div <div
id="search-modal" id="search-modal"

177
static/markdown-editor.js Normal file
View File

@ -0,0 +1,177 @@
(function(){
const editorId = '--markdown-editor';
const resetFileMessage = 'Reset File to Latest from Git';
const gitPushMessage = 'Commit and Push changes to Git';
// TODO configure this and access token via HTML form
const G = {
instance: 'https://gitlab.com',
repo: 'octtspacc/sitoctt',
branch: 'sitoctt-next',
};
const editorData = {
currentFilePath: `content/${document.documentElement.lang}/${document.documentElement.dataset.sourceFilePath}`,
};
let editorHandler;
const gitReadFile = async (filePath) => (await (await fetch(`${G.instance}/api/v4/projects/${encodeURIComponent(G.repo)}/repository/files/${encodeURIComponent(filePath)}/raw?ref=${G.branch}`)).text());
const gitPushFile = (filePath, fileContent) => null; // TODO
const readPageFile = async (filePath) => { // TODO read cached file in localStorage, but not when a newer one is on git
//if (!filePath) {
// return '';
//}
return await gitReadFile(filePath);
};
const cachePageFile = async (filePath, fileContent) => null; // TODO write to localStorage, trigger on any text input
const displayCurrentFile = () => document.querySelector('#--editor-buttons').querySelector('span').innerHTML = `(<code>${editorData.currentFilePath}</code>)`;
editorData.close = () => {
const editorEl = document.querySelector(`#${editorId}`);
editorEl.hidden = true;
editorEl.style.display = 'none';
document.body.style.overflow = null;
};
editorData.setup = async (/*filePath*/) => {
if (editorHandler) {
return;
}
document.head.appendChild(Object.assign(document.createElement('style'), { innerHTML: `
#${editorId} {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 100%;
z-index: 9;
background-color: rgba(255, 255, 255, 0.5);
}
#${editorId} .toastui-editor-defaultUI {
width: 95%;
height: 95%;
top: 2.5%;
bottom: 2.5%;
left: 2.5%;
right: 2.5%;
background-color: ghostwhite;
}
#${editorId} .toastui-editor-main-container,
#${editorId} .ProseMirror {
height: 100%;
font-size: 16px;
}
/* quick fix for showing all buttons on mobile */
#${editorId} .toastui-editor-dropdown-toolbar {
display: table;
}
#${editorId} .toastui-editor-toolbar-divider {
display: none;
}
` }));
document.head.appendChild(Object.assign(document.createElement('link'), {
rel: "stylesheet", href: "/lib/toastui-editor.min.css",
}));
document.body.appendChild(Object.assign(document.createElement('div'), {
id: editorId, hidden: true, style: "display: none;",
}));
await SpaccDotWeb.requireScript('/lib/toastui-editor-all.min.js');
editorHandler = new toastui.Editor({
el: document.querySelector(`#${editorId}`),
height: '100%',
previewStyle: 'tab',
hideModeSwitch: true,
usageStatistics: false,
initialValue: (await readPageFile(editorData.currentFilePath)),
});
editorHandler.addCommand('markdown', 'closeEditor', editorData.close);
editorHandler.addCommand('markdown', 'resetFile', (() => { // TODO re-pull page source from git
if (confirm(`${resetFileMessage}?`)) {
gitReadFile(editorData.currentFilePath);
}
}));
editorHandler.addCommand('markdown', 'gitPush', (() => {
if (confirm(`${gitPushMessage}?`)) {
gitPushFile(editorData.currentFilePath);
}
}));
editorHandler.insertToolbarItem({ groupIndex: 6 }, {
tooltip: gitPushMessage,
command: 'gitPush',
text: '@',
className: 'toastui-editor-toolbar-icons',
style: { backgroundImage: 'none' },
});
/* editorHandler.insertToolbarItem({ groupIndex: 6 }, { // TODO
tooltip: resetFileMessage,
command: 'resetFile',
text: '#',
className: 'toastui-editor-toolbar-icons',
style: { backgroundImage: 'none' },
}); */
editorHandler.insertToolbarItem({ groupIndex: 6 }, {
tooltip: "Close the Editor",
command: 'closeEditor',
text: 'X',
className: 'toastui-editor-toolbar-icons',
style: { backgroundImage: 'none' },
});
editorData.setupButtons();
editorData.setup = Void;
};
editorData.setupButtons = () => {
const buttonsEl = document.querySelector('#--editor-buttons');
displayCurrentFile();
buttonsEl.querySelector('[name="this"]').onclick = editorData.open;
buttonsEl.querySelector('[name="custom"]').onclick = (async () => {
const filePath = prompt(`Path of custom File?`);
if (filePath) {
await editorData.setup(/*filePath*/);
const fileContent = await readPageFile(editorData.currentFilePath = filePath);
displayCurrentFile();
editorHandler.setMarkdown(fileContent);
await editorData.open();
}
});
buttonsEl.style.display = null;
delete editorData.setupButtons;
};
editorData.open = async () => {
await editorData.setup(/*filePath*/);
const editorEl = document.querySelector(`#${editorId}`);
editorEl.style.display = 'block';
editorEl.hidden = false;
document.body.style.overflow = 'hidden';
};
window.sitoctt.markdownEditor = editorData;
if (false) { // TODO show edit page button and presetup editor if localStorage contains token
window.addEventListener('load', editorData.setup);
}
})();

View File

@ -8,6 +8,10 @@ vaNp2PerVDzUvdLlZKazGYIHXb5xduSnRp4HRHU9TMzSyuP5fr9XohcCAwEAAQ==`,
var signatureScheme = 'RSASSA-PKCS1-v1_5'; var signatureScheme = 'RSASSA-PKCS1-v1_5';
var encryptionType = {name: signatureScheme, hash: {name: "SHA-256"}}; var encryptionType = {name: signatureScheme, hash: {name: "SHA-256"}};
function ensureRequirements () {
return SpaccDotWeb.requireScript('./forge.min.js', { useCurrentPath: true });
}
async function makeSignedScript (scriptText, keyIndex, pemPrivateKey) { async function makeSignedScript (scriptText, keyIndex, pemPrivateKey) {
return ('1,' return ('1,'
+ keyIndex + ',' + keyIndex + ','
@ -111,11 +115,15 @@ function verificationKeyFromPublicKeyPEM (pemPublicKey) {
["verify"]); ["verify"]);
} }
window.OcttRuntime = { makeSignedScript, verifyAndRunScript }; window.OcttRuntime = { ensureRequirements, verifyAndRunScript, makeSignedScript };
window.addEventListener('load', (function(){
var scriptCipher = (new URLSearchParams(location.search)).get('octtRuntime'); var scriptCipher = (new URLSearchParams(location.search)).get('octtRuntime');
if (scriptCipher) { if (scriptCipher) {
ensureRequirements().then(function(){
verifyAndRunScript(scriptCipher); verifyAndRunScript(scriptCipher);
});
} }
}));
})(); })();

View File

@ -1,5 +1,4 @@
(function(){ (function(){
// TODO make links work on file:/// (must be relative)
// TODO fix ajax navigation to different-language page, doesn't currently load the index for the selected language // TODO fix ajax navigation to different-language page, doesn't currently load the index for the selected language
// TODO better perf // TODO better perf
// TODO thumbnails? // TODO thumbnails?
@ -93,8 +92,9 @@ function displaySearch() {
buildIndex(); buildIndex();
} }
if (!searchVisible) { if (!searchVisible) {
document.body.style.overflow = "hidden"; document.body.style.overflow = 'hidden';
wrapper.style.visibility = "visible"; wrapper.style.visibility = 'visible';
wrapper.style.display = '';
input.focus(); input.focus();
searchVisible = true; searchVisible = true;
} }
@ -103,8 +103,9 @@ function displaySearch() {
function hideSearch() { function hideSearch() {
if (searchVisible) { if (searchVisible) {
document.body.style.overflow = "visible"; document.body.style.overflow = 'visible';
wrapper.style.visibility = "hidden"; wrapper.style.visibility = 'hidden';
wrapper.style.display = 'none';
input.value = ""; input.value = "";
document.querySelector('.SiteSearchForm > input').value = ""; document.querySelector('.SiteSearchForm > input').value = "";
output.innerHTML = ""; output.innerHTML = "";

View File

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{{ site.LanguageCode | default site.Language.Lang }}" {{- with partialCached "func/GetLanguageDirection" "GetLanguageDirection" }} dir="{{ . }}" {{- end }}> <html lang="{{ site.LanguageCode | default site.Language.Lang }}" {{- with partialCached "func/GetLanguageDirection" "GetLanguageDirection" }} dir="{{ . }}" {{- end }} data-source-file-path="{{ with .File }}{{ .Path }}{{ end }}">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

View File

@ -1,5 +1,8 @@
<footer class="{{ .Site.Params.background_color_class | default "bg-black" }} bottom-0 w-100 pa3" role="contentinfo" style="background-color: #330066;"> <footer class="{{ .Site.Params.background_color_class | default "bg-black" }} bottom-0 w-100 pa3" role="contentinfo" style="background-color: #330066;">
<a href="#!/header" class="fixed bg-dark-gray pa3 br-100 bottom-1 right-1" style="background-color:#707; z-index:9;">⬆️</a> <a href="#!/header" class="fixed bg-dark-gray pa3 br-100 bottom-1 right-1" style="background-color:#707; z-index:9;">⬆️</a>
<p id="--editor-buttons" class="white tr" style="display: none;">
📝️ Edit <span class="f7"></span> <button name="this">Current Page</button> <button name="custom">Custom File</button>
</p>
<div class="flex justify-between"> <div class="flex justify-between">
<a class="fw4 hover-white no-underline white-80 dib-ns pv2 ph3" href="{{ .Site.Home.Permalink }}" > <a class="fw4 hover-white no-underline white-80 dib-ns pv2 ph3" href="{{ .Site.Home.Permalink }}" >
&copy; {{ with .Site.Copyright | default .Site.Title }} {{ . | safeHTML }} 2022{{ now.Format "2006" }} {{ end }} &copy; {{ with .Site.Copyright | default .Site.Title }} {{ . | safeHTML }} 2022{{ now.Format "2006" }} {{ end }}

View File

@ -1,10 +1,11 @@
<script> window.Void = (function Void(){}); </script> <script> window.sitoctt = {}; window.Void = (function Void(){}); </script>
<script src="/ajax-navigation.js"></script> <script src="/ajax-navigation.js"></script>
<script src="/local-file-tweaks.js"></script> <script src="/local-file-tweaks.js"></script>
<script src="/{{ .Lang }}/searchindex.js"></script> <script src="/{{ .Lang }}/searchindex.js"></script>
<script src="/lib/fuse.min.js"></script> <script src="/lib/fuse.min.js"></script>
<script src="/lib/forge.min.js"></script> <script src="/lib/SpaccDotWeb.Alt.min.js"></script>
<script src="/octt-runtime.js"></script> <script src="/octt-runtime.js"></script>
{{ if hugo.IsProduction }} {{ if hugo.IsProduction }}
<script src="/analytics.js"></script> <script src="/analytics.js"></script>
{{ end }} {{ end }}
<script src="/markdown-editor.js"></script>