chore(commons): prettier

enforce trailing commas as this is the norm in the frontend and makes diffs better readable

Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
Philip Molares 2025-03-21 21:13:30 +01:00
parent 59744b65ea
commit aa87ff35b3
32 changed files with 171 additions and 171 deletions

View file

@ -4,7 +4,7 @@
"jsxSingleQuote": true,
"semi": false,
"tabWidth": 2,
"trailingComma": "none",
"trailingComma": "all",
"bracketSpacing": true,
"bracketSameLine": true,
"arrowParens": "always"

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -34,7 +34,7 @@ describe('frontmatter extraction', () => {
'this is not frontmatter',
'because',
'there is no',
'end marker'
'end marker',
]
const extraction = extractFrontmatter(testNote)
expect(extraction).toBeUndefined()

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -20,7 +20,7 @@ const FRONTMATTER_INCOMPLETE_END_REGEX = /^-{1,2}$/
* given multiline string for retrieving the non-frontmatter content.
*/
export const extractFrontmatter = (
lines: string[]
lines: string[],
): FrontmatterExtractionResult | undefined => {
if (lines.length < 2 || !FRONTMATTER_BEGIN_REGEX.test(lines[0])) {
return undefined
@ -30,7 +30,7 @@ export const extractFrontmatter = (
return {
rawText: '',
lineOffset: i + 1,
incomplete: true
incomplete: true,
}
}
if (
@ -40,7 +40,7 @@ export const extractFrontmatter = (
return {
rawText: lines.slice(1, i).join('\n'),
lineOffset: i + 1,
incomplete: false
incomplete: false,
}
}
}

View file

@ -1,9 +1,9 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
export enum DisconnectReason {
USER_NOT_PERMITTED = 4000
USER_NOT_PERMITTED = 4000,
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -7,7 +7,7 @@ import {
ConnectionStateEvent,
Message,
MessagePayloads,
MessageType
MessageType,
} from './message.js'
import { TransportAdapter } from './transport-adapter.js'
import { EventEmitter2, Listener } from 'eventemitter2'
@ -26,7 +26,7 @@ type MessageEventPayloadMap = {
export enum ConnectionState {
DISCONNECTED = 'DISCONNECTED',
CONNECTING = 'CONNECTING',
CONNECTED = 'CONNECTED'
CONNECTED = 'CONNECTED',
}
/**
@ -53,7 +53,7 @@ export class MessageTransporter extends EventEmitter2<MessageEventPayloadMap> {
if (this.transportAdapter === undefined) {
console.debug(
"Can't send message without transport adapter. Message that couldn't be sent was",
content
content,
)
return
}
@ -62,7 +62,7 @@ export class MessageTransporter extends EventEmitter2<MessageEventPayloadMap> {
this.onDisconnecting()
console.debug(
"Can't send message over closed connection. Triggering onDisconencted event. Message that couldn't be sent was",
content
content,
)
return
}
@ -105,7 +105,7 @@ export class MessageTransporter extends EventEmitter2<MessageEventPayloadMap> {
this.onConnected()
} else {
this.destroyOnConnectedEventHandler = websocket.bindOnConnectedEvent(
this.onConnected.bind(this)
this.onConnected.bind(this),
)
}
}
@ -167,13 +167,13 @@ export class MessageTransporter extends EventEmitter2<MessageEventPayloadMap> {
private bindWebsocketEvents(transportAdapter: TransportAdapter) {
this.destroyOnErrorEventHandler = transportAdapter.bindOnErrorEvent(
this.onDisconnecting.bind(this)
this.onDisconnecting.bind(this),
)
this.destroyOnCloseEventHandler = transportAdapter.bindOnCloseEvent(
this.onDisconnecting.bind(this)
this.onDisconnecting.bind(this),
)
this.destroyOnMessageEventHandler = transportAdapter.bindOnMessageEvent(
this.receiveMessage.bind(this)
this.receiveMessage.bind(this),
)
}
@ -221,7 +221,7 @@ export class MessageTransporter extends EventEmitter2<MessageEventPayloadMap> {
callback()
}
return this.on('ready', callback, {
objectify: true
objectify: true,
}) as Listener
}
@ -237,7 +237,7 @@ export class MessageTransporter extends EventEmitter2<MessageEventPayloadMap> {
callback()
}
return this.on('connected', callback, {
objectify: true
objectify: true,
}) as Listener
}
@ -253,11 +253,11 @@ export class MessageTransporter extends EventEmitter2<MessageEventPayloadMap> {
protected startSendingOfReadyRequests(): void {
this.readyInterval = setInterval(() => {
this.sendMessage({
type: MessageType.READY_REQUEST
type: MessageType.READY_REQUEST,
})
}, 400)
this.sendMessage({
type: MessageType.READY_REQUEST
type: MessageType.READY_REQUEST,
})
}
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -19,13 +19,13 @@ export enum MessageType {
REALTIME_USER_SET_ACTIVITY = 'REALTIME_USER_SET_ACTIVITY',
READY_REQUEST = 'READY_REQUEST',
READY_ANSWER = 'READY_ANSWER'
READY_ANSWER = 'READY_ANSWER',
}
export enum ConnectionStateEvent {
READY = 'ready',
CONNECTED = 'connected',
DISCONNECTED = 'disconnected'
DISCONNECTED = 'disconnected',
}
export interface MessagePayloads {

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -46,7 +46,7 @@ export class MockedBackendTransportAdapter implements TransportAdapter {
}
bindOnMessageEvent(
handler: (value: Message<MessageType>) => void
handler: (value: Message<MessageType>) => void,
): () => void {
this.messageHandler = handler
return () => {
@ -74,17 +74,17 @@ export class MockedBackendTransportAdapter implements TransportAdapter {
() =>
this.messageHandler?.({
type: MessageType.NOTE_CONTENT_UPDATE,
payload: this.doc.encodeStateAsUpdate(value.payload)
payload: this.doc.encodeStateAsUpdate(value.payload),
}),
0
0,
)
} else if (value.type === MessageType.READY_REQUEST) {
setTimeout(
() =>
this.messageHandler?.({
type: MessageType.READY_ANSWER
type: MessageType.READY_ANSWER,
}),
0
0,
)
}
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -7,7 +7,7 @@ import {
NoteFrontmatter,
NoteTextDirection,
NoteType,
OpenGraph
OpenGraph,
} from '../note-frontmatter/frontmatter.js'
import { SlideOptions } from '../note-frontmatter/slide-show-options.js'
import { convertRawFrontmatterToNoteFrontmatter } from './convert-raw-frontmatter-to-note-frontmatter.js'
@ -31,8 +31,8 @@ describe('convertRawFrontmatterToNoteFrontmatter', () => {
breaks: breaks,
opengraph: opengraph,
slideOptions: slideOptions,
tags: 'tags'
})
tags: 'tags',
}),
).toStrictEqual({
title: 'title',
description: 'description',
@ -44,8 +44,8 @@ describe('convertRawFrontmatterToNoteFrontmatter', () => {
opengraph: opengraph,
slideOptions: slideOptions,
license: 'license',
tags: ['tags']
tags: ['tags'],
} as NoteFrontmatter)
}
},
)
})

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -12,7 +12,7 @@ import { RawNoteFrontmatter } from './types.js'
* @param rawData A {@link RawNoteFrontmatter} object containing the properties of the parsed yaml frontmatter.
*/
export const convertRawFrontmatterToNoteFrontmatter = (
rawData: RawNoteFrontmatter
rawData: RawNoteFrontmatter,
): NoteFrontmatter => {
return {
title: rawData.title,
@ -25,6 +25,6 @@ export const convertRawFrontmatterToNoteFrontmatter = (
opengraph: rawData.opengraph,
slideOptions: rawData.slideOptions,
license: rawData.license,
tags: parseTags(rawData.tags)
tags: parseTags(rawData.tags),
}
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -32,7 +32,7 @@ describe('yaml frontmatter', () => {
it('should parse the tag inline-list syntax', () => {
const noteFrontmatter = parseRawFrontmatterFromYaml(
"tags: ['test123', 'abc']"
"tags: ['test123', 'abc']",
)
expect(noteFrontmatter.value?.tags).toEqual(['test123', 'abc'])
})
@ -57,7 +57,7 @@ describe('yaml frontmatter', () => {
`)
expect(noteFrontmatter.value?.opengraph.title).toEqual('Testtitle')
expect(noteFrontmatter.value?.opengraph.image).toEqual(
'https://dummyimage.com/48.png'
'https://dummyimage.com/48.png',
)
expect(noteFrontmatter.value?.opengraph['image:type']).toEqual('image/png')
})

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -7,7 +7,7 @@ import { defaultNoteFrontmatter } from '../note-frontmatter/index.js'
import {
NoteTextDirection,
NoteType,
OpenGraph
OpenGraph,
} from '../note-frontmatter/index.js'
import { SlideOptions } from '../note-frontmatter/index.js'
import { ISO6391 } from '../note-frontmatter/iso6391.js'
@ -24,7 +24,7 @@ const schema = Joi.object<RawNoteFrontmatter>({
tags: Joi.alternatives(
Joi.array().items(Joi.string()),
Joi.string(),
Joi.number().cast('string')
Joi.number().cast('string'),
)
.optional()
.default(defaultNoteFrontmatter.tags),
@ -51,17 +51,17 @@ const schema = Joi.object<RawNoteFrontmatter>({
transition: Joi.string().optional(),
backgroundTransition: Joi.string().optional(),
autoSlideStoppable: Joi.boolean().optional(),
slideNumber: Joi.boolean().optional()
slideNumber: Joi.boolean().optional(),
})
.optional()
.default(defaultNoteFrontmatter.slideOptions),
opengraph: Joi.object<OpenGraph>({
title: Joi.string().optional(),
image: Joi.string().uri().optional()
image: Joi.string().uri().optional(),
})
.unknown(true)
.optional()
.default(defaultNoteFrontmatter.opengraph)
.default(defaultNoteFrontmatter.opengraph),
})
.default(defaultNoteFrontmatter)
.unknown(true)

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -14,7 +14,7 @@ describe('parse tags', () => {
'c',
'd',
'e',
'f'
'f',
])
})
@ -25,7 +25,7 @@ describe('parse tags', () => {
'c',
'd',
'e',
'f'
'f',
])
})
})

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -7,7 +7,7 @@ import {
Iso6391Language,
NoteTextDirection,
NoteType,
OpenGraph
OpenGraph,
} from '../note-frontmatter/index.js'
import { SlideOptions } from '../note-frontmatter/index.js'

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -11,7 +11,7 @@ export const defaultSlideOptions: SlideOptions = {
autoSlide: 0,
autoSlideStoppable: true,
backgroundTransition: 'fade',
slideNumber: false
slideNumber: false,
}
export const defaultNoteFrontmatter: NoteFrontmatter = {
@ -25,5 +25,5 @@ export const defaultNoteFrontmatter: NoteFrontmatter = {
license: '',
type: NoteType.DOCUMENT,
opengraph: {},
slideOptions: defaultSlideOptions
slideOptions: defaultSlideOptions,
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -12,12 +12,12 @@ export type OpenGraph = Record<string, string>
export enum NoteTextDirection {
LTR = 'ltr',
RTL = 'rtl'
RTL = 'rtl',
}
export enum NoteType {
DOCUMENT = 'document',
SLIDE = 'slide'
SLIDE = 'slide',
}
export interface NoteFrontmatter {
title: string

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -187,5 +187,5 @@ export const ISO6391 = [
'yo',
'za',
'zh',
'zu'
'zu',
] as const

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -15,12 +15,12 @@ describe('validate url', () => {
describe('protocols', () => {
it('works with http', () => {
expect(parseUrl('http://example.org').get().toString()).toEqual(
'http://example.org/'
'http://example.org/',
)
})
it('works with https', () => {
expect(parseUrl('https://example.org').get().toString()).toEqual(
'https://example.org/'
'https://example.org/',
)
})
it("doesn't work without protocol", () => {
@ -28,7 +28,7 @@ describe('validate url', () => {
})
it("doesn't work any other protocol", () => {
expect(() => parseUrl('git://example.org').get()).toThrowError(
WrongProtocolError
WrongProtocolError,
)
})
})
@ -36,22 +36,22 @@ describe('validate url', () => {
describe('trailing slash', () => {
it('accepts urls with just domain with trailing slash', () => {
expect(parseUrl('http://example.org/').get().toString()).toEqual(
'http://example.org/'
'http://example.org/',
)
})
it('accepts urls with just domain without trailing slash', () => {
expect(parseUrl('http://example.org').get().toString()).toEqual(
'http://example.org/'
'http://example.org/',
)
})
it('declines urls with with subpath and trailing slash', () => {
expect(() =>
parseUrl('http://example.org/asd/').get().toString()
parseUrl('http://example.org/asd/').get().toString(),
).toThrow(NoSubdirectoryAllowedError)
})
it('declines urls with with subpath and without trailing slash', () => {
expect(() => parseUrl('http://example.org/asd').get().toString()).toThrow(
NoSubdirectoryAllowedError
NoSubdirectoryAllowedError,
)
})
})

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -18,11 +18,11 @@ export function parseUrl(url: string | undefined): Optional<URL> {
return createOptionalUrl(url)
.guard(
(value) => value.protocol === 'https:' || value.protocol === 'http:',
() => new WrongProtocolError()
() => new WrongProtocolError(),
)
.guard(
(value) => value.pathname === '/',
() => new NoSubdirectoryAllowedError()
() => new NoSubdirectoryAllowedError(),
)
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -13,19 +13,19 @@ describe('Permissions', () => {
sharedToUsers: [
{
username: 'logged_in',
canEdit: true
}
canEdit: true,
},
],
sharedToGroups: [
{
groupName: SpecialGroup.EVERYONE,
canEdit: true
canEdit: true,
},
{
groupName: SpecialGroup.LOGGED_IN,
canEdit: true
}
]
canEdit: true,
},
],
}
describe('userIsOwner', () => {
it('returns true, if user is owner', () => {
@ -45,25 +45,25 @@ describe('Permissions', () => {
})
it('returns true, if user is logged in and this is user specifically may edit', () => {
expect(
userCanEdit({ ...testPermissions, sharedToGroups: [] }, 'logged_in')
userCanEdit({ ...testPermissions, sharedToGroups: [] }, 'logged_in'),
).toBeTruthy()
})
it('returns true, if user is logged in and loggedIn users may edit', () => {
expect(
userCanEdit({ ...testPermissions, sharedToUsers: [] }, 'logged_in')
userCanEdit({ ...testPermissions, sharedToUsers: [] }, 'logged_in'),
).toBeTruthy()
})
it('returns true, if user is guest and guests are allowed to edit', () => {
expect(
userCanEdit({ ...testPermissions, sharedToUsers: [] }, undefined)
userCanEdit({ ...testPermissions, sharedToUsers: [] }, undefined),
).toBeTruthy()
})
it('returns false, if user is logged in and loggedIn users may not edit', () => {
expect(
userCanEdit(
{ ...testPermissions, sharedToUsers: [], sharedToGroups: [] },
'logged_in'
)
'logged_in',
),
).toBeFalsy()
})
it('returns false, if user is guest and guests are not allowed to edit', () => {
@ -75,12 +75,12 @@ describe('Permissions', () => {
sharedToGroups: [
{
groupName: SpecialGroup.LOGGED_IN,
canEdit: true
}
]
canEdit: true,
},
],
},
undefined
)
undefined,
),
).toBeFalsy()
})
})

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -14,7 +14,7 @@ import { NotePermissions, SpecialGroup } from './permissions.types.js'
*/
export const userIsOwner = (
permissions: NotePermissions,
user?: string
user?: string,
): boolean => {
return !!user && permissions.owner === user
}
@ -28,21 +28,21 @@ export const userIsOwner = (
*/
export const userCanEdit = (
permissions: NotePermissions,
user?: string
user?: string,
): boolean => {
const isOwner = userIsOwner(permissions, user)
const mayWriteViaUserPermission = permissions.sharedToUsers.some(
(value) => value.canEdit && value.username === user
(value) => value.canEdit && value.username === user,
)
const mayWriteViaGroupPermission =
!!user &&
permissions.sharedToGroups.some(
(value) =>
value.groupName === (SpecialGroup.LOGGED_IN as string) && value.canEdit
value.groupName === (SpecialGroup.LOGGED_IN as string) && value.canEdit,
)
const everyoneMayWriteViaGroupPermission = permissions.sharedToGroups.some(
(value) =>
value.groupName === (SpecialGroup.EVERYONE as string) && value.canEdit
value.groupName === (SpecialGroup.EVERYONE as string) && value.canEdit,
)
return (
isOwner ||

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -22,10 +22,10 @@ export interface NoteGroupPermissionEntry {
export enum AccessLevel {
NONE,
READ_ONLY,
WRITEABLE
WRITEABLE,
}
export enum SpecialGroup {
EVERYONE = '_EVERYONE',
LOGGED_IN = '_LOGGED_IN'
LOGGED_IN = '_LOGGED_IN',
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -19,8 +19,8 @@ describe('extract first heading', () => {
it("doesn't extract heading-anchor", () => {
const headline = new Element(`h${headlineIndex}`, {}, [
new Element('a', { class: 'class1 heading-anchor class2' }, [
new Text('invalid link content')
])
new Text('invalid link content'),
]),
])
const document = new Document([headline])
expect(extractFirstHeading(document)).toBe('')
@ -31,8 +31,8 @@ describe('extract first heading', () => {
new Element('a', {}, [
new Text('Valid'),
new Element('div', {}, [new Text('Text')]),
new Text(`${headlineIndex}`)
])
new Text(`${headlineIndex}`),
]),
])
const document = new Document([headline])
expect(extractFirstHeading(document)).toBe(`ValidText${headlineIndex}`)
@ -40,7 +40,7 @@ describe('extract first heading', () => {
it('extracts image alt texts', () => {
const headline = new Element(`h${headlineIndex}`, {}, [
new Element('img', { alt: 'Image Alt' })
new Element('img', { alt: 'Image Alt' }),
])
const document = new Document([headline])
expect(extractFirstHeading(document)).toBe('Image Alt')
@ -48,10 +48,10 @@ describe('extract first heading', () => {
it('extracts only the first found headline', () => {
const headline1 = new Element(`h${headlineIndex}`, {}, [
new Text(`headline${headlineIndex}`)
new Text(`headline${headlineIndex}`),
])
const headline2 = new Element(`h${headlineIndex}`, {}, [
new Text('headline1')
new Text('headline1'),
])
const document = new Document([headline1, headline2])
expect(extractFirstHeading(document)).toBe(`headline${headlineIndex}`)

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -14,7 +14,7 @@ const headlineTagRegex = /^h[1-6]$/gi
* @return the plain text representation of the first headline. {@code undefined} if no headline has been found.
*/
export function extractFirstHeading(
nodes: NodeWithChildren
nodes: NodeWithChildren,
): string | undefined {
const foundHeadlineNode = checkNodesForHeadline(nodes.children)
if (!foundHeadlineNode) {

View file

@ -1,12 +1,12 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import {
NoteFrontmatter,
NoteTextDirection,
NoteType
NoteType,
} from '../note-frontmatter/frontmatter.js'
import { generateNoteTitle } from './generate-note-title.js'
import { describe, expect, it } from '@jest/globals'
@ -27,8 +27,8 @@ const testFrontmatter: NoteFrontmatter = {
autoSlide: 0,
autoSlideStoppable: true,
backgroundTransition: 'fade',
slideNumber: false
}
slideNumber: false,
},
}
describe('generate note title', () => {
@ -37,9 +37,9 @@ describe('generate note title', () => {
{
...testFrontmatter,
title: 'frontmatter',
opengraph: { title: 'opengraph' }
opengraph: { title: 'opengraph' },
},
() => 'first-heading'
() => 'first-heading',
)
expect(actual).toEqual('frontmatter')
})
@ -47,7 +47,7 @@ describe('generate note title', () => {
it('will choose the opengraph title second', () => {
const actual = generateNoteTitle(
{ ...testFrontmatter, opengraph: { title: 'opengraph' } },
() => 'first-heading'
() => 'first-heading',
)
expect(actual).toEqual('opengraph')
})
@ -55,7 +55,7 @@ describe('generate note title', () => {
it('will choose the first heading third', () => {
const actual = generateNoteTitle(
{ ...testFrontmatter },
() => 'first-heading'
() => 'first-heading',
)
expect(actual).toEqual('first-heading')
})

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -14,7 +14,7 @@ import type { NoteFrontmatter } from '../note-frontmatter/frontmatter.js'
*/
export const generateNoteTitle = (
frontmatter: NoteFrontmatter | undefined,
firstHeadingProvider: () => string | undefined
firstHeadingProvider: () => string | undefined,
): string => {
if (frontmatter?.title) {
return frontmatter.title.trim()

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -42,7 +42,7 @@ export class InMemoryConnectionTransportAdapter implements TransportAdapter {
}
bindOnMessageEvent(
handler: (value: Message<MessageType>) => void
handler: (value: Message<MessageType>) => void,
): () => void {
this.onMessageHandler = handler
return () => (this.onMessageHandler = undefined)

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -25,12 +25,12 @@ describe('realtime doc', () => {
1, 1, 221, 208, 165, 230, 3, 0, 4, 1, 15, 109, 97, 114, 107, 100, 111,
119, 110, 67, 111, 110, 116, 101, 110, 116, 32, 116, 101, 120, 116, 67,
111, 110, 116, 101, 110, 116, 70, 114, 111, 109, 83, 116, 97, 116, 101,
86, 101, 99, 116, 111, 114, 85, 112, 100, 97, 116, 101, 0
]
86, 101, 99, 116, 111, 114, 85, 112, 100, 97, 116, 101, 0,
],
)
expect(realtimeDoc.getCurrentContent()).toBe(
'textContentFromStateVectorUpdate'
'textContentFromStateVectorUpdate',
)
})
})

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -10,7 +10,7 @@ import {
Doc,
encodeStateAsUpdate,
encodeStateVector,
Text as YText
Text as YText,
} from 'yjs'
const MARKDOWN_CONTENT_CHANNEL_NAME = 'markdownContent'
@ -26,7 +26,7 @@ export class RealtimeDoc extends EventEmitter2<RealtimeDocEvents> {
private doc: Doc = new Doc()
private readonly docUpdateListener: (
update: Uint8Array,
origin: unknown
origin: unknown,
) => void
/**

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -30,28 +30,28 @@ describe('y-doc-sync-adapter', () => {
textServer.observe(() =>
// eslint-disable-next-line @typescript-eslint/no-base-to-string
console.log('textServer', new Date(), textServer.toString())
console.log('textServer', new Date(), textServer.toString()),
)
textClient1.observe(() =>
// eslint-disable-next-line @typescript-eslint/no-base-to-string
console.log('textClient1', new Date(), textClient1.toString())
console.log('textClient1', new Date(), textClient1.toString()),
)
textClient2.observe(() =>
// eslint-disable-next-line @typescript-eslint/no-base-to-string
console.log('textClient2', new Date(), textClient2.toString())
console.log('textClient2', new Date(), textClient2.toString()),
)
const transporterAdapterServerTo1 = new InMemoryConnectionTransportAdapter(
's>1'
's>1',
)
const transporterAdapterServerTo2 = new InMemoryConnectionTransportAdapter(
's>2'
's>2',
)
const transporterAdapterClient1 = new InMemoryConnectionTransportAdapter(
'1>s'
'1>s',
)
const transporterAdapterClient2 = new InMemoryConnectionTransportAdapter(
'2>s'
'2>s',
)
const messageTransporterServerTo1 = new MessageTransporter()
@ -60,54 +60,54 @@ describe('y-doc-sync-adapter', () => {
const messageTransporterClient2 = new MessageTransporter()
messageTransporterServerTo1.on(MessageType.NOTE_CONTENT_UPDATE, () =>
console.log('Received NOTE_CONTENT_UPDATE from client 1 to server')
console.log('Received NOTE_CONTENT_UPDATE from client 1 to server'),
)
messageTransporterServerTo2.on(MessageType.NOTE_CONTENT_UPDATE, () =>
console.log('Received NOTE_CONTENT_UPDATE from client 2 to server')
console.log('Received NOTE_CONTENT_UPDATE from client 2 to server'),
)
messageTransporterClient1.on(MessageType.NOTE_CONTENT_UPDATE, () =>
console.log('Received NOTE_CONTENT_UPDATE from server to client 1')
console.log('Received NOTE_CONTENT_UPDATE from server to client 1'),
)
messageTransporterClient2.on(MessageType.NOTE_CONTENT_UPDATE, () =>
console.log('Received NOTE_CONTENT_UPDATE from server to client 2')
console.log('Received NOTE_CONTENT_UPDATE from server to client 2'),
)
messageTransporterServerTo1.on(MessageType.NOTE_CONTENT_STATE_REQUEST, () =>
console.log('Received NOTE_CONTENT_REQUEST from client 1 to server')
console.log('Received NOTE_CONTENT_REQUEST from client 1 to server'),
)
messageTransporterServerTo2.on(MessageType.NOTE_CONTENT_STATE_REQUEST, () =>
console.log('Received NOTE_CONTENT_REQUEST from client 2 to server')
console.log('Received NOTE_CONTENT_REQUEST from client 2 to server'),
)
messageTransporterClient1.on(MessageType.NOTE_CONTENT_STATE_REQUEST, () =>
console.log('Received NOTE_CONTENT_REQUEST from server to client 1')
console.log('Received NOTE_CONTENT_REQUEST from server to client 1'),
)
messageTransporterClient2.on(MessageType.NOTE_CONTENT_STATE_REQUEST, () =>
console.log('Received NOTE_CONTENT_REQUEST from server to client 2')
console.log('Received NOTE_CONTENT_REQUEST from server to client 2'),
)
messageTransporterClient1.doAsSoonAsConnected(() =>
console.log('1>s is connected')
console.log('1>s is connected'),
)
messageTransporterClient2.doAsSoonAsConnected(() =>
console.log('2>s is connected')
console.log('2>s is connected'),
)
messageTransporterServerTo1.doAsSoonAsConnected(() =>
console.log('s>1 is connected')
console.log('s>1 is connected'),
)
messageTransporterServerTo2.doAsSoonAsConnected(() =>
console.log('s>2 is connected')
console.log('s>2 is connected'),
)
messageTransporterClient1.doAsSoonAsReady(() => console.log('1>s is ready'))
messageTransporterClient2.doAsSoonAsReady(() => console.log('2>s is ready'))
messageTransporterServerTo1.doAsSoonAsReady(() =>
console.log('s>1 is connected')
console.log('s>1 is connected'),
)
messageTransporterServerTo2.doAsSoonAsReady(() =>
console.log('s>2 is connected')
console.log('s>2 is connected'),
)
docServer.on('update', (update: number[], origin: unknown) => {
const message: Message<MessageType.NOTE_CONTENT_UPDATE> = {
type: MessageType.NOTE_CONTENT_UPDATE,
payload: update
payload: update,
}
if (origin !== messageTransporterServerTo1) {
console.log('YDoc on Server updated. Sending to Client 1')
@ -131,23 +131,23 @@ describe('y-doc-sync-adapter', () => {
const yDocSyncAdapter1 = new YDocSyncClientAdapter(
messageTransporterClient1,
docClient1
docClient1,
)
const yDocSyncAdapter2 = new YDocSyncClientAdapter(
messageTransporterClient2,
docClient2
docClient2,
)
const yDocSyncAdapterServerTo1 = new YDocSyncServerAdapter(
messageTransporterServerTo1,
docServer,
() => true
() => true,
)
const yDocSyncAdapterServerTo2 = new YDocSyncServerAdapter(
messageTransporterServerTo2,
docServer,
() => true
() => true,
)
const waitForClient1Sync = new Promise<void>((resolve) => {
@ -202,7 +202,7 @@ describe('y-doc-sync-adapter', () => {
waitForClient1Sync,
waitForClient2Sync,
waitForServerTo11Sync,
waitForServerTo21Sync
waitForServerTo21Sync,
])
textClient1.insert(0, 'test2')

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -23,7 +23,7 @@ export abstract class YDocSyncAdapter {
constructor(
protected readonly messageTransporter: MessageTransporter,
protected readonly doc: RealtimeDoc
protected readonly doc: RealtimeDoc,
) {
this.yDocUpdateListener = doc.on(
'update',
@ -31,8 +31,8 @@ export abstract class YDocSyncAdapter {
this.distributeDocUpdate(update, origin)
},
{
objectify: true
}
objectify: true,
},
) as Listener
this.destroyEventListenerCallback = this.bindDocumentSyncMessageEvents()
@ -50,7 +50,7 @@ export abstract class YDocSyncAdapter {
callback()
}
return this.eventEmitter.on('synced', callback, {
objectify: true
objectify: true,
}) as Listener
}
@ -69,10 +69,10 @@ export abstract class YDocSyncAdapter {
(payload) => {
this.messageTransporter.sendMessage({
type: MessageType.NOTE_CONTENT_UPDATE,
payload: this.doc.encodeStateAsUpdate(payload.payload)
payload: this.doc.encodeStateAsUpdate(payload.payload),
})
},
{ objectify: true }
{ objectify: true },
) as Listener
const disconnectedListener = this.messageTransporter.on(
@ -81,13 +81,13 @@ export abstract class YDocSyncAdapter {
this.synced = false
this.eventEmitter.emit('desynced')
},
{ objectify: true }
{ objectify: true },
) as Listener
const noteContentUpdateListener = this.messageTransporter.on(
MessageType.NOTE_CONTENT_UPDATE,
(payload) => this.applyIncomingUpdatePayload(payload.payload),
{ objectify: true }
{ objectify: true },
) as Listener
return () => {
@ -107,7 +107,7 @@ export abstract class YDocSyncAdapter {
}
const message: Message<MessageType.NOTE_CONTENT_UPDATE> = {
type: MessageType.NOTE_CONTENT_UPDATE,
payload: update
payload: update,
}
this.messageTransporter.sendMessage(message)
@ -124,7 +124,7 @@ export abstract class YDocSyncAdapter {
public requestDocumentState(): void {
this.messageTransporter.sendMessage({
type: MessageType.NOTE_CONTENT_STATE_REQUEST,
payload: this.doc.encodeStateVector()
payload: this.doc.encodeStateVector(),
})
}
}

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -16,7 +16,7 @@ export class YDocSyncClientAdapter extends YDocSyncAdapter {
() => {
this.markAsSynced()
},
{ objectify: true }
{ objectify: true },
) as Listener
return () => {

View file

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
* SPDX-FileCopyrightText: 2025 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
@ -11,7 +11,7 @@ export class YDocSyncServerAdapter extends YDocSyncAdapter {
constructor(
readonly messageTransporter: MessageTransporter,
readonly doc: RealtimeDoc,
private readonly acceptEditsProvider: () => boolean
private readonly acceptEditsProvider: () => boolean,
) {
super(messageTransporter, doc)
this.markAsSynced()