Skip to content

Commit ede99bc

Browse files
committed
add parseHtml
1 parent 5698721 commit ede99bc

File tree

14 files changed

+46
-51
lines changed

14 files changed

+46
-51
lines changed

app-ugc/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"app": "workspace:*",
4040
"comlink": "^4.4.1",
4141
"micromorph": "^0.4.5",
42-
"shared": "workspace:*"
42+
"shared": "workspace:*",
43+
"shared-dom": "workspace:*"
4344
}
4445
}

app-ugc/src/setBody.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import { resizeIframe } from './registerServiceWorker'
77
import diff from 'micromorph'
88
import '@iframe-resizer/child'
9+
import { parseHtml } from 'shared-dom/utility'
910

1011
self.onmessage = async (event) => {
1112
const data = event.data as unknown
@@ -21,10 +22,8 @@ self.onmessage = async (event) => {
2122
}
2223
}
2324

24-
const domParser = new DOMParser()
25-
2625
export async function setBody({ body, css }: RawRenderBodyInput) {
27-
await diff(document, domParser.parseFromString(body, 'text/html'))
26+
await diff(document, parseHtml(body))
2827
if (css != null) {
2928
const style = document.createElement('style')
3029
style.textContent = css

app/src/components/addNote.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { assertNever, objEntries, objValues } from 'shared/utility'
2222
import { CardsRemote } from './cardsRemote'
2323
import { createMutation } from '@tanstack/solid-query'
2424
import { useTableCountContext } from './tableCountContext'
25+
import { parseHtml } from 'shared-dom/utility'
2526

2627
function toView(template: Template): NoteCardView {
2728
const now = C.getDate()
@@ -95,11 +96,10 @@ export const AddNote: VoidComponent<{
9596
const noteCard = wip.noteCard!
9697
if (noteCard.cards.length === 0)
9798
C.toastFatal('There must be at least 1 card')
98-
const dp = new DOMParser()
9999
await tx(async () => {
100100
const fieldValues = await Promise.all(
101101
objEntries(noteCard.note.fieldValues).map(async ([f, v]) => {
102-
const doc = dp.parseFromString(v, 'text/html')
102+
const doc = parseHtml(v)
103103
await Promise.all(
104104
Array.from(doc.images).map(async (i) => {
105105
await mutate(i)

app/src/components/fieldEditor.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { type NoteCardView } from '../uiLogic/cards'
3131
import { toOneLine } from 'shared/htmlToText'
3232
import { type NoteId, type MediaId } from 'shared/brand'
3333
import { C } from '../topLevelAwait'
34+
import { parseHtml } from 'shared-dom/utility'
3435
// import "prosemirror-image-plugin/src/styles/sideResize.css"
3536

3637
// cf. https://gitlab.com/emergence-engineering/prosemirror-image-plugin/-/blob/master/src/updateImageNode.ts
@@ -131,7 +132,6 @@ const mySchema = makeSchema('editor')
131132
const mySchemaSerializer = makeSchema('serializer')
132133

133134
const domSerializer = DOMSerializer.fromSchema(mySchemaSerializer)
134-
const domParser = new DOMParser()
135135
const proseMirrorDOMParser = ProseMirrorDOMParser.fromSchema(mySchema)
136136

137137
export const FieldEditor: VoidComponent<{
@@ -220,7 +220,7 @@ async function updateImgSrc(img: HTMLImageElement) {
220220
}
221221

222222
async function createEditorState(value: string) {
223-
const doc = domParser.parseFromString(value, 'text/html')
223+
const doc = parseHtml(value)
224224
await Promise.all(Array.from(doc.images).map(updateImgSrc))
225225
return EditorState.create({
226226
doc: proseMirrorDOMParser.parse(doc),

app/src/components/noteSync.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { type NoteRemote, type Note } from 'shared/domain/note'
1818
import { UploadEntry } from './uploadEntry'
1919
import { uploadNotes } from '../domain/sync'
2020
import { C } from '../topLevelAwait'
21+
import { parseHtml } from 'shared-dom/utility'
2122

2223
const NoteSync: VoidComponent<{ template: Template; note: Note }> = (props) => (
2324
<>
@@ -64,8 +65,6 @@ export const NoteNookSync: VoidComponent<{
6465
)
6566
}
6667

67-
const dp = new DOMParser()
68-
6968
const NoteNookSyncActual: VoidComponent<{
7069
note: Note
7170
template: Template
@@ -84,7 +83,7 @@ const NoteNookSyncActual: VoidComponent<{
8483
}
8584
if (remoteNote != null) {
8685
for (const [field, value] of objEntries(remoteNote.fieldValues)) {
87-
const doc = dp.parseFromString(value, 'text/html')
86+
const doc = parseHtml(value)
8887
await Promise.all(
8988
Array.from(doc.images).map(async (imgEl) => {
9089
const rmId = imgEl

app/src/hubMessenger.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { type Template } from 'shared/domain/template'
1313
import { type Note } from 'shared/domain/note'
1414
import { type Card } from 'shared/domain/card'
1515
import { objEntries } from 'shared/utility'
16+
import { parseHtml } from 'shared-dom/utility'
1617

1718
export const appExpose = {
1819
ping: () => {},
@@ -32,11 +33,10 @@ export const appExpose = {
3233
[rt.nook]: { remoteTemplateId: rt.id, uploadDate: now },
3334
},
3435
} satisfies Template
35-
const dp = new DOMParser()
3636
if (template.templateType.tag === 'standard') {
3737
await Promise.all(
3838
template.templateType.templates.map(async (t) => {
39-
const { imgSrcs, front, back } = getTemplateImages(t, dp)
39+
const { imgSrcs, front, back } = getTemplateImages(t)
4040
t.front = serializer.serializeToString(front)
4141
t.back = serializer.serializeToString(back)
4242
return await downloadImages(imgSrcs)
@@ -45,7 +45,6 @@ export const appExpose = {
4545
} else {
4646
const { imgSrcs, front, back } = getTemplateImages(
4747
template.templateType.template,
48-
dp,
4948
)
5049
await downloadImages(imgSrcs)
5150
template.templateType.template.front =
@@ -73,7 +72,7 @@ export const appExpose = {
7372
[nook, { remoteNoteId: rn.id, uploadDate: now }],
7473
]),
7574
} satisfies Note
76-
await downloadImages(getNoteImages(n.fieldValues, new DOMParser()))
75+
await downloadImages(getNoteImages(n.fieldValues))
7776
await C.db.upsertNote(n)
7877
const ords = noteOrds.bind(C)(n, template)
7978
const cards = ords.map((i) => {
@@ -100,10 +99,10 @@ export const appExpose = {
10099
// highTODO needs security on the origin
101100
Comlink.expose(appExpose, Comlink.windowEndpoint(self.parent))
102101

103-
function getNoteImages(fieldValues: Record<string, string>, dp: DOMParser) {
102+
function getNoteImages(fieldValues: Record<string, string>) {
104103
const imgSrcs = new Map<MediaId, string>()
105104
for (const [f, v] of objEntries(fieldValues)) {
106-
const doc = dp.parseFromString(v, 'text/html')
105+
const doc = parseHtml(v)
107106
Array.from(doc.images).forEach((i) => {
108107
mutate(i, imgSrcs)
109108
})
@@ -128,10 +127,10 @@ function mutate(img: HTMLImageElement, imgSrcs: Map<MediaId, string>) {
128127
}
129128
}
130129

131-
function getTemplateImages(ct: ChildTemplate, dp: DOMParser) {
130+
function getTemplateImages(ct: ChildTemplate) {
132131
const imgSrcs = new Map<MediaId, string>()
133-
const front = dp.parseFromString(ct.front, 'text/html')
134-
const back = dp.parseFromString(ct.back, 'text/html')
132+
const front = parseHtml(ct.front)
133+
const back = parseHtml(ct.back)
135134
Array.from(front.images).forEach((i) => {
136135
mutate(i, imgSrcs)
137136
})

app/src/sqlite/crsqlite.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,11 @@ import { SQLITE_DETERMINISTIC, SQLITE_UTF8 } from '@vlcn.io/wa-sqlite'
1212
import initSql from 'shared/sql.json'
1313
import { ftsNormalize } from 'shared/htmlToText'
1414

15-
// const dp = new DOMParser()
16-
1715
function getMediaIds(fvs: string) {
1816
// highTODO uncomment and fix by adding the mediaId table back
1917
// const values = parseMap<string, string>(fvs).values()
2018
// return Array.from(values)
21-
// .flatMap((v) => dp.parseFromString(v, 'text/html'))
19+
// .flatMap((v) => parseHtml(v))
2220
// .flatMap((d) => Array.from(d.images))
2321
// .map((i) => i.getAttribute('src'))
2422
// .join(unitSeparator)

app/src/sqlite/note.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,6 @@ JOIN noteFieldValue ON noteFieldValue.noteId = x.noteId AND noteFieldValue.field
260260
)
261261
},
262262
getNewNotesToUpload: async function (noteId?: NoteId, nook?: NookId) {
263-
const dp = new DOMParser()
264263
const remoteTemplates = await ky
265264
.selectFrom('remoteTemplate')
266265
.selectAll()
@@ -285,7 +284,7 @@ JOIN noteFieldValue ON noteFieldValue.noteId = x.noteId AND noteFieldValue.field
285284
.filter(notEmpty)
286285
return domainToCreateRemote(note, remoteIds)
287286
})
288-
.map(async (n) => await remotifyNote(dp, n).then((x) => x.note)),
287+
.map(async (n) => await remotifyNote(n).then((x) => x.note)),
289288
)
290289
},
291290
getNewNotesToUploadDom: async function (noteId?: NoteId) {
@@ -318,7 +317,6 @@ JOIN noteFieldValue ON noteFieldValue.noteId = x.noteId AND noteFieldValue.field
318317
)
319318
},
320319
getEditedNotesToUpload: async function (noteId?: NoteId, nook?: NookId) {
321-
const dp = new DOMParser()
322320
const remoteTemplates = await ky
323321
.selectFrom('remoteTemplate')
324322
.selectAll()
@@ -360,7 +358,7 @@ JOIN noteFieldValue ON noteFieldValue.noteId = x.noteId AND noteFieldValue.field
360358
)
361359
return domainToEditRemote(note, remotes)
362360
})
363-
.map(async (n) => await remotifyNote(dp, n).then((x) => x.note)),
361+
.map(async (n) => await remotifyNote(n).then((x) => x.note)),
364362
)
365363
},
366364
getEditedNotesToUploadDom: async function (noteId?: NoteId) {
@@ -402,7 +400,6 @@ JOIN noteFieldValue ON noteFieldValue.noteId = x.noteId AND noteFieldValue.field
402400
> & { note: Note },
403401
) {
404402
const { hashByLocal } = await remotifyNote(
405-
new DOMParser(),
406403
domainToCreateRemote(remoteNote.note, [
407404
/* this doesn't need any real values */
408405
]),
@@ -479,14 +476,10 @@ JOIN noteFieldValue ON noteFieldValue.noteId = x.noteId AND noteFieldValue.field
479476
}
480477

481478
async function remotifyNote<T extends CreateRemoteNote | EditRemoteNote>(
482-
dp: DOMParser,
483479
note: T,
484480
) {
485481
const fieldValues: Record<string, string> = {} satisfies T['fieldValues']
486-
const { docs, hashByLocal } = await remotifyDoms(
487-
dp,
488-
objValues(note.fieldValues),
489-
)
482+
const { docs, hashByLocal } = await remotifyDoms(objValues(note.fieldValues))
490483
let i = 0
491484
for (const field of objKeys(note.fieldValues)) {
492485
fieldValues[field] = docs[i]!.body.innerHTML

app/src/sqlite/template.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,11 @@ export const templateCollectionMethods = {
219219
templateId?: TemplateId,
220220
nook?: NookId,
221221
) {
222-
const dp = new DOMParser()
223222
const templatesAndStuff = await this.getNewTemplatesToUploadDom(templateId)
224223
return await Promise.all(
225224
templatesAndStuff
226225
.map((n) => domainToCreateRemote(n, nook))
227-
.map(
228-
async (n) => await remotifyTemplate(dp, n).then((x) => x.template),
229-
),
226+
.map(async (n) => await remotifyTemplate(n).then((x) => x.template)),
230227
)
231228
},
232229
getNewTemplatesToUploadDom: async function (templateId?: TemplateId) {
@@ -246,15 +243,12 @@ export const templateCollectionMethods = {
246243
templateId?: TemplateId,
247244
nook?: NookId,
248245
) {
249-
const dp = new DOMParser()
250246
const templatesAndStuff =
251247
await this.getEditedTemplatesToUploadDom(templateId)
252248
return await Promise.all(
253249
templatesAndStuff
254250
.map((n) => domainToEditRemote(n, nook))
255-
.map(
256-
async (n) => await remotifyTemplate(dp, n).then((x) => x.template),
257-
),
251+
.map(async (n) => await remotifyTemplate(n).then((x) => x.template)),
258252
)
259253
},
260254
getEditedTemplatesToUploadDom: async function (templateId?: TemplateId) {
@@ -293,7 +287,6 @@ export const templateCollectionMethods = {
293287
.where('id', '=', templateDbId)
294288
.executeTakeFirstOrThrow()
295289
const { hashByLocal } = await remotifyTemplate(
296-
new DOMParser(),
297290
domainToCreateRemote(toTemplate([{ ...template, ...remoteTemplate }])!),
298291
)
299292
const srcs = new Set(hashByLocal.keys())
@@ -392,7 +385,7 @@ function toTemplate(allTemplates: TemplateRow[]) {
392385

393386
async function remotifyTemplate<
394387
T extends CreateRemoteTemplate | EditRemoteTemplate,
395-
>(dp: DOMParser, template: T) {
388+
>(template: T) {
396389
const serializer = new XMLSerializer()
397390
const serialize = (doc: Document) => {
398391
const s = serializer.serializeToString(doc)
@@ -407,7 +400,7 @@ async function remotifyTemplate<
407400
t.front,
408401
t.back,
409402
])
410-
const { docs, hashByLocal } = await remotifyDoms(dp, rawDoms)
403+
const { docs, hashByLocal } = await remotifyDoms(rawDoms)
411404
let i = 0
412405
for (const t of template.templateType.templates) {
413406
t.front = serialize(docs[i]!)
@@ -420,7 +413,7 @@ async function remotifyTemplate<
420413
hashByLocal,
421414
}
422415
} else {
423-
const { docs, hashByLocal } = await remotifyDoms(dp, [
416+
const { docs, hashByLocal } = await remotifyDoms([
424417
template.templateType.template.front,
425418
template.templateType.template.back,
426419
])

app/src/sqlite/util.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ import { jsonArrayFrom } from 'kysely/helpers/sqlite'
3535
import { sql, type AliasedRawBuilder, type ExpressionBuilder } from 'kysely'
3636
import { arrayToBase64, base64ToArray } from 'shared/binary'
3737
import { nullNook } from 'shared-edge'
38+
import { parseHtml } from 'shared-dom/utility'
3839

3940
export function parseTags(rawTags: string) {
4041
return parseSet<string>(rawTags)
4142
}
4243

43-
export async function remotifyDoms(dp: DOMParser, rawDoms: string[]) {
44-
const docs = rawDoms.map((rawDom) => dp.parseFromString(rawDom, 'text/html'))
44+
export async function remotifyDoms(rawDoms: string[]) {
45+
const docs = rawDoms.map(parseHtml)
4546
const imgSrcs = new Set(
4647
docs
4748
.flatMap((pd) => Array.from(pd.images))

hub-ugc/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"comlink": "^4.4.1",
4040
"hub": "workspace:*",
4141
"micromorph": "^0.4.5",
42-
"shared": "workspace:*"
42+
"shared": "workspace:*",
43+
"shared-dom": "workspace:*"
4344
}
4445
}

hub-ugc/src/setBody.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
import { resizeIframe } from './registerServiceWorker'
77
import diff from 'micromorph'
88
import '@iframe-resizer/child'
9+
import { parseHtml } from 'shared-dom/utility'
910

1011
self.onmessage = async (event) => {
1112
const data = event.data as unknown
@@ -21,10 +22,8 @@ self.onmessage = async (event) => {
2122
}
2223
}
2324

24-
const domParser = new DOMParser()
25-
2625
export async function setBody({ body, css }: RawRenderBodyInput) {
27-
await diff(document, domParser.parseFromString(body, 'text/html'))
26+
await diff(document, parseHtml(body))
2827
if (css != null) {
2928
const style = document.createElement('style')
3029
style.textContent = css

pnpm-lock.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shared-dom/src/utility.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@ export function disposeObserver(ro: ResizeObserver | undefined, ref: Element) {
77
ro.disconnect()
88
}
99
}
10+
11+
let domParser: DOMParser
12+
export function parseHtml(html: string) {
13+
if (domParser == null) domParser = new DOMParser()
14+
return domParser.parseFromString(html, 'text/html')
15+
}

0 commit comments

Comments
 (0)