Compare commits
No commits in common. "b59c6c8b58dd509c08777090561ff14c4e56e0db" and "8b421ea59ea4616f85d407c0c8ccbf011fcc739a" have entirely different histories.
b59c6c8b58
...
8b421ea59e
3 changed files with 19 additions and 106 deletions
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
|
|
@ -23,10 +22,6 @@ type Engine struct {
|
||||||
DevMode bool
|
DevMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
templateLock sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewEngine(viewFS, staticFS fs.FS, devmode bool) (e Engine, err error) { // {{{
|
func NewEngine(viewFS, staticFS fs.FS, devmode bool) (e Engine, err error) { // {{{
|
||||||
e.parsedTemplates = make(map[string]*template.Template)
|
e.parsedTemplates = make(map[string]*template.Template)
|
||||||
e.viewFS = viewFS
|
e.viewFS = viewFS
|
||||||
|
|
@ -67,9 +62,7 @@ func (e *Engine) getComponentFilenames() (files []string, err error) { // {{{
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func (e *Engine) ReloadTemplates() { // {{{
|
func (e *Engine) ReloadTemplates() { // {{{
|
||||||
templateLock.Lock()
|
|
||||||
e.parsedTemplates = make(map[string]*template.Template)
|
e.parsedTemplates = make(map[string]*template.Template)
|
||||||
templateLock.Unlock()
|
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func (e *Engine) StaticResource(w http.ResponseWriter, r *http.Request) { // {{{
|
func (e *Engine) StaticResource(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
|
|
@ -126,9 +119,7 @@ func (e *Engine) getPage(layout, page string) (tmpl *template.Template, err erro
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
templateLock.Lock()
|
|
||||||
e.parsedTemplates[page] = tmpl
|
e.parsedTemplates[page] = tmpl
|
||||||
templateLock.Unlock()
|
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func (e *Engine) Render(p Page, w http.ResponseWriter, r *http.Request) (err error) { // {{{
|
func (e *Engine) Render(p Page, w http.ResponseWriter, r *http.Request) (err error) { // {{{
|
||||||
|
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
width="7.1437349mm"
|
|
||||||
height="6.3499999mm"
|
|
||||||
viewBox="0 0 7.1437349 6.3499999"
|
|
||||||
version="1.1"
|
|
||||||
id="svg1"
|
|
||||||
inkscape:version="1.4.2 (ebf0e94, 2025-05-08)"
|
|
||||||
sodipodi:docname="icon_table.svg"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview1"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#000000"
|
|
||||||
borderopacity="0.25"
|
|
||||||
inkscape:showpageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
inkscape:deskcolor="#d1d1d1"
|
|
||||||
inkscape:document-units="mm"
|
|
||||||
inkscape:zoom="0.81067621"
|
|
||||||
inkscape:cx="69.078134"
|
|
||||||
inkscape:cy="155.4258"
|
|
||||||
inkscape:window-width="1916"
|
|
||||||
inkscape:window-height="1161"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="0"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="layer1" />
|
|
||||||
<defs
|
|
||||||
id="defs1" />
|
|
||||||
<g
|
|
||||||
inkscape:label="Layer 1"
|
|
||||||
inkscape:groupmode="layer"
|
|
||||||
id="layer1"
|
|
||||||
transform="translate(-86.666022,-107.47612)">
|
|
||||||
<title
|
|
||||||
id="title1">table</title>
|
|
||||||
<path
|
|
||||||
d="m 87.459775,107.47612 h 5.556243 a 0.79374826,0.79374826 0 0 1 0.793739,0.79375 v 4.7625 a 0.79374826,0.79374826 0 0 1 -0.793739,0.79375 h -5.556243 a 0.79374826,0.79374826 0 0 1 -0.793753,-0.79375 v -4.7625 a 0.79374826,0.79374826 0 0 1 0.793753,-0.79375 m 0,1.5875 v 1.58749 h 2.381245 v -1.58749 h -2.381245 m 3.174998,0 v 1.58749 h 2.381245 v -1.58749 h -2.381245 m -3.174998,2.38125 v 1.5875 h 2.381245 v -1.5875 h -2.381245 m 3.174998,0 v 1.5875 h 2.381245 v -1.5875 z"
|
|
||||||
id="path1"
|
|
||||||
style="stroke-width:0.396873" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB |
|
|
@ -1,4 +1,4 @@
|
||||||
import { ROOT_NODE, uuidv7 } from 'node_store'
|
import { ROOT_NODE, uuidv7, StoreFile } from 'node_store'
|
||||||
import { CustomHTMLElement } from './lib/custom_html_element.mjs'
|
import { CustomHTMLElement } from './lib/custom_html_element.mjs'
|
||||||
import { MarkedPosition } from './marked_position.mjs'
|
import { MarkedPosition } from './marked_position.mjs'
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ export class N2PageNodeUI extends CustomHTMLElement {
|
||||||
<style>
|
<style>
|
||||||
.el-functions {
|
.el-functions {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr min-content min-content;
|
grid-template-columns: 1fr min-content;
|
||||||
grid-gap: 8px;
|
grid-gap: 8px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-items: end;
|
justify-items: end;
|
||||||
|
|
@ -27,7 +27,6 @@ export class N2PageNodeUI extends CustomHTMLElement {
|
||||||
<div data-el="functions">
|
<div data-el="functions">
|
||||||
<img data-el="icon-markdown">
|
<img data-el="icon-markdown">
|
||||||
<img data-el="icon-save" src="/images/${_VERSION}/icon_save_disabled.svg">
|
<img data-el="icon-save" src="/images/${_VERSION}/icon_save_disabled.svg">
|
||||||
<img data-el="icon-table-format" src="/images/${_VERSION}/icon_table.svg">
|
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
}// }}}
|
}// }}}
|
||||||
|
|
@ -75,14 +74,6 @@ export class N2PageNodeUI extends CustomHTMLElement {
|
||||||
this.elNodeContent.addEventListener('input', event => this.contentChanged(event))
|
this.elNodeContent.addEventListener('input', event => this.contentChanged(event))
|
||||||
this.elNodeContent.addEventListener('paste', async (event) => this.pasteHandler(event))
|
this.elNodeContent.addEventListener('paste', async (event) => this.pasteHandler(event))
|
||||||
this.elIconMarkdown.addEventListener('click', () => this.showMarkdown(!this.showMarkdown()))
|
this.elIconMarkdown.addEventListener('click', () => this.showMarkdown(!this.showMarkdown()))
|
||||||
this.elIconTableFormat.addEventListener('click', () => {
|
|
||||||
const from = this.elNodeContent.selectionStart
|
|
||||||
const to = this.elNodeContent.selectionEnd
|
|
||||||
const sel = this.elNodeContent.value.slice(from, to)
|
|
||||||
|
|
||||||
this.formatTable(sel)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
this.showMarkdown(true)
|
this.showMarkdown(true)
|
||||||
}// }}}
|
}// }}}
|
||||||
|
|
@ -128,7 +119,7 @@ export class N2PageNodeUI extends CustomHTMLElement {
|
||||||
return this.classList.contains('show-markdown')
|
return this.classList.contains('show-markdown')
|
||||||
}
|
}
|
||||||
}// }}}
|
}// }}}
|
||||||
async pasteHandler(event) {// {{{
|
async pasteHandler(event) {
|
||||||
const clipboardItems = event.clipboardData?.items
|
const clipboardItems = event.clipboardData?.items
|
||||||
if (!clipboardItems)
|
if (!clipboardItems)
|
||||||
return
|
return
|
||||||
|
|
@ -143,58 +134,38 @@ export class N2PageNodeUI extends CustomHTMLElement {
|
||||||
if (!file)
|
if (!file)
|
||||||
throw new Error("Couldn't convert image to file object.")
|
throw new Error("Couldn't convert image to file object.")
|
||||||
const uuid = uuidv7()
|
const uuid = uuidv7()
|
||||||
await globalThis.nodeStore.files.add({ data: { UUID: uuid, file: file } })
|
await globalThis.nodeStore.files.add({ data: { UUID: uuid, file: file }})
|
||||||
|
|
||||||
const [start, end] = [this.elNodeContent.selectionStart, this.elNodeContent.selectionEnd]
|
const [start, end] = [this.elNodeContent.selectionStart, this.elNodeContent.selectionEnd]
|
||||||
this.elNodeContent.setRangeText(``, start, end, 'select');
|
this.elNodeContent.setRangeText(``, start, end, 'select');
|
||||||
|
|
||||||
// Editing the textarea programatically doesn't generate the events it usually gets when edited interactively.
|
|
||||||
this.node.setContent(this.elNodeContent.value)
|
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
alert(`Unknown paste type of '${item.kind}'`)
|
alert(`Unknown paste type of '${item.kind}'`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}// }}}
|
}
|
||||||
|
|
||||||
|
// Example usage: Displaying the image or preparing it for upload
|
||||||
|
handleImageBlob(blob) {
|
||||||
|
// 1. Create a local URL to preview it in an <img> tag if needed
|
||||||
|
const localUrl = URL.createObjectURL(blob)
|
||||||
|
console.log('Local preview URL:', localUrl)
|
||||||
|
|
||||||
|
// 2. Or prepare it for a FormData upload
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('image', blob, 'pasted-image.png')
|
||||||
|
|
||||||
|
// fetch('/upload', { method: 'POST', body: formData })
|
||||||
|
}
|
||||||
|
|
||||||
editMarkdown(data) {// {{{
|
editMarkdown(data) {// {{{
|
||||||
this.showMarkdown(false)
|
this.showMarkdown(false)
|
||||||
this.elNodeContent.selectionStart = data.position.start
|
this.elNodeContent.selectionStart = data.position.start
|
||||||
this.elNodeContent.selectionEnd = data.position.end
|
this.elNodeContent.selectionEnd = data.position.end
|
||||||
this.elNodeContent.focus()
|
this.elNodeContent.focus()
|
||||||
}// }}}
|
}// }}}
|
||||||
formatTable(t) {
|
|
||||||
const lines = t.split(/\r?\n/)
|
|
||||||
if (lines < 1)
|
|
||||||
return
|
|
||||||
|
|
||||||
let first = -1
|
|
||||||
let last = -1
|
|
||||||
let numColumns = 0
|
|
||||||
let colwidth = []
|
|
||||||
|
|
||||||
for (let i = 0; i < lines.length; i++) {
|
|
||||||
// -1 for split, -1 because number of columns are one less than number of pipes.
|
|
||||||
const columns = lines[i].split('|')
|
|
||||||
const linecols = columns.length - 1 - 1
|
|
||||||
numColumns = Math.max(numColumns, linecols)
|
|
||||||
|
|
||||||
if (linecols >= 1) {
|
|
||||||
if (first == -1)
|
|
||||||
first = i
|
|
||||||
last = i
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (linecols < 1 && last > -1)
|
|
||||||
break
|
|
||||||
|
|
||||||
// Keep count of column width
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(first, last, columns)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
customElements.define('n2-nodeui', N2PageNodeUI)
|
customElements.define('n2-nodeui', N2PageNodeUI)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue