mirror of
https://github.com/thomiceli/opengist.git
synced 2024-12-31 15:22:39 +00:00
Convert Javascript to Typescript
This commit is contained in:
parent
0eb1b103d0
commit
8b08c5a5cc
9 changed files with 324 additions and 302 deletions
162
public/editor.js
vendored
162
public/editor.js
vendored
|
@ -1,162 +0,0 @@
|
|||
import {EditorView, gutter, keymap, lineNumbers} from "@codemirror/view"
|
||||
import {Compartment, EditorState, Facet, SelectionRange} from "@codemirror/state"
|
||||
import {indentLess} from "@codemirror/commands";
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
EditorView.theme({}, {dark: true})
|
||||
|
||||
let editorsjs = []
|
||||
let editorsParentdom = document.getElementById('editors')
|
||||
let allEditorsdom = document.querySelectorAll('#editors > .editor')
|
||||
let firstEditordom = allEditorsdom[0]
|
||||
|
||||
const txtFacet = Facet.define({
|
||||
combine(values) {
|
||||
return values[0]
|
||||
}
|
||||
})
|
||||
let indentSize = new Compartment, wrapMode = new Compartment, indentType = new Compartment
|
||||
|
||||
const newEditor = (dom, value = '') => {
|
||||
let editor = new EditorView({
|
||||
doc: value,
|
||||
parent: dom,
|
||||
extensions: [
|
||||
lineNumbers(), gutter({class: "cm-mygutter"}),
|
||||
keymap.of([{key: "Tab", run: customIndentMore, shift: indentLess}]),
|
||||
indentSize.of(EditorState.tabSize.of(2)),
|
||||
wrapMode.of([]),
|
||||
indentType.of(txtFacet.of("space")),
|
||||
]
|
||||
})
|
||||
|
||||
dom.querySelector('.editor-indent-type').onchange = (e) => {
|
||||
let newTabType = e.target.value
|
||||
setIndentType(editor, !['tab', 'space'].includes(newTabType) ? 'space' : newTabType)
|
||||
}
|
||||
|
||||
dom.querySelector('.editor-indent-size').onchange = (e) => {
|
||||
let newTabSize = parseInt(e.target.value)
|
||||
setIndentSize(editor, ![2, 4, 8].includes(newTabSize) ? 2 : newTabSize)
|
||||
}
|
||||
|
||||
dom.querySelector('.editor-wrap-mode').onchange = (e) => {
|
||||
let newWrapMode = e.target.value
|
||||
setLineWrapping(editor, newWrapMode === 'soft')
|
||||
}
|
||||
|
||||
dom.addEventListener("drop", (e) => {
|
||||
e.preventDefault(); // prevent the browser from opening the dropped file
|
||||
e.target.closest('.editor').querySelector('input.form-filename').value = e.dataTransfer.files[0].name
|
||||
});
|
||||
|
||||
// remove editor on delete
|
||||
let deleteBtns = dom.querySelector('button.delete-file')
|
||||
if (deleteBtns !== null) {
|
||||
deleteBtns.onclick = () => {
|
||||
editorsjs.splice(editorsjs.indexOf(editor), 1);
|
||||
dom.remove()
|
||||
}
|
||||
}
|
||||
|
||||
editor.dom.addEventListener("input", function inputConfirmLeave() {
|
||||
if (!editor.inView) return; // skip events outside the viewport
|
||||
|
||||
editor.dom.removeEventListener("input", inputConfirmLeave);
|
||||
window.onbeforeunload = () => {
|
||||
return 'Are you sure you want to quit?';
|
||||
}
|
||||
});
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
function getIndentation(state) {
|
||||
if (indentType.get(state).value === 'tab') {
|
||||
return '\t';
|
||||
}
|
||||
return ' '.repeat(indentSize.get(state).value);
|
||||
}
|
||||
|
||||
function customIndentMore({state, dispatch}) {
|
||||
let indentation = getIndentation(state)
|
||||
dispatch({
|
||||
...state.update(changeBySelectedLine(state, (line, changes) => {
|
||||
changes.push({from: state.selection.ranges[0].from, insert: indentation})
|
||||
})), selection: {
|
||||
anchor: state.selection.ranges[0].from + indentation.length,
|
||||
head: state.selection.ranges[0].from + indentation.length,
|
||||
}
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
function changeBySelectedLine(state, f) {
|
||||
let atLine = -1
|
||||
return state.changeByRange(range => {
|
||||
let changes = []
|
||||
for (let line = state.doc.lineAt(range.from); ;) {
|
||||
if (line.number > atLine) {
|
||||
f(line, changes)
|
||||
atLine = line.number
|
||||
}
|
||||
if (range.to <= line.to) break
|
||||
line = state.doc.lineAt(line.number + 1)
|
||||
}
|
||||
let changeSet = state.changes(changes)
|
||||
return {
|
||||
changes,
|
||||
range: new SelectionRange(changeSet.mapPos(range.anchor, 1), changeSet.mapPos(range.head, 1))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function setIndentType(view, type) {
|
||||
view.dispatch({effects: indentType.reconfigure(txtFacet.of(type))})
|
||||
}
|
||||
|
||||
function setIndentSize(view, size) {
|
||||
view.dispatch({effects: indentSize.reconfigure(EditorState.tabSize.of(size))})
|
||||
}
|
||||
|
||||
function setLineWrapping(view, enable) {
|
||||
if (enable) {
|
||||
view.dispatch({effects: wrapMode.reconfigure(EditorView.lineWrapping)})
|
||||
} else {
|
||||
view.dispatch({effects: wrapMode.reconfigure([])})
|
||||
}
|
||||
}
|
||||
|
||||
let arr = [...allEditorsdom]
|
||||
arr.forEach(el => {
|
||||
// in case we edit the gist contents
|
||||
let currEditor = newEditor(el, el.querySelector('.form-filecontent').value)
|
||||
editorsjs.push(currEditor)
|
||||
})
|
||||
|
||||
document.getElementById('add-file').onclick = () => {
|
||||
let newEditorDom = firstEditordom.cloneNode(true)
|
||||
|
||||
// reset the filename of the new cloned element
|
||||
newEditorDom.querySelector('input[name="name"]').value = ""
|
||||
|
||||
// removing the previous codemirror editor
|
||||
let newEditorDomCM = newEditorDom.querySelector('.cm-editor')
|
||||
newEditorDomCM.remove()
|
||||
|
||||
// creating the new codemirror editor and append it in the editor div
|
||||
editorsjs.push(newEditor(newEditorDom))
|
||||
editorsParentdom.append(newEditorDom)
|
||||
}
|
||||
|
||||
document.querySelector('form#create').onsubmit = () => {
|
||||
let j = 0
|
||||
document.querySelectorAll('.form-filecontent').forEach((e) => {
|
||||
e.value = encodeURIComponent(editorsjs[j++].state.doc.toString())
|
||||
})
|
||||
}
|
||||
|
||||
document.onsubmit = () => {
|
||||
window.onbeforeunload = null;
|
||||
}
|
||||
})
|
171
public/editor.ts
vendored
Normal file
171
public/editor.ts
vendored
Normal file
|
@ -0,0 +1,171 @@
|
|||
import {EditorView, gutter, keymap, lineNumbers} from "@codemirror/view";
|
||||
import {Compartment, EditorState, Facet, Line, SelectionRange} from "@codemirror/state";
|
||||
import {indentLess} from "@codemirror/commands";
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
EditorView.theme({}, {dark: true});
|
||||
|
||||
let editorsjs: EditorView[] = [];
|
||||
let editorsParentdom = document.getElementById("editors")!;
|
||||
let allEditorsdom = document.querySelectorAll("#editors > .editor");
|
||||
let firstEditordom = allEditorsdom[0];
|
||||
|
||||
const txtFacet = Facet.define<string>({
|
||||
combine(values) {
|
||||
return values;
|
||||
},
|
||||
});
|
||||
|
||||
let indentSize = new Compartment(),
|
||||
wrapMode = new Compartment(),
|
||||
indentType = new Compartment();
|
||||
|
||||
const newEditor = (dom: HTMLElement, value: string = ""): EditorView => {
|
||||
let editor = new EditorView({
|
||||
doc: value,
|
||||
parent: dom,
|
||||
extensions: [
|
||||
lineNumbers(),
|
||||
gutter({class: "cm-mygutter"}),
|
||||
keymap.of([{key: "Tab", run: customIndentMore, shift: indentLess}]),
|
||||
indentSize.of(EditorState.tabSize.of(2)),
|
||||
wrapMode.of([]),
|
||||
indentType.of(txtFacet.of("space")),
|
||||
],
|
||||
});
|
||||
|
||||
dom.querySelector<HTMLInputElement>(".editor-indent-type")!.onchange = (e) => {
|
||||
let newTabType = (e.target as HTMLInputElement).value;
|
||||
setIndentType(editor, !["tab", "space"].includes(newTabType) ? "space" : newTabType);
|
||||
};
|
||||
|
||||
dom.querySelector<HTMLInputElement>(".editor-indent-size")!.onchange = (e) => {
|
||||
let newTabSize = parseInt((e.target as HTMLInputElement).value);
|
||||
setIndentSize(editor, ![2, 4, 8].includes(newTabSize) ? 2 : newTabSize);
|
||||
};
|
||||
|
||||
dom.querySelector<HTMLInputElement>(".editor-wrap-mode")!.onchange = (e) => {
|
||||
let newWrapMode = (e.target as HTMLInputElement).value;
|
||||
setLineWrapping(editor, newWrapMode === "soft");
|
||||
};
|
||||
|
||||
dom.addEventListener("drop", (e) => {
|
||||
e.preventDefault(); // prevent the browser from opening the dropped file
|
||||
(e.target as HTMLInputElement)
|
||||
.closest(".editor")
|
||||
.querySelector<HTMLInputElement>("input.form-filename")!.value =
|
||||
e.dataTransfer.files[0].name;
|
||||
});
|
||||
|
||||
// remove editor on delete
|
||||
let deleteBtns = dom.querySelector<HTMLButtonElement>("button.delete-file");
|
||||
if (deleteBtns !== null) {
|
||||
deleteBtns.onclick = () => {
|
||||
editorsjs.splice(editorsjs.indexOf(editor), 1);
|
||||
dom.remove();
|
||||
};
|
||||
}
|
||||
|
||||
editor.dom.addEventListener("input", function inputConfirmLeave() {
|
||||
if (!editor.inView) return; // skip events outside the viewport
|
||||
|
||||
editor.dom.removeEventListener("input", inputConfirmLeave);
|
||||
window.onbeforeunload = () => {
|
||||
return "Are you sure you want to quit?";
|
||||
};
|
||||
});
|
||||
|
||||
return editor;
|
||||
};
|
||||
|
||||
function getIndentation(state: EditorState): string {
|
||||
// @ts-ignore
|
||||
if (indentType.get(state).value === "tab") {
|
||||
return "\t";
|
||||
}
|
||||
// @ts-ignore
|
||||
return " ".repeat(indentSize.get(state).value);
|
||||
}
|
||||
|
||||
function customIndentMore({state, dispatch,}: { state: EditorState; dispatch: (value: any) => void; }): boolean {
|
||||
let indentation = getIndentation(state);
|
||||
dispatch({
|
||||
...state.update(changeBySelectedLine(state, (line, changes) => {
|
||||
changes.push({from: state.selection.ranges[0].from, insert: indentation,});
|
||||
})),
|
||||
selection: {
|
||||
anchor: state.selection.ranges[0].from + indentation.length,
|
||||
head: state.selection.ranges[0].from + indentation.length,
|
||||
},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function changeBySelectedLine(state: EditorState, f: (line: Line, changes: any[]) => void): any {
|
||||
let atLine = -1;
|
||||
return state.changeByRange((range) => {
|
||||
let changes: any[] = [];
|
||||
for (let line = state.doc.lineAt(range.from); ;) {
|
||||
if (line.number > atLine) {
|
||||
f(line, changes);
|
||||
atLine = line.number;
|
||||
}
|
||||
if (range.to <= line.to) break;
|
||||
line = state.doc.lineAt(line.number + 1);
|
||||
}
|
||||
let changeSet = state.changes(changes);
|
||||
return {
|
||||
changes,
|
||||
// @ts-ignore
|
||||
range: new SelectionRange(changeSet.mapPos(range.anchor, 1), changeSet.mapPos(range.head, 1)),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function setIndentType(view: EditorView, type: string): void {
|
||||
view.dispatch({effects: indentType.reconfigure(txtFacet.of(type))});
|
||||
}
|
||||
|
||||
function setIndentSize(view: EditorView, size: number): void {
|
||||
view.dispatch({effects: indentSize.reconfigure(EditorState.tabSize.of(size))});
|
||||
}
|
||||
|
||||
function setLineWrapping(view: EditorView, enable: boolean): void {
|
||||
view.dispatch({
|
||||
effects: wrapMode.reconfigure(enable ? EditorView.lineWrapping : []),
|
||||
});
|
||||
}
|
||||
|
||||
let arr = Array.from(allEditorsdom);
|
||||
arr.forEach((el: HTMLElement) => {
|
||||
// in case we edit the gist contents
|
||||
let currEditor = newEditor(el, el.querySelector<HTMLInputElement>(".form-filecontent")!.value);
|
||||
editorsjs.push(currEditor);
|
||||
});
|
||||
|
||||
document.getElementById("add-file")!.onclick = () => {
|
||||
let newEditorDom = firstEditordom.cloneNode(true) as HTMLElement;
|
||||
|
||||
// reset the filename of the new cloned element
|
||||
newEditorDom.querySelector<HTMLInputElement>('input[name="name"]')!.value = "";
|
||||
|
||||
// removing the previous codemirror editor
|
||||
let newEditorDomCM = newEditorDom.querySelector(".cm-editor");
|
||||
newEditorDomCM!.remove();
|
||||
|
||||
// creating the new codemirror editor and append it in the editor div
|
||||
editorsjs.push(newEditor(newEditorDom));
|
||||
editorsParentdom.append(newEditorDom);
|
||||
};
|
||||
|
||||
document.querySelector<HTMLFormElement>("form#create")!.onsubmit = () => {
|
||||
let j = 0;
|
||||
document.querySelectorAll<HTMLInputElement>(".form-filecontent").forEach((e) => {
|
||||
e.value = encodeURIComponent(editorsjs[j++].state.doc.toString());
|
||||
});
|
||||
};
|
||||
|
||||
document.onsubmit = () => {
|
||||
window.onbeforeunload = null;
|
||||
};
|
||||
});
|
136
public/main.js
vendored
136
public/main.js
vendored
|
@ -1,136 +0,0 @@
|
|||
import './style.css'
|
||||
import './markdown.css'
|
||||
import './favicon.svg'
|
||||
import 'highlight.js/styles/tokyo-night-dark.css'
|
||||
import moment from 'moment'
|
||||
import md from 'markdown-it'
|
||||
import hljs from 'highlight.js'
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('.moment-timestamp').forEach((e) => {
|
||||
e.title = moment.unix(e.innerHTML).format('LLLL')
|
||||
e.innerHTML = moment.unix(e.innerHTML).fromNow()
|
||||
})
|
||||
|
||||
document.querySelectorAll('.moment-timestamp-date').forEach((e) => {
|
||||
e.innerHTML = moment.unix(e.innerHTML).format('DD/MM/YYYY HH:mm')
|
||||
})
|
||||
|
||||
let rev = document.querySelector('.revision-text')
|
||||
if (rev) {
|
||||
let fullRev = rev.innerHTML
|
||||
let smallRev = fullRev.substring(0, 7)
|
||||
rev.innerHTML = smallRev
|
||||
|
||||
rev.onmouseover = () => {
|
||||
rev.innerHTML = fullRev
|
||||
}
|
||||
rev.onmouseout = () => {
|
||||
rev.innerHTML = smallRev
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('.markdown').forEach((e) => {
|
||||
e.innerHTML = md().render(e.innerHTML);
|
||||
})
|
||||
|
||||
document.querySelectorAll('.table-code').forEach((el) => {
|
||||
let ext = el.dataset.filename.split('.').pop()
|
||||
|
||||
if (hljs.autoDetection(ext) && ext !== 'txt') {
|
||||
el.querySelectorAll('td.line-code').forEach((ell) => {
|
||||
ell.classList.add('language-'+ext)
|
||||
hljs.highlightElement(ell);
|
||||
});
|
||||
}
|
||||
|
||||
// more efficient
|
||||
el.addEventListener('click', event => {
|
||||
if (event.target.matches('.line-num')) {
|
||||
Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected'));
|
||||
|
||||
event.target.nextSibling.classList.add('selected')
|
||||
|
||||
let filename = el.dataset.filenameSlug
|
||||
let line = event.target.textContent
|
||||
let url = location.protocol + '//' + location.host + location.pathname
|
||||
let hash = '#file-'+ filename + '-' +line
|
||||
window.history.pushState(null, null, url+hash);
|
||||
location.hash = hash;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
let colorhash = () => {
|
||||
Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected'));
|
||||
let lineEl = document.querySelector(location.hash)
|
||||
if (lineEl) {
|
||||
lineEl.nextSibling.classList.add('selected')
|
||||
}
|
||||
}
|
||||
|
||||
if (location.hash) {
|
||||
colorhash()
|
||||
}
|
||||
window.onhashchange = colorhash
|
||||
|
||||
document.getElementById('main-menu-button').onclick = () => {
|
||||
document.getElementById('mobile-menu').classList.toggle('hidden')
|
||||
}
|
||||
|
||||
let tabs = document.getElementById('gist-tabs')
|
||||
if (tabs) {
|
||||
tabs.onchange = (e) => {
|
||||
// navigate to the url in data-url
|
||||
window.location.href = e.target.selectedOptions[0].dataset.url
|
||||
}
|
||||
}
|
||||
|
||||
let gistmenutoggle = document.getElementById('gist-menu-toggle');
|
||||
if (gistmenutoggle) {
|
||||
let gistmenucopy = document.getElementById('gist-menu-copy')
|
||||
let gistmenubuttoncopy = document.getElementById('gist-menu-button-copy')
|
||||
let gistmenuinput = document.getElementById('gist-menu-input')
|
||||
let gistmenutitle = document.getElementById('gist-menu-title')
|
||||
gistmenutitle.textContent = gistmenucopy.children[0].firstChild.textContent
|
||||
gistmenuinput.value = gistmenucopy.children[0].dataset.link
|
||||
|
||||
gistmenutoggle.onclick = () => {
|
||||
gistmenucopy.classList.toggle('hidden')
|
||||
}
|
||||
|
||||
for (let item of gistmenucopy.children) {
|
||||
item.onclick = () => {
|
||||
gistmenutitle.textContent = item.firstChild.textContent
|
||||
gistmenuinput.value = item.dataset.link
|
||||
gistmenucopy.classList.toggle('hidden')
|
||||
}
|
||||
}
|
||||
|
||||
gistmenubuttoncopy.onclick = () => {
|
||||
let text = gistmenuinput.value
|
||||
navigator.clipboard.writeText(text).then(null, function(err) {
|
||||
console.error('Could not copy text: ', err);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let sortgist = document.getElementById('sort-gists-button')
|
||||
if (sortgist) {
|
||||
sortgist.onclick = () => {
|
||||
document.getElementById('sort-gists-dropdown').classList.toggle('hidden')
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('.copy-gist-btn').forEach((e) => {
|
||||
e.onclick = () => {
|
||||
navigator.clipboard.writeText(e.parentNode.querySelector('.gist-content').textContent).then(null, function (err) {
|
||||
console.error('Could not copy text: ', err);
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
});
|
140
public/main.ts
vendored
Normal file
140
public/main.ts
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
import './style.css';
|
||||
import './markdown.css';
|
||||
import './favicon.svg';
|
||||
import 'highlight.js/styles/tokyo-night-dark.css';
|
||||
import moment from 'moment';
|
||||
import md from 'markdown-it';
|
||||
import hljs from 'highlight.js';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.querySelectorAll('.moment-timestamp').forEach((e: HTMLElement) => {
|
||||
e.title = moment.unix(parseInt(e.innerHTML)).format('LLLL');
|
||||
e.innerHTML = moment.unix(parseInt(e.innerHTML)).fromNow();
|
||||
});
|
||||
|
||||
document.querySelectorAll('.moment-timestamp-date').forEach((e: HTMLElement) => {
|
||||
e.innerHTML = moment.unix(parseInt(e.innerHTML)).format('DD/MM/YYYY HH:mm');
|
||||
});
|
||||
|
||||
const rev = document.querySelector<HTMLElement>('.revision-text');
|
||||
if (rev) {
|
||||
const fullRev = rev.innerHTML;
|
||||
const smallRev = fullRev.substring(0, 7);
|
||||
rev.innerHTML = smallRev;
|
||||
|
||||
rev.onmouseover = () => {
|
||||
rev.innerHTML = fullRev;
|
||||
};
|
||||
rev.onmouseout = () => {
|
||||
rev.innerHTML = smallRev;
|
||||
};
|
||||
}
|
||||
|
||||
document.querySelectorAll('.markdown').forEach((e: HTMLElement) => {
|
||||
e.innerHTML = md().render(e.innerHTML);
|
||||
});
|
||||
|
||||
document.querySelectorAll<HTMLElement>('.table-code').forEach((el) => {
|
||||
const ext = el.dataset.filename?.split('.').pop() || '';
|
||||
|
||||
if (hljs.autoDetection(ext) && ext !== 'txt') {
|
||||
el.querySelectorAll<HTMLElement>('td.line-code').forEach((ell) => {
|
||||
ell.classList.add('language-' + ext);
|
||||
hljs.highlightElement(ell);
|
||||
});
|
||||
}
|
||||
|
||||
el.addEventListener('click', event => {
|
||||
if (event.target && (event.target as HTMLElement).matches('.line-num')) {
|
||||
Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected'));
|
||||
|
||||
const nextSibling = (event.target as HTMLElement).nextSibling;
|
||||
if (nextSibling instanceof HTMLElement) {
|
||||
nextSibling.classList.add('selected');
|
||||
}
|
||||
|
||||
|
||||
const filename = el.dataset.filenameSlug;
|
||||
const line = (event.target as HTMLElement).textContent;
|
||||
const url = location.protocol + '//' + location.host + location.pathname;
|
||||
const hash = '#file-' + filename + '-' + line;
|
||||
window.history.pushState(null, null, url + hash);
|
||||
location.hash = hash;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const colorhash = () => {
|
||||
Array.from(document.querySelectorAll('.table-code .selected')).forEach((el) => el.classList.remove('selected'));
|
||||
const lineEl = document.querySelector<HTMLElement>(location.hash);
|
||||
if (lineEl) {
|
||||
const nextSibling = lineEl.nextSibling;
|
||||
if (nextSibling instanceof HTMLElement) {
|
||||
nextSibling.classList.add('selected');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (location.hash) {
|
||||
colorhash();
|
||||
}
|
||||
window.onhashchange = colorhash;
|
||||
|
||||
document.getElementById('main-menu-button')!.onclick = () => {
|
||||
document.getElementById('mobile-menu')!.classList.toggle('hidden');
|
||||
};
|
||||
|
||||
const tabs = document.getElementById('gist-tabs');
|
||||
if (tabs) {
|
||||
tabs.onchange = (e: Event) => {
|
||||
const target = e.target as HTMLSelectElement;
|
||||
window.location.href = target.selectedOptions[0].dataset.url || '';
|
||||
};
|
||||
}
|
||||
|
||||
const gistmenutoggle = document.getElementById('gist-menu-toggle');
|
||||
if (gistmenutoggle) {
|
||||
const gistmenucopy = document.getElementById('gist-menu-copy')!;
|
||||
const gistmenubuttoncopy = document.getElementById('gist-menu-button-copy')!;
|
||||
const gistmenuinput = document.getElementById('gist-menu-input') as HTMLInputElement;
|
||||
const gistmenutitle = document.getElementById('gist-menu-title')!;
|
||||
|
||||
gistmenutitle.textContent = gistmenucopy.children[0].firstChild!.textContent;
|
||||
gistmenuinput.value = (gistmenucopy.children[0] as HTMLElement).dataset.link || '';
|
||||
|
||||
gistmenutoggle.onclick = () => {
|
||||
gistmenucopy.classList.toggle('hidden');
|
||||
};
|
||||
|
||||
for (const item of Array.from(gistmenucopy.children)) {
|
||||
(item as HTMLElement).onclick = () => {
|
||||
gistmenutitle.textContent = item.firstChild!.textContent;
|
||||
gistmenuinput.value = (item as HTMLElement).dataset.link || '';
|
||||
gistmenucopy.classList.toggle('hidden');
|
||||
};
|
||||
}
|
||||
|
||||
gistmenubuttoncopy.onclick = () => {
|
||||
const text = gistmenuinput.value;
|
||||
navigator.clipboard.writeText(text).catch((err) => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const sortgist = document.getElementById('sort-gists-button');
|
||||
if (sortgist) {
|
||||
sortgist.onclick = () => {
|
||||
document.getElementById('sort-gists-dropdown')!.classList.toggle('hidden');
|
||||
};
|
||||
}
|
||||
|
||||
document.querySelectorAll('.copy-gist-btn').forEach((e: HTMLElement) => {
|
||||
e.onclick = () => {
|
||||
navigator.clipboard.writeText(e.parentNode!.querySelector<HTMLElement>('.gist-content')!.textContent || '').catch((err) => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
};
|
||||
});
|
||||
});
|
2
templates/base/base_header.html
vendored
2
templates/base/base_header.html
vendored
|
@ -6,7 +6,7 @@
|
|||
<link rel="icon" type="image/svg+xml" href="{{ asset "favicon.svg" }}" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="stylesheet" href="{{ asset "main.css" }}" />
|
||||
<script type="module" src="{{ asset "main.js" }}"></script>
|
||||
<script type="module" src="{{ asset "main.ts" }}"></script>
|
||||
|
||||
{{ if .htmlTitle }}
|
||||
<title>{{ .htmlTitle }} - Opengist</title>
|
||||
|
|
2
templates/pages/create.html
vendored
2
templates/pages/create.html
vendored
|
@ -65,6 +65,6 @@
|
|||
</main>
|
||||
</div>
|
||||
|
||||
<script type="module" src="{{ asset "editor.js" }}"></script>
|
||||
<script type="module" src="{{ asset "editor.ts" }}"></script>
|
||||
|
||||
{{ template "footer" .}}
|
||||
|
|
2
templates/pages/edit.html
vendored
2
templates/pages/edit.html
vendored
|
@ -102,6 +102,6 @@
|
|||
</main>
|
||||
</div>
|
||||
|
||||
<script type="module" src="{{ asset "editor.js" }}"></script>
|
||||
<script type="module" src="{{ asset "editor.ts" }}"></script>
|
||||
|
||||
{{ template "footer" .}}
|
||||
|
|
9
tsconfig.json
Normal file
9
tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"files": [
|
||||
"public/main.ts",
|
||||
"public/editor.ts",
|
||||
],
|
||||
}
|
|
@ -9,7 +9,7 @@ export default defineConfig({
|
|||
assetsDir: 'assets',
|
||||
manifest: true,
|
||||
rollupOptions: {
|
||||
input: ['./public/main.js', './public/editor.js']
|
||||
input: ['./public/main.ts', './public/editor.ts']
|
||||
}
|
||||
}
|
||||
})
|
Loading…
Reference in a new issue