ocean-brain 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/server/client/dist/assets/{Calendar-BytW4PeT.js → Calendar-DbPut8EU.js} +1 -1
- package/server/client/dist/assets/{Callout-9sJgGNRb.js → Callout-DfX-gIUB.js} +1 -1
- package/server/client/dist/assets/{Graph-o5u-NzrA.js → Graph-yHE9m5fy.js} +1 -1
- package/server/client/dist/assets/{Image-DxWhlIDG.js → Image-DK0lnaK2.js} +1 -1
- package/server/client/dist/assets/{Image.es-B0LL3pb7.js → Image.es-CtMc7BW4.js} +1 -1
- package/server/client/dist/assets/{Note-CYoYzZNu.js → Note-BECn-AoI.js} +2 -2
- package/server/client/dist/assets/{Plus.es-DpxzgRtY.js → Plus.es-BGVIIQtM.js} +1 -1
- package/server/client/dist/assets/{Reminders-DAepTZg1.js → Reminders-CvEJf0eQ.js} +1 -1
- package/server/client/dist/assets/{Search-6KH7An44.js → Search-CKZhztuV.js} +1 -1
- package/server/client/dist/assets/{SurfaceCard-EMs50xSF.js → SurfaceCard-Bnfo5EOl.js} +1 -1
- package/server/client/dist/assets/Tag-C4oAwjs0.js +1 -0
- package/server/client/dist/assets/{TagNotes-BTbu-f6v.js → TagNotes-Rl1ZSJP6.js} +1 -1
- package/server/client/dist/assets/{Trash.es-C5x35NKF.js → Trash.es-BcwUz2yM.js} +1 -1
- package/server/client/dist/assets/ViewNotes-B9Yc0A87.js +1 -0
- package/server/client/dist/assets/ViewSectionTableRenderer-C5yJBO7C.js +102 -0
- package/server/client/dist/assets/Views-Bqq0pUEE.js +1 -0
- package/server/client/dist/assets/{image.api-DRhRQ0Gf.js → image.api-CuGTgzyQ.js} +1 -1
- package/server/client/dist/assets/{index-DYlYUrjH.js → index-B43ulIPo.js} +40 -40
- package/server/client/dist/assets/{index-DswSFFMb.js → index-BQDR6hIA.js} +1 -1
- package/server/client/dist/assets/{index-Cd81UxEh.css → index-CDjYEIVf.css} +1 -1
- package/server/client/dist/assets/manage-image-Bs4Kmevx.js +1 -0
- package/server/client/dist/assets/{manage-image-detail-CJkfybR9.js → manage-image-detail-WARala-v.js} +1 -1
- package/server/client/dist/assets/{mcp-piouFDNm.js → mcp-C0Z3vKBa.js} +1 -1
- package/server/client/dist/assets/{note-core-Z6kqulGB.js → note-core-DMZcZ4yV.js} +53 -53
- package/server/client/dist/assets/{note-vendor-i1M2FSI2.js → note-vendor-uuJO2MTD.js} +1 -1
- package/server/client/dist/assets/{placeholder-DGz3CHej.js → placeholder-D080guzn.js} +3 -3
- package/server/client/dist/assets/{properties-CM4khczg.js → properties-DbnmfbT5.js} +1 -1
- package/server/client/dist/assets/trash-D5ZiZfTk.js +1 -0
- package/server/client/dist/assets/{useReminderMutate-DHjDDHKg.js → useReminderMutate-h7d_S_X2.js} +2 -2
- package/server/client/dist/index.html +4 -4
- package/server/dist/features/note/services/markdown-intent-write.js +17 -0
- package/server/dist/features/note/services/markdown-intent-write.js.map +1 -1
- package/server/dist/features/note/services/markdown-patch.js.map +1 -1
- package/server/dist/features/view/graphql/view.type-defs.js +22 -0
- package/server/dist/features/view/graphql/view.type-defs.js.map +1 -1
- package/server/dist/features/view/services/workspace.js +77 -16
- package/server/dist/features/view/services/workspace.js.map +1 -1
- package/server/dist/modules/blocknote.js +320 -5
- package/server/dist/modules/blocknote.js.map +1 -1
- package/server/prisma/schema.prisma +1 -0
- package/server/client/dist/assets/Tag-C89j8x56.js +0 -1
- package/server/client/dist/assets/ViewNotes-DPEuki3y.js +0 -1
- package/server/client/dist/assets/Views-BGkuNhVd.js +0 -1
- package/server/client/dist/assets/manage-image-C6sHhWnI.js +0 -1
- package/server/client/dist/assets/trash-C2lItz-b.js +0 -1
- package/server/client/dist/assets/view-dashboard-C17WsdL7.js +0 -99
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/features/view/services/workspace.ts"],"sourcesContent":["import type { Note, Prisma, PropertyValueType } from '@prisma/client';\nimport {\n InvalidNotePropertyInputError,\n normalizePropertyKey,\n normalizeUrlValue,\n} from '~/features/note/services/properties.js';\nimport { buildNoteTagNamesWhere, type NoteTagMatchMode } from '~/features/note/services/tag-filter.js';\nimport models from '~/models.js';\n\nexport type ViewTagMatchMode = NoteTagMatchMode;\nexport type ViewDisplayType = 'list' | 'calendar';\nexport type ViewPropertyFilterOperator = 'equals' | 'before' | 'after' | 'exists' | 'notExists';\nexport type ViewSortBy = 'updatedAt' | 'createdAt' | 'title';\nexport type ViewSortOrder = 'asc' | 'desc';\n\nexport interface ViewPropertyFilterRecord {\n key: string;\n name: string;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n value: string | null;\n}\n\nexport interface ViewSectionRecord {\n id: string;\n tabId: string;\n title: string;\n displayType: ViewDisplayType;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n order: number;\n}\n\nexport interface ViewTabRecord {\n id: string;\n title: string;\n order: number;\n sections: ViewSectionRecord[];\n}\n\nexport interface ViewWorkspaceRecord {\n activeTabId: string | null;\n tabs: ViewTabRecord[];\n}\n\nexport interface ViewSectionInput {\n title?: string;\n displayType?: ViewDisplayType;\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n limit?: number;\n}\n\nexport interface ViewNotesQueryInput {\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n}\n\nexport interface ViewNotesQueryRecord {\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n}\n\nexport interface ViewPropertyFilterInput {\n key: string;\n operator: ViewPropertyFilterOperator;\n value?: string | null;\n valueType?: PropertyValueType | null;\n}\n\nexport interface ViewSectionNotesResult {\n totalCount: number;\n notes: Note[];\n}\n\nconst VIEW_WORKSPACE_ID = 1;\n\nexport const DEFAULT_VIEW_SECTION_LIMIT = 5;\nexport const MIN_VIEW_SECTION_LIMIT = 1;\nexport const MAX_VIEW_SECTION_LIMIT = 20;\nexport const DEFAULT_VIEW_NOTES_QUERY_LIMIT = 20;\nexport const MAX_VIEW_NOTES_QUERY_LIMIT = 50;\nconst MAX_VIEW_PROPERTY_FILTERS = 10;\nconst DEFAULT_VIEW_DISPLAY_TYPE: ViewDisplayType = 'list';\nconst DEFAULT_VIEW_SORT_BY: ViewSortBy = 'updatedAt';\nconst DEFAULT_VIEW_SORT_ORDER: ViewSortOrder = 'desc';\n\ntype ViewDbClient = typeof models | Prisma.TransactionClient;\n\nconst orderedViewSectionTagsInclude = {\n tags: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n },\n} satisfies Prisma.ViewSectionInclude;\n\nconst orderedViewTabSectionsInclude = {\n sections: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n },\n} satisfies Prisma.ViewTabInclude;\n\ntype DbViewSection = Prisma.ViewSectionGetPayload<{\n include: typeof orderedViewSectionTagsInclude;\n}>;\n\ntype DbViewTab = Prisma.ViewTabGetPayload<{\n include: typeof orderedViewTabSectionsInclude;\n}>;\n\nconst normalizeTagName = (value: string) => {\n const trimmedValue = value.trim();\n\n if (!trimmedValue) {\n return '';\n }\n\n if (trimmedValue.startsWith('@')) {\n return trimmedValue;\n }\n\n if (trimmedValue.startsWith('#')) {\n return `@${trimmedValue.slice(1)}`;\n }\n\n return `@${trimmedValue}`;\n};\n\nexport const normalizeViewTagNames = (values: string[]) => {\n const normalizedTagNames = values.flatMap((value) => value.split(','));\n\n return Array.from(new Set(normalizedTagNames.map(normalizeTagName).filter(Boolean)));\n};\n\ninterface StoredViewQuery {\n propertyFilters?: ViewPropertyFilterRecord[];\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n}\n\nconst isViewPropertyFilterOperator = (value: unknown): value is ViewPropertyFilterOperator => {\n return value === 'equals' || value === 'before' || value === 'after' || value === 'exists' || value === 'notExists';\n};\n\nconst isPropertyValueType = (value: unknown): value is PropertyValueType => {\n return (\n value === 'text' ||\n value === 'url' ||\n value === 'number' ||\n value === 'date' ||\n value === 'boolean' ||\n value === 'select'\n );\n};\n\nconst normalizeViewDisplayType = (value: ViewDisplayType | undefined): ViewDisplayType => {\n return value === 'calendar' ? 'calendar' : DEFAULT_VIEW_DISPLAY_TYPE;\n};\n\nconst normalizeViewSortBy = (value: ViewSortBy | undefined): ViewSortBy => {\n return value === 'createdAt' || value === 'title' ? value : DEFAULT_VIEW_SORT_BY;\n};\n\nconst normalizeViewSortOrder = (value: ViewSortOrder | undefined): ViewSortOrder => {\n return value === 'asc' ? 'asc' : DEFAULT_VIEW_SORT_ORDER;\n};\n\nconst normalizeFilterValue = ({\n value,\n valueType,\n operator,\n}: {\n value?: string | null;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n}) => {\n if (operator === 'exists' || operator === 'notExists') {\n return null;\n }\n\n const normalizedValue = String(value ?? '').trim();\n\n if (!normalizedValue) {\n throw new InvalidNotePropertyInputError('Property filter value is required.');\n }\n\n if (valueType === 'number' && !Number.isFinite(Number(normalizedValue))) {\n throw new InvalidNotePropertyInputError('Number property filter value must be finite.');\n }\n\n if (valueType === 'boolean' && normalizedValue !== 'true' && normalizedValue !== 'false') {\n throw new InvalidNotePropertyInputError('Boolean property filter value must be true or false.');\n }\n\n if (valueType === 'date') {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(normalizedValue)) {\n throw new InvalidNotePropertyInputError('Date property filter values must use YYYY-MM-DD.');\n }\n\n const date = new Date(`${normalizedValue}T00:00:00.000Z`);\n\n if (Number.isNaN(date.getTime()) || date.toISOString().slice(0, 10) !== normalizedValue) {\n throw new InvalidNotePropertyInputError('Date property filter value is invalid.');\n }\n }\n\n if ((operator === 'before' || operator === 'after') && valueType !== 'date' && valueType !== 'number') {\n throw new InvalidNotePropertyInputError('Before and after filters require date or number properties.');\n }\n\n if (valueType === 'url') {\n return normalizeUrlValue(normalizedValue);\n }\n\n return normalizedValue;\n};\n\nexport const normalizeViewPropertyFilters = (filters: ViewPropertyFilterInput[] | null | undefined) => {\n const normalizedFilters = filters ?? [];\n\n if (normalizedFilters.length > MAX_VIEW_PROPERTY_FILTERS) {\n throw new InvalidNotePropertyInputError(`A view can have up to ${MAX_VIEW_PROPERTY_FILTERS} property filters.`);\n }\n\n return normalizedFilters\n .map((filter): ViewPropertyFilterRecord | null => {\n const key = normalizePropertyKey(filter.key);\n const valueType = filter.valueType;\n const operator = filter.operator;\n\n if (!isPropertyValueType(valueType)) {\n throw new InvalidNotePropertyInputError('Property filter value type is required.');\n }\n\n if (!isViewPropertyFilterOperator(operator)) {\n throw new InvalidNotePropertyInputError('Property filter operator is invalid.');\n }\n\n const storedName = (filter as { name?: unknown }).name;\n const name = typeof storedName === 'string' && storedName.trim() ? storedName.trim() : key;\n\n return {\n key,\n name,\n valueType,\n operator,\n value: normalizeFilterValue({\n value: filter.value,\n valueType,\n operator,\n }),\n };\n })\n .filter((filter): filter is ViewPropertyFilterRecord => filter !== null);\n};\n\nconst parseStoredViewQuery = (value: string | null): Required<StoredViewQuery> => {\n if (!value) {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n };\n }\n\n try {\n const parsed = JSON.parse(value) as Partial<StoredViewQuery>;\n\n return {\n propertyFilters: normalizeViewPropertyFilters(parsed.propertyFilters ?? []),\n sortBy: normalizeViewSortBy(parsed.sortBy),\n sortOrder: normalizeViewSortOrder(parsed.sortOrder),\n };\n } catch {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n };\n }\n};\n\nconst serializeStoredViewQuery = ({ propertyFilters, sortBy, sortOrder }: Required<StoredViewQuery>) => {\n return JSON.stringify({\n propertyFilters,\n sortBy,\n sortOrder,\n });\n};\n\nexport const clampViewSectionLimit = (value: number | undefined) => {\n const numericValue = typeof value === 'number' ? value : Number.NaN;\n\n if (!Number.isInteger(numericValue)) {\n return DEFAULT_VIEW_SECTION_LIMIT;\n }\n\n return Math.min(MAX_VIEW_SECTION_LIMIT, Math.max(MIN_VIEW_SECTION_LIMIT, numericValue));\n};\n\nexport const normalizeViewTabTitle = (title: string) => {\n const trimmedTitle = title.trim();\n\n return trimmedTitle || 'Untitled View';\n};\n\nconst buildDefaultSectionTitle = (tagNames: string[], propertyFilters: ViewPropertyFilterRecord[]) => {\n if (tagNames.length > 0) {\n return tagNames.slice(0, 2).join(' + ');\n }\n\n if (propertyFilters.length > 0) {\n return propertyFilters\n .slice(0, 2)\n .map((filter) => filter.name)\n .join(' + ');\n }\n\n return 'All notes';\n};\n\nexport const normalizeViewSectionInput = (input: ViewSectionInput) => {\n const tagNames = normalizeViewTagNames(input.tagNames ?? []);\n const propertyFilters = normalizeViewPropertyFilters(input.propertyFilters);\n const trimmedTitle = input.title?.trim() ?? '';\n const sortBy = normalizeViewSortBy(input.sortBy);\n const sortOrder = normalizeViewSortOrder(input.sortOrder);\n\n return {\n title: trimmedTitle || buildDefaultSectionTitle(tagNames, propertyFilters),\n displayType: normalizeViewDisplayType(input.displayType),\n tagNames,\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters,\n sortBy,\n sortOrder,\n limit: clampViewSectionLimit(input.limit),\n } satisfies {\n title: string;\n displayType: ViewDisplayType;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n };\n};\n\nexport const normalizeViewNotesQueryInput = (input: ViewNotesQueryInput): ViewNotesQueryRecord => {\n return {\n tagNames: normalizeViewTagNames(input.tagNames ?? []),\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters: normalizeViewPropertyFilters(input.propertyFilters),\n sortBy: normalizeViewSortBy(input.sortBy),\n sortOrder: normalizeViewSortOrder(input.sortOrder),\n };\n};\n\nexport const normalizeViewNotesPagination = (pagination?: { limit?: number; offset?: number }) => {\n const numericLimit = Number(pagination?.limit ?? DEFAULT_VIEW_NOTES_QUERY_LIMIT);\n const limit = Number.isInteger(numericLimit)\n ? Math.min(MAX_VIEW_NOTES_QUERY_LIMIT, Math.max(1, numericLimit))\n : DEFAULT_VIEW_NOTES_QUERY_LIMIT;\n const numericOffset = Number(pagination?.offset ?? 0);\n const offset = Number.isInteger(numericOffset) ? Math.max(0, numericOffset) : 0;\n\n return { limit, offset };\n};\n\nexport const pickNextActiveViewTabId = (tabIds: number[], deletedTabId: number, currentActiveTabId: number | null) => {\n const remainingTabIds = tabIds.filter((tabId) => tabId !== deletedTabId);\n\n if (remainingTabIds.length === 0) {\n return null;\n }\n\n if (currentActiveTabId !== deletedTabId) {\n return currentActiveTabId;\n }\n\n return remainingTabIds[0] ?? null;\n};\n\nconst ensureValidReorderIds = (currentIds: number[], nextIds: number[]) => {\n if (currentIds.length !== nextIds.length) {\n throw new Error('Reorder payload must include every item exactly once.');\n }\n\n const currentIdSet = new Set(currentIds);\n const nextIdSet = new Set(nextIds);\n\n if (currentIdSet.size !== currentIds.length || nextIdSet.size !== nextIds.length) {\n throw new Error('Reorder payload contains duplicate ids.');\n }\n\n for (const id of currentIdSet) {\n if (!nextIdSet.has(id)) {\n throw new Error('Reorder payload must match the current item set.');\n }\n }\n};\n\nconst parseViewId = (id: string) => {\n const numericId = Number(id);\n\n if (!Number.isInteger(numericId) || numericId <= 0) {\n throw new Error('A valid id is required.');\n }\n\n return numericId;\n};\n\nconst serializeViewSection = (section: DbViewSection): ViewSectionRecord => {\n const query = parseStoredViewQuery(section.query);\n\n return {\n id: String(section.id),\n tabId: String(section.tabId),\n title: section.title,\n displayType: normalizeViewDisplayType(section.displayType as ViewDisplayType),\n tagNames: section.tags.map((tag) => tag.name),\n mode: section.mode as ViewTagMatchMode,\n propertyFilters: query.propertyFilters,\n sortBy: query.sortBy,\n sortOrder: query.sortOrder,\n limit: section.limit,\n order: section.order,\n };\n};\n\nconst serializeViewTab = (tab: DbViewTab): ViewTabRecord => ({\n id: String(tab.id),\n title: tab.title,\n order: tab.order,\n sections: tab.sections.map(serializeViewSection),\n});\n\nconst getOrderedViewTabs = async (db: ViewDbClient) => {\n return db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewTabSectionsInclude,\n });\n};\n\nconst ensureViewWorkspace = async (db: ViewDbClient) => {\n return db.viewWorkspace.upsert({\n where: { id: VIEW_WORKSPACE_ID },\n update: {},\n create: { id: VIEW_WORKSPACE_ID },\n });\n};\n\nconst readViewWorkspace = async (db: ViewDbClient): Promise<ViewWorkspaceRecord> => {\n const [workspace, tabs] = await Promise.all([ensureViewWorkspace(db), getOrderedViewTabs(db)]);\n\n const activeTabId =\n workspace.activeTabId !== null && tabs.some((tab) => tab.id === workspace.activeTabId)\n ? String(workspace.activeTabId)\n : tabs[0]\n ? String(tabs[0].id)\n : null;\n\n return {\n activeTabId,\n tabs: tabs.map(serializeViewTab),\n };\n};\n\nconst readViewSection = async (db: ViewDbClient, id: number): Promise<ViewSectionRecord | null> => {\n const section = await db.viewSection.findUnique({\n where: { id },\n include: orderedViewSectionTagsInclude,\n });\n\n return section ? serializeViewSection(section) : null;\n};\n\nexport const hydratePropertyFilters = async (\n db: ViewDbClient,\n filters: ViewPropertyFilterRecord[],\n options: { validateSelectOptions?: boolean } = {},\n) => {\n if (filters.length === 0) {\n return [];\n }\n\n const definitions = await db.propertyDefinition.findMany({\n where: { key: { in: filters.map((filter) => filter.key) } },\n select: {\n key: true,\n name: true,\n valueType: true,\n options: {\n select: {\n value: true,\n },\n },\n },\n });\n const definitionByKey = new Map(definitions.map((definition) => [definition.key, definition]));\n\n return filters.map((filter) => {\n const definition = definitionByKey.get(filter.key);\n\n if (!definition) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} is not defined.`);\n }\n\n if (definition.valueType !== filter.valueType) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} uses ${definition.valueType} values.`);\n }\n\n if (\n options.validateSelectOptions &&\n filter.valueType === 'select' &&\n filter.operator !== 'exists' &&\n filter.operator !== 'notExists'\n ) {\n const optionValue = normalizeSelectFilterValue(filter.value ?? '');\n\n if (!definition.options.some((option) => option.value === optionValue)) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} option ${optionValue} is not defined.`);\n }\n }\n\n return {\n ...filter,\n name: definition.name,\n };\n });\n};\n\nconst buildStoredViewQuery = async (db: ViewDbClient, section: ReturnType<typeof normalizeViewSectionInput>) => {\n const propertyFilters = await hydratePropertyFilters(db, section.propertyFilters, { validateSelectOptions: true });\n\n return serializeStoredViewQuery({\n propertyFilters,\n sortBy: section.sortBy,\n sortOrder: section.sortOrder,\n });\n};\n\nconst getNextTabOrder = async (db: ViewDbClient) => {\n const lastTab = await db.viewTab.findFirst({\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastTab ? lastTab.order + 1 : 0;\n};\n\nconst getNextSectionOrder = async (db: ViewDbClient, tabId: number) => {\n const lastSection = await db.viewSection.findFirst({\n where: { tabId },\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastSection ? lastSection.order + 1 : 0;\n};\n\nconst resequenceViewTabs = async (db: ViewDbClient) => {\n const tabs = await db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n tabs.map((tab, index) =>\n db.viewTab.update({\n where: { id: tab.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nconst resequenceViewSections = async (db: ViewDbClient, tabId: number) => {\n const sections = await db.viewSection.findMany({\n where: { tabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n sections.map((section, index) =>\n db.viewSection.update({\n where: { id: section.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nexport const getViewWorkspace = async () => {\n return readViewWorkspace(models);\n};\n\nexport const getViewSectionById = async (id: string) => {\n return readViewSection(models, parseViewId(id));\n};\n\nconst normalizeSelectFilterValue = (value: string) => {\n return value.trim().toLowerCase().replace(/\\s+/g, '-');\n};\n\nconst buildPropertyFilterValueWhere = (filter: ViewPropertyFilterRecord): Prisma.NotePropertyWhereInput => {\n switch (filter.valueType) {\n case 'number': {\n const numberValue = Number(filter.value);\n\n if (filter.operator === 'before') {\n return { numberValue: { lt: numberValue } };\n }\n\n if (filter.operator === 'after') {\n return { numberValue: { gt: numberValue } };\n }\n\n return { numberValue };\n }\n case 'date': {\n const dateValue = new Date(`${filter.value}T00:00:00.000Z`);\n\n if (filter.operator === 'before') {\n return { dateValue: { lt: dateValue } };\n }\n\n if (filter.operator === 'after') {\n return { dateValue: { gt: dateValue } };\n }\n\n return { dateValue };\n }\n case 'boolean':\n return { boolValue: filter.value === 'true' };\n case 'select':\n return { option: { is: { value: normalizeSelectFilterValue(filter.value ?? '') } } };\n case 'url':\n case 'text':\n default:\n return { textValueNormalized: filter.value?.toLowerCase() ?? '' };\n }\n};\n\nexport const buildPropertyFilterWhere = (filter: ViewPropertyFilterRecord): Prisma.NoteWhereInput => {\n const definitionWhere = {\n definition: {\n is: {\n key: filter.key,\n },\n },\n } satisfies Prisma.NotePropertyWhereInput;\n\n if (filter.operator === 'notExists') {\n return {\n properties: {\n none: definitionWhere,\n },\n };\n }\n\n if (filter.operator === 'exists') {\n return {\n properties: {\n some: definitionWhere,\n },\n };\n }\n\n return {\n properties: {\n some: {\n ...definitionWhere,\n ...buildPropertyFilterValueWhere(filter),\n },\n },\n };\n};\n\nexport const buildViewNotesWhere = (\n query: Pick<ViewNotesQueryRecord, 'tagNames' | 'mode' | 'propertyFilters'>,\n): Prisma.NoteWhereInput => {\n const clauses: Prisma.NoteWhereInput[] = [];\n\n if (query.tagNames.length > 0) {\n clauses.push(buildNoteTagNamesWhere(query.tagNames, query.mode as NoteTagMatchMode));\n }\n\n for (const filter of query.propertyFilters) {\n clauses.push(buildPropertyFilterWhere(filter));\n }\n\n if (clauses.length === 0) {\n return {};\n }\n\n return { AND: clauses };\n};\n\nexport const buildViewSectionWhere = (section: ViewSectionRecord): Prisma.NoteWhereInput => {\n return buildViewNotesWhere(section);\n};\n\nconst buildViewNotesOrderBy = (\n query: Pick<ViewNotesQueryRecord, 'sortBy' | 'sortOrder'>,\n): Prisma.NoteOrderByWithRelationInput[] => {\n return [{ [query.sortBy]: query.sortOrder }, { id: 'asc' }];\n};\n\nconst buildViewSectionOrderBy = (section: ViewSectionRecord): Prisma.NoteOrderByWithRelationInput[] => {\n return buildViewNotesOrderBy(section);\n};\n\nexport const getViewSectionNotes = async (\n id: string,\n pagination: {\n limit: number;\n offset: number;\n },\n): Promise<ViewSectionNotesResult | null> => {\n const section = await models.viewSection.findUnique({\n where: { id: parseViewId(id) },\n include: orderedViewSectionTagsInclude,\n });\n\n if (!section) {\n return null;\n }\n\n const serializedSection = serializeViewSection(section);\n const where = buildViewSectionWhere(serializedSection);\n\n const [totalCount, notes] = await Promise.all([\n models.note.count({ where }),\n models.note.findMany({\n orderBy: buildViewSectionOrderBy(serializedSection),\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset),\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const getNotesByProperties = async (\n input: ViewNotesQueryInput,\n pagination?: {\n limit?: number;\n offset?: number;\n },\n): Promise<ViewSectionNotesResult> => {\n const normalizedQuery = normalizeViewNotesQueryInput(input);\n\n if (normalizedQuery.propertyFilters.length === 0) {\n throw new InvalidNotePropertyInputError('At least one property filter is required.');\n }\n\n const query = {\n ...normalizedQuery,\n propertyFilters: await hydratePropertyFilters(models, normalizedQuery.propertyFilters, {\n validateSelectOptions: true,\n }),\n };\n const normalizedPagination = normalizeViewNotesPagination(pagination);\n const where = buildViewNotesWhere(query);\n\n const [totalCount, notes] = await Promise.all([\n models.note.count({ where }),\n models.note.findMany({\n orderBy: buildViewNotesOrderBy(query),\n where,\n take: normalizedPagination.limit,\n skip: normalizedPagination.offset,\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const createViewTab = async (title: string) => {\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const nextTabOrder = await getNextTabOrder(tx);\n const createdTab = await tx.viewTab.create({\n data: {\n title: normalizeViewTabTitle(title),\n order: nextTabOrder,\n },\n include: orderedViewTabSectionsInclude,\n });\n\n if (workspace.activeTabId === null) {\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: createdTab.id },\n });\n }\n\n return serializeViewTab(createdTab);\n });\n};\n\nexport const updateViewTab = async (id: string, title: string) => {\n const updatedTab = await models.viewTab.update({\n where: { id: parseViewId(id) },\n data: {\n title: normalizeViewTabTitle(title),\n },\n include: orderedViewTabSectionsInclude,\n });\n\n return serializeViewTab(updatedTab);\n};\n\nexport const deleteViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n if (!tabs.some((tab) => tab.id === tabId)) {\n return false;\n }\n\n await tx.viewTab.delete({ where: { id: tabId } });\n await resequenceViewTabs(tx);\n\n const nextActiveTabId = pickNextActiveViewTabId(\n tabs.map((tab) => tab.id),\n tabId,\n workspace.activeTabId,\n );\n\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: nextActiveTabId },\n });\n\n return true;\n });\n};\n\nexport const setActiveViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tab = await tx.viewTab.findUnique({\n where: { id: tabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n await tx.viewWorkspace.update({\n where: { id: workspace.id },\n data: { activeTabId: tabId },\n });\n\n return readViewWorkspace(tx);\n });\n};\n\nexport const reorderViewTabs = async (tabIds: string[]) => {\n const nextTabIds = tabIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentTabIds = tabs.map((tab) => tab.id);\n\n ensureValidReorderIds(currentTabIds, nextTabIds);\n\n await Promise.all(\n nextTabIds.map((tabId, index) =>\n tx.viewTab.update({\n where: { id: tabId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedTabs = await getOrderedViewTabs(tx);\n return reorderedTabs.map(serializeViewTab);\n });\n};\n\nexport const createViewSection = async (tabId: string, input: ViewSectionInput) => {\n const numericTabId = parseViewId(tabId);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const tab = await tx.viewTab.findUnique({\n where: { id: numericTabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n const nextSectionOrder = await getNextSectionOrder(tx, numericTabId);\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const createdSection = await tx.viewSection.create({\n data: {\n tabId: numericTabId,\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n order: nextSectionOrder,\n tags: {\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(createdSection);\n });\n};\n\nexport const updateViewSection = async (id: string, input: ViewSectionInput) => {\n const sectionId = parseViewId(id);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const updatedSection = await tx.viewSection.update({\n where: { id: sectionId },\n data: {\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n tags: {\n deleteMany: {},\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(updatedSection);\n });\n};\n\nexport const deleteViewSection = async (id: string) => {\n const sectionId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const section = await tx.viewSection.findUnique({\n where: { id: sectionId },\n select: { id: true, tabId: true },\n });\n\n if (!section) {\n return false;\n }\n\n await tx.viewSection.delete({\n where: { id: sectionId },\n });\n await resequenceViewSections(tx, section.tabId);\n\n return true;\n });\n};\n\nexport const reorderViewSections = async (tabId: string, sectionIds: string[]) => {\n const numericTabId = parseViewId(tabId);\n const nextSectionIds = sectionIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const sections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentSectionIds = sections.map((section) => section.id);\n\n ensureValidReorderIds(currentSectionIds, nextSectionIds);\n\n await Promise.all(\n nextSectionIds.map((sectionId, index) =>\n tx.viewSection.update({\n where: { id: sectionId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedSections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n });\n\n return reorderedSections.map(serializeViewSection);\n });\n};\n"],"mappings":"AACA;AAAA,EACI;AAAA,EACA;AAAA,EACA;AAAA,OACG;AACP,SAAS,8BAAqD;AAC9D,OAAO,YAAY;AAiFnB,MAAM,oBAAoB;AAEnB,MAAM,6BAA6B;AACnC,MAAM,yBAAyB;AAC/B,MAAM,yBAAyB;AAC/B,MAAM,iCAAiC;AACvC,MAAM,6BAA6B;AAC1C,MAAM,4BAA4B;AAClC,MAAM,4BAA6C;AACnD,MAAM,uBAAmC;AACzC,MAAM,0BAAyC;AAI/C,MAAM,gCAAgC;AAAA,EAClC,MAAM;AAAA,IACF,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,EACpD;AACJ;AAEA,MAAM,gCAAgC;AAAA,EAClC,UAAU;AAAA,IACN,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,SAAS;AAAA,EACb;AACJ;AAUA,MAAM,mBAAmB,CAAC,UAAkB;AACxC,QAAM,eAAe,MAAM,KAAK;AAEhC,MAAI,CAAC,cAAc;AACf,WAAO;AAAA,EACX;AAEA,MAAI,aAAa,WAAW,GAAG,GAAG;AAC9B,WAAO;AAAA,EACX;AAEA,MAAI,aAAa,WAAW,GAAG,GAAG;AAC9B,WAAO,IAAI,aAAa,MAAM,CAAC,CAAC;AAAA,EACpC;AAEA,SAAO,IAAI,YAAY;AAC3B;AAEO,MAAM,wBAAwB,CAAC,WAAqB;AACvD,QAAM,qBAAqB,OAAO,QAAQ,CAAC,UAAU,MAAM,MAAM,GAAG,CAAC;AAErE,SAAO,MAAM,KAAK,IAAI,IAAI,mBAAmB,IAAI,gBAAgB,EAAE,OAAO,OAAO,CAAC,CAAC;AACvF;AAQA,MAAM,+BAA+B,CAAC,UAAwD;AAC1F,SAAO,UAAU,YAAY,UAAU,YAAY,UAAU,WAAW,UAAU,YAAY,UAAU;AAC5G;AAEA,MAAM,sBAAsB,CAAC,UAA+C;AACxE,SACI,UAAU,UACV,UAAU,SACV,UAAU,YACV,UAAU,UACV,UAAU,aACV,UAAU;AAElB;AAEA,MAAM,2BAA2B,CAAC,UAAwD;AACtF,SAAO,UAAU,aAAa,aAAa;AAC/C;AAEA,MAAM,sBAAsB,CAAC,UAA8C;AACvE,SAAO,UAAU,eAAe,UAAU,UAAU,QAAQ;AAChE;AAEA,MAAM,yBAAyB,CAAC,UAAoD;AAChF,SAAO,UAAU,QAAQ,QAAQ;AACrC;AAEA,MAAM,uBAAuB,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACJ,MAIM;AACF,MAAI,aAAa,YAAY,aAAa,aAAa;AACnD,WAAO;AAAA,EACX;AAEA,QAAM,kBAAkB,OAAO,SAAS,EAAE,EAAE,KAAK;AAEjD,MAAI,CAAC,iBAAiB;AAClB,UAAM,IAAI,8BAA8B,oCAAoC;AAAA,EAChF;AAEA,MAAI,cAAc,YAAY,CAAC,OAAO,SAAS,OAAO,eAAe,CAAC,GAAG;AACrE,UAAM,IAAI,8BAA8B,8CAA8C;AAAA,EAC1F;AAEA,MAAI,cAAc,aAAa,oBAAoB,UAAU,oBAAoB,SAAS;AACtF,UAAM,IAAI,8BAA8B,sDAAsD;AAAA,EAClG;AAEA,MAAI,cAAc,QAAQ;AACtB,QAAI,CAAC,sBAAsB,KAAK,eAAe,GAAG;AAC9C,YAAM,IAAI,8BAA8B,kDAAkD;AAAA,IAC9F;AAEA,UAAM,OAAO,oBAAI,KAAK,GAAG,eAAe,gBAAgB;AAExD,QAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,KAAK,KAAK,YAAY,EAAE,MAAM,GAAG,EAAE,MAAM,iBAAiB;AACrF,YAAM,IAAI,8BAA8B,wCAAwC;AAAA,IACpF;AAAA,EACJ;AAEA,OAAK,aAAa,YAAY,aAAa,YAAY,cAAc,UAAU,cAAc,UAAU;AACnG,UAAM,IAAI,8BAA8B,6DAA6D;AAAA,EACzG;AAEA,MAAI,cAAc,OAAO;AACrB,WAAO,kBAAkB,eAAe;AAAA,EAC5C;AAEA,SAAO;AACX;AAEO,MAAM,+BAA+B,CAAC,YAA0D;AACnG,QAAM,oBAAoB,WAAW,CAAC;AAEtC,MAAI,kBAAkB,SAAS,2BAA2B;AACtD,UAAM,IAAI,8BAA8B,yBAAyB,yBAAyB,oBAAoB;AAAA,EAClH;AAEA,SAAO,kBACF,IAAI,CAAC,WAA4C;AAC9C,UAAM,MAAM,qBAAqB,OAAO,GAAG;AAC3C,UAAM,YAAY,OAAO;AACzB,UAAM,WAAW,OAAO;AAExB,QAAI,CAAC,oBAAoB,SAAS,GAAG;AACjC,YAAM,IAAI,8BAA8B,yCAAyC;AAAA,IACrF;AAEA,QAAI,CAAC,6BAA6B,QAAQ,GAAG;AACzC,YAAM,IAAI,8BAA8B,sCAAsC;AAAA,IAClF;AAEA,UAAM,aAAc,OAA8B;AAClD,UAAM,OAAO,OAAO,eAAe,YAAY,WAAW,KAAK,IAAI,WAAW,KAAK,IAAI;AAEvF,WAAO;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,qBAAqB;AAAA,QACxB,OAAO,OAAO;AAAA,QACd;AAAA,QACA;AAAA,MACJ,CAAC;AAAA,IACL;AAAA,EACJ,CAAC,EACA,OAAO,CAAC,WAA+C,WAAW,IAAI;AAC/E;AAEA,MAAM,uBAAuB,CAAC,UAAoD;AAC9E,MAAI,CAAC,OAAO;AACR,WAAO;AAAA,MACH,iBAAiB,CAAC;AAAA,MAClB,QAAQ;AAAA,MACR,WAAW;AAAA,IACf;AAAA,EACJ;AAEA,MAAI;AACA,UAAM,SAAS,KAAK,MAAM,KAAK;AAE/B,WAAO;AAAA,MACH,iBAAiB,6BAA6B,OAAO,mBAAmB,CAAC,CAAC;AAAA,MAC1E,QAAQ,oBAAoB,OAAO,MAAM;AAAA,MACzC,WAAW,uBAAuB,OAAO,SAAS;AAAA,IACtD;AAAA,EACJ,QAAQ;AACJ,WAAO;AAAA,MACH,iBAAiB,CAAC;AAAA,MAClB,QAAQ;AAAA,MACR,WAAW;AAAA,IACf;AAAA,EACJ;AACJ;AAEA,MAAM,2BAA2B,CAAC,EAAE,iBAAiB,QAAQ,UAAU,MAAiC;AACpG,SAAO,KAAK,UAAU;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EACJ,CAAC;AACL;AAEO,MAAM,wBAAwB,CAAC,UAA8B;AAChE,QAAM,eAAe,OAAO,UAAU,WAAW,QAAQ,OAAO;AAEhE,MAAI,CAAC,OAAO,UAAU,YAAY,GAAG;AACjC,WAAO;AAAA,EACX;AAEA,SAAO,KAAK,IAAI,wBAAwB,KAAK,IAAI,wBAAwB,YAAY,CAAC;AAC1F;AAEO,MAAM,wBAAwB,CAAC,UAAkB;AACpD,QAAM,eAAe,MAAM,KAAK;AAEhC,SAAO,gBAAgB;AAC3B;AAEA,MAAM,2BAA2B,CAAC,UAAoB,oBAAgD;AAClG,MAAI,SAAS,SAAS,GAAG;AACrB,WAAO,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,KAAK;AAAA,EAC1C;AAEA,MAAI,gBAAgB,SAAS,GAAG;AAC5B,WAAO,gBACF,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,WAAW,OAAO,IAAI,EAC3B,KAAK,KAAK;AAAA,EACnB;AAEA,SAAO;AACX;AAEO,MAAM,4BAA4B,CAAC,UAA4B;AAClE,QAAM,WAAW,sBAAsB,MAAM,YAAY,CAAC,CAAC;AAC3D,QAAM,kBAAkB,6BAA6B,MAAM,eAAe;AAC1E,QAAM,eAAe,MAAM,OAAO,KAAK,KAAK;AAC5C,QAAM,SAAS,oBAAoB,MAAM,MAAM;AAC/C,QAAM,YAAY,uBAAuB,MAAM,SAAS;AAExD,SAAO;AAAA,IACH,OAAO,gBAAgB,yBAAyB,UAAU,eAAe;AAAA,IACzE,aAAa,yBAAyB,MAAM,WAAW;AAAA,IACvD;AAAA,IACA,MAAM,MAAM,SAAS,OAAO,OAAO;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,sBAAsB,MAAM,KAAK;AAAA,EAC5C;AAUJ;AAEO,MAAM,+BAA+B,CAAC,UAAqD;AAC9F,SAAO;AAAA,IACH,UAAU,sBAAsB,MAAM,YAAY,CAAC,CAAC;AAAA,IACpD,MAAM,MAAM,SAAS,OAAO,OAAO;AAAA,IACnC,iBAAiB,6BAA6B,MAAM,eAAe;AAAA,IACnE,QAAQ,oBAAoB,MAAM,MAAM;AAAA,IACxC,WAAW,uBAAuB,MAAM,SAAS;AAAA,EACrD;AACJ;AAEO,MAAM,+BAA+B,CAAC,eAAqD;AAC9F,QAAM,eAAe,OAAO,YAAY,SAAS,8BAA8B;AAC/E,QAAM,QAAQ,OAAO,UAAU,YAAY,IACrC,KAAK,IAAI,4BAA4B,KAAK,IAAI,GAAG,YAAY,CAAC,IAC9D;AACN,QAAM,gBAAgB,OAAO,YAAY,UAAU,CAAC;AACpD,QAAM,SAAS,OAAO,UAAU,aAAa,IAAI,KAAK,IAAI,GAAG,aAAa,IAAI;AAE9E,SAAO,EAAE,OAAO,OAAO;AAC3B;AAEO,MAAM,0BAA0B,CAAC,QAAkB,cAAsB,uBAAsC;AAClH,QAAM,kBAAkB,OAAO,OAAO,CAAC,UAAU,UAAU,YAAY;AAEvE,MAAI,gBAAgB,WAAW,GAAG;AAC9B,WAAO;AAAA,EACX;AAEA,MAAI,uBAAuB,cAAc;AACrC,WAAO;AAAA,EACX;AAEA,SAAO,gBAAgB,CAAC,KAAK;AACjC;AAEA,MAAM,wBAAwB,CAAC,YAAsB,YAAsB;AACvE,MAAI,WAAW,WAAW,QAAQ,QAAQ;AACtC,UAAM,IAAI,MAAM,uDAAuD;AAAA,EAC3E;AAEA,QAAM,eAAe,IAAI,IAAI,UAAU;AACvC,QAAM,YAAY,IAAI,IAAI,OAAO;AAEjC,MAAI,aAAa,SAAS,WAAW,UAAU,UAAU,SAAS,QAAQ,QAAQ;AAC9E,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC7D;AAEA,aAAW,MAAM,cAAc;AAC3B,QAAI,CAAC,UAAU,IAAI,EAAE,GAAG;AACpB,YAAM,IAAI,MAAM,kDAAkD;AAAA,IACtE;AAAA,EACJ;AACJ;AAEA,MAAM,cAAc,CAAC,OAAe;AAChC,QAAM,YAAY,OAAO,EAAE;AAE3B,MAAI,CAAC,OAAO,UAAU,SAAS,KAAK,aAAa,GAAG;AAChD,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC7C;AAEA,SAAO;AACX;AAEA,MAAM,uBAAuB,CAAC,YAA8C;AACxE,QAAM,QAAQ,qBAAqB,QAAQ,KAAK;AAEhD,SAAO;AAAA,IACH,IAAI,OAAO,QAAQ,EAAE;AAAA,IACrB,OAAO,OAAO,QAAQ,KAAK;AAAA,IAC3B,OAAO,QAAQ;AAAA,IACf,aAAa,yBAAyB,QAAQ,WAA8B;AAAA,IAC5E,UAAU,QAAQ,KAAK,IAAI,CAAC,QAAQ,IAAI,IAAI;AAAA,IAC5C,MAAM,QAAQ;AAAA,IACd,iBAAiB,MAAM;AAAA,IACvB,QAAQ,MAAM;AAAA,IACd,WAAW,MAAM;AAAA,IACjB,OAAO,QAAQ;AAAA,IACf,OAAO,QAAQ;AAAA,EACnB;AACJ;AAEA,MAAM,mBAAmB,CAAC,SAAmC;AAAA,EACzD,IAAI,OAAO,IAAI,EAAE;AAAA,EACjB,OAAO,IAAI;AAAA,EACX,OAAO,IAAI;AAAA,EACX,UAAU,IAAI,SAAS,IAAI,oBAAoB;AACnD;AAEA,MAAM,qBAAqB,OAAO,OAAqB;AACnD,SAAO,GAAG,QAAQ,SAAS;AAAA,IACvB,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,SAAS;AAAA,EACb,CAAC;AACL;AAEA,MAAM,sBAAsB,OAAO,OAAqB;AACpD,SAAO,GAAG,cAAc,OAAO;AAAA,IAC3B,OAAO,EAAE,IAAI,kBAAkB;AAAA,IAC/B,QAAQ,CAAC;AAAA,IACT,QAAQ,EAAE,IAAI,kBAAkB;AAAA,EACpC,CAAC;AACL;AAEA,MAAM,oBAAoB,OAAO,OAAmD;AAChF,QAAM,CAAC,WAAW,IAAI,IAAI,MAAM,QAAQ,IAAI,CAAC,oBAAoB,EAAE,GAAG,mBAAmB,EAAE,CAAC,CAAC;AAE7F,QAAM,cACF,UAAU,gBAAgB,QAAQ,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,UAAU,WAAW,IAC/E,OAAO,UAAU,WAAW,IAC5B,KAAK,CAAC,IACJ,OAAO,KAAK,CAAC,EAAE,EAAE,IACjB;AAEZ,SAAO;AAAA,IACH;AAAA,IACA,MAAM,KAAK,IAAI,gBAAgB;AAAA,EACnC;AACJ;AAEA,MAAM,kBAAkB,OAAO,IAAkB,OAAkD;AAC/F,QAAM,UAAU,MAAM,GAAG,YAAY,WAAW;AAAA,IAC5C,OAAO,EAAE,GAAG;AAAA,IACZ,SAAS;AAAA,EACb,CAAC;AAED,SAAO,UAAU,qBAAqB,OAAO,IAAI;AACrD;AAEO,MAAM,yBAAyB,OAClC,IACA,SACA,UAA+C,CAAC,MAC/C;AACD,MAAI,QAAQ,WAAW,GAAG;AACtB,WAAO,CAAC;AAAA,EACZ;AAEA,QAAM,cAAc,MAAM,GAAG,mBAAmB,SAAS;AAAA,IACrD,OAAO,EAAE,KAAK,EAAE,IAAI,QAAQ,IAAI,CAAC,WAAW,OAAO,GAAG,EAAE,EAAE;AAAA,IAC1D,QAAQ;AAAA,MACJ,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX,SAAS;AAAA,QACL,QAAQ;AAAA,UACJ,OAAO;AAAA,QACX;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACD,QAAM,kBAAkB,IAAI,IAAI,YAAY,IAAI,CAAC,eAAe,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC;AAE7F,SAAO,QAAQ,IAAI,CAAC,WAAW;AAC3B,UAAM,aAAa,gBAAgB,IAAI,OAAO,GAAG;AAEjD,QAAI,CAAC,YAAY;AACb,YAAM,IAAI,8BAA8B,YAAY,OAAO,GAAG,kBAAkB;AAAA,IACpF;AAEA,QAAI,WAAW,cAAc,OAAO,WAAW;AAC3C,YAAM,IAAI,8BAA8B,YAAY,OAAO,GAAG,SAAS,WAAW,SAAS,UAAU;AAAA,IACzG;AAEA,QACI,QAAQ,yBACR,OAAO,cAAc,YACrB,OAAO,aAAa,YACpB,OAAO,aAAa,aACtB;AACE,YAAM,cAAc,2BAA2B,OAAO,SAAS,EAAE;AAEjE,UAAI,CAAC,WAAW,QAAQ,KAAK,CAAC,WAAW,OAAO,UAAU,WAAW,GAAG;AACpE,cAAM,IAAI,8BAA8B,YAAY,OAAO,GAAG,WAAW,WAAW,kBAAkB;AAAA,MAC1G;AAAA,IACJ;AAEA,WAAO;AAAA,MACH,GAAG;AAAA,MACH,MAAM,WAAW;AAAA,IACrB;AAAA,EACJ,CAAC;AACL;AAEA,MAAM,uBAAuB,OAAO,IAAkB,YAA0D;AAC5G,QAAM,kBAAkB,MAAM,uBAAuB,IAAI,QAAQ,iBAAiB,EAAE,uBAAuB,KAAK,CAAC;AAEjH,SAAO,yBAAyB;AAAA,IAC5B;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,WAAW,QAAQ;AAAA,EACvB,CAAC;AACL;AAEA,MAAM,kBAAkB,OAAO,OAAqB;AAChD,QAAM,UAAU,MAAM,GAAG,QAAQ,UAAU;AAAA,IACvC,SAAS,CAAC,EAAE,OAAO,OAAO,GAAG,EAAE,WAAW,OAAO,CAAC;AAAA,IAClD,QAAQ,EAAE,OAAO,KAAK;AAAA,EAC1B,CAAC;AAED,SAAO,UAAU,QAAQ,QAAQ,IAAI;AACzC;AAEA,MAAM,sBAAsB,OAAO,IAAkB,UAAkB;AACnE,QAAM,cAAc,MAAM,GAAG,YAAY,UAAU;AAAA,IAC/C,OAAO,EAAE,MAAM;AAAA,IACf,SAAS,CAAC,EAAE,OAAO,OAAO,GAAG,EAAE,WAAW,OAAO,CAAC;AAAA,IAClD,QAAQ,EAAE,OAAO,KAAK;AAAA,EAC1B,CAAC;AAED,SAAO,cAAc,YAAY,QAAQ,IAAI;AACjD;AAEA,MAAM,qBAAqB,OAAO,OAAqB;AACnD,QAAM,OAAO,MAAM,GAAG,QAAQ,SAAS;AAAA,IACnC,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,QAAQ,EAAE,IAAI,KAAK;AAAA,EACvB,CAAC;AAED,QAAM,QAAQ;AAAA,IACV,KAAK;AAAA,MAAI,CAAC,KAAK,UACX,GAAG,QAAQ,OAAO;AAAA,QACd,OAAO,EAAE,IAAI,IAAI,GAAG;AAAA,QACpB,MAAM,EAAE,OAAO,MAAM;AAAA,MACzB,CAAC;AAAA,IACL;AAAA,EACJ;AACJ;AAEA,MAAM,yBAAyB,OAAO,IAAkB,UAAkB;AACtE,QAAM,WAAW,MAAM,GAAG,YAAY,SAAS;AAAA,IAC3C,OAAO,EAAE,MAAM;AAAA,IACf,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,IAChD,QAAQ,EAAE,IAAI,KAAK;AAAA,EACvB,CAAC;AAED,QAAM,QAAQ;AAAA,IACV,SAAS;AAAA,MAAI,CAAC,SAAS,UACnB,GAAG,YAAY,OAAO;AAAA,QAClB,OAAO,EAAE,IAAI,QAAQ,GAAG;AAAA,QACxB,MAAM,EAAE,OAAO,MAAM;AAAA,MACzB,CAAC;AAAA,IACL;AAAA,EACJ;AACJ;AAEO,MAAM,mBAAmB,YAAY;AACxC,SAAO,kBAAkB,MAAM;AACnC;AAEO,MAAM,qBAAqB,OAAO,OAAe;AACpD,SAAO,gBAAgB,QAAQ,YAAY,EAAE,CAAC;AAClD;AAEA,MAAM,6BAA6B,CAAC,UAAkB;AAClD,SAAO,MAAM,KAAK,EAAE,YAAY,EAAE,QAAQ,QAAQ,GAAG;AACzD;AAEA,MAAM,gCAAgC,CAAC,WAAoE;AACvG,UAAQ,OAAO,WAAW;AAAA,IACtB,KAAK,UAAU;AACX,YAAM,cAAc,OAAO,OAAO,KAAK;AAEvC,UAAI,OAAO,aAAa,UAAU;AAC9B,eAAO,EAAE,aAAa,EAAE,IAAI,YAAY,EAAE;AAAA,MAC9C;AAEA,UAAI,OAAO,aAAa,SAAS;AAC7B,eAAO,EAAE,aAAa,EAAE,IAAI,YAAY,EAAE;AAAA,MAC9C;AAEA,aAAO,EAAE,YAAY;AAAA,IACzB;AAAA,IACA,KAAK,QAAQ;AACT,YAAM,YAAY,oBAAI,KAAK,GAAG,OAAO,KAAK,gBAAgB;AAE1D,UAAI,OAAO,aAAa,UAAU;AAC9B,eAAO,EAAE,WAAW,EAAE,IAAI,UAAU,EAAE;AAAA,MAC1C;AAEA,UAAI,OAAO,aAAa,SAAS;AAC7B,eAAO,EAAE,WAAW,EAAE,IAAI,UAAU,EAAE;AAAA,MAC1C;AAEA,aAAO,EAAE,UAAU;AAAA,IACvB;AAAA,IACA,KAAK;AACD,aAAO,EAAE,WAAW,OAAO,UAAU,OAAO;AAAA,IAChD,KAAK;AACD,aAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,2BAA2B,OAAO,SAAS,EAAE,EAAE,EAAE,EAAE;AAAA,IACvF,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AACI,aAAO,EAAE,qBAAqB,OAAO,OAAO,YAAY,KAAK,GAAG;AAAA,EACxE;AACJ;AAEO,MAAM,2BAA2B,CAAC,WAA4D;AACjG,QAAM,kBAAkB;AAAA,IACpB,YAAY;AAAA,MACR,IAAI;AAAA,QACA,KAAK,OAAO;AAAA,MAChB;AAAA,IACJ;AAAA,EACJ;AAEA,MAAI,OAAO,aAAa,aAAa;AACjC,WAAO;AAAA,MACH,YAAY;AAAA,QACR,MAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AAEA,MAAI,OAAO,aAAa,UAAU;AAC9B,WAAO;AAAA,MACH,YAAY;AAAA,QACR,MAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AAAA,IACH,YAAY;AAAA,MACR,MAAM;AAAA,QACF,GAAG;AAAA,QACH,GAAG,8BAA8B,MAAM;AAAA,MAC3C;AAAA,IACJ;AAAA,EACJ;AACJ;AAEO,MAAM,sBAAsB,CAC/B,UACwB;AACxB,QAAM,UAAmC,CAAC;AAE1C,MAAI,MAAM,SAAS,SAAS,GAAG;AAC3B,YAAQ,KAAK,uBAAuB,MAAM,UAAU,MAAM,IAAwB,CAAC;AAAA,EACvF;AAEA,aAAW,UAAU,MAAM,iBAAiB;AACxC,YAAQ,KAAK,yBAAyB,MAAM,CAAC;AAAA,EACjD;AAEA,MAAI,QAAQ,WAAW,GAAG;AACtB,WAAO,CAAC;AAAA,EACZ;AAEA,SAAO,EAAE,KAAK,QAAQ;AAC1B;AAEO,MAAM,wBAAwB,CAAC,YAAsD;AACxF,SAAO,oBAAoB,OAAO;AACtC;AAEA,MAAM,wBAAwB,CAC1B,UACwC;AACxC,SAAO,CAAC,EAAE,CAAC,MAAM,MAAM,GAAG,MAAM,UAAU,GAAG,EAAE,IAAI,MAAM,CAAC;AAC9D;AAEA,MAAM,0BAA0B,CAAC,YAAsE;AACnG,SAAO,sBAAsB,OAAO;AACxC;AAEO,MAAM,sBAAsB,OAC/B,IACA,eAIyC;AACzC,QAAM,UAAU,MAAM,OAAO,YAAY,WAAW;AAAA,IAChD,OAAO,EAAE,IAAI,YAAY,EAAE,EAAE;AAAA,IAC7B,SAAS;AAAA,EACb,CAAC;AAED,MAAI,CAAC,SAAS;AACV,WAAO;AAAA,EACX;AAEA,QAAM,oBAAoB,qBAAqB,OAAO;AACtD,QAAM,QAAQ,sBAAsB,iBAAiB;AAErD,QAAM,CAAC,YAAY,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC1C,OAAO,KAAK,MAAM,EAAE,MAAM,CAAC;AAAA,IAC3B,OAAO,KAAK,SAAS;AAAA,MACjB,SAAS,wBAAwB,iBAAiB;AAAA,MAClD;AAAA,MACA,MAAM,OAAO,WAAW,KAAK;AAAA,MAC7B,MAAM,OAAO,WAAW,MAAM;AAAA,IAClC,CAAC;AAAA,EACL,CAAC;AAED,SAAO;AAAA,IACH;AAAA,IACA;AAAA,EACJ;AACJ;AAEO,MAAM,uBAAuB,OAChC,OACA,eAIkC;AAClC,QAAM,kBAAkB,6BAA6B,KAAK;AAE1D,MAAI,gBAAgB,gBAAgB,WAAW,GAAG;AAC9C,UAAM,IAAI,8BAA8B,2CAA2C;AAAA,EACvF;AAEA,QAAM,QAAQ;AAAA,IACV,GAAG;AAAA,IACH,iBAAiB,MAAM,uBAAuB,QAAQ,gBAAgB,iBAAiB;AAAA,MACnF,uBAAuB;AAAA,IAC3B,CAAC;AAAA,EACL;AACA,QAAM,uBAAuB,6BAA6B,UAAU;AACpE,QAAM,QAAQ,oBAAoB,KAAK;AAEvC,QAAM,CAAC,YAAY,KAAK,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC1C,OAAO,KAAK,MAAM,EAAE,MAAM,CAAC;AAAA,IAC3B,OAAO,KAAK,SAAS;AAAA,MACjB,SAAS,sBAAsB,KAAK;AAAA,MACpC;AAAA,MACA,MAAM,qBAAqB;AAAA,MAC3B,MAAM,qBAAqB;AAAA,IAC/B,CAAC;AAAA,EACL,CAAC;AAED,SAAO;AAAA,IACH;AAAA,IACA;AAAA,EACJ;AACJ;AAEO,MAAM,gBAAgB,OAAO,UAAkB;AAClD,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,YAAY,MAAM,oBAAoB,EAAE;AAC9C,UAAM,eAAe,MAAM,gBAAgB,EAAE;AAC7C,UAAM,aAAa,MAAM,GAAG,QAAQ,OAAO;AAAA,MACvC,MAAM;AAAA,QACF,OAAO,sBAAsB,KAAK;AAAA,QAClC,OAAO;AAAA,MACX;AAAA,MACA,SAAS;AAAA,IACb,CAAC;AAED,QAAI,UAAU,gBAAgB,MAAM;AAChC,YAAM,GAAG,cAAc,OAAO;AAAA,QAC1B,OAAO,EAAE,IAAI,kBAAkB;AAAA,QAC/B,MAAM,EAAE,aAAa,WAAW,GAAG;AAAA,MACvC,CAAC;AAAA,IACL;AAEA,WAAO,iBAAiB,UAAU;AAAA,EACtC,CAAC;AACL;AAEO,MAAM,gBAAgB,OAAO,IAAY,UAAkB;AAC9D,QAAM,aAAa,MAAM,OAAO,QAAQ,OAAO;AAAA,IAC3C,OAAO,EAAE,IAAI,YAAY,EAAE,EAAE;AAAA,IAC7B,MAAM;AAAA,MACF,OAAO,sBAAsB,KAAK;AAAA,IACtC;AAAA,IACA,SAAS;AAAA,EACb,CAAC;AAED,SAAO,iBAAiB,UAAU;AACtC;AAEO,MAAM,gBAAgB,OAAO,OAAe;AAC/C,QAAM,QAAQ,YAAY,EAAE;AAE5B,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,YAAY,MAAM,oBAAoB,EAAE;AAC9C,UAAM,OAAO,MAAM,GAAG,QAAQ,SAAS;AAAA,MACnC,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,MAChD,QAAQ,EAAE,IAAI,KAAK;AAAA,IACvB,CAAC;AAED,QAAI,CAAC,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,KAAK,GAAG;AACvC,aAAO;AAAA,IACX;AAEA,UAAM,GAAG,QAAQ,OAAO,EAAE,OAAO,EAAE,IAAI,MAAM,EAAE,CAAC;AAChD,UAAM,mBAAmB,EAAE;AAE3B,UAAM,kBAAkB;AAAA,MACpB,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,MACxB;AAAA,MACA,UAAU;AAAA,IACd;AAEA,UAAM,GAAG,cAAc,OAAO;AAAA,MAC1B,OAAO,EAAE,IAAI,kBAAkB;AAAA,MAC/B,MAAM,EAAE,aAAa,gBAAgB;AAAA,IACzC,CAAC;AAED,WAAO;AAAA,EACX,CAAC;AACL;AAEO,MAAM,mBAAmB,OAAO,OAAe;AAClD,QAAM,QAAQ,YAAY,EAAE;AAE5B,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,YAAY,MAAM,oBAAoB,EAAE;AAC9C,UAAM,MAAM,MAAM,GAAG,QAAQ,WAAW;AAAA,MACpC,OAAO,EAAE,IAAI,MAAM;AAAA,MACnB,QAAQ,EAAE,IAAI,KAAK;AAAA,IACvB,CAAC;AAED,QAAI,CAAC,KAAK;AACN,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACzC;AAEA,UAAM,GAAG,cAAc,OAAO;AAAA,MAC1B,OAAO,EAAE,IAAI,UAAU,GAAG;AAAA,MAC1B,MAAM,EAAE,aAAa,MAAM;AAAA,IAC/B,CAAC;AAED,WAAO,kBAAkB,EAAE;AAAA,EAC/B,CAAC;AACL;AAEO,MAAM,kBAAkB,OAAO,WAAqB;AACvD,QAAM,aAAa,OAAO,IAAI,WAAW;AAEzC,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,OAAO,MAAM,GAAG,QAAQ,SAAS;AAAA,MACnC,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,MAChD,QAAQ,EAAE,IAAI,KAAK;AAAA,IACvB,CAAC;AACD,UAAM,gBAAgB,KAAK,IAAI,CAAC,QAAQ,IAAI,EAAE;AAE9C,0BAAsB,eAAe,UAAU;AAE/C,UAAM,QAAQ;AAAA,MACV,WAAW;AAAA,QAAI,CAAC,OAAO,UACnB,GAAG,QAAQ,OAAO;AAAA,UACd,OAAO,EAAE,IAAI,MAAM;AAAA,UACnB,MAAM,EAAE,OAAO,MAAM;AAAA,QACzB,CAAC;AAAA,MACL;AAAA,IACJ;AAEA,UAAM,gBAAgB,MAAM,mBAAmB,EAAE;AACjD,WAAO,cAAc,IAAI,gBAAgB;AAAA,EAC7C,CAAC;AACL;AAEO,MAAM,oBAAoB,OAAO,OAAe,UAA4B;AAC/E,QAAM,eAAe,YAAY,KAAK;AACtC,QAAM,cAAc,0BAA0B,KAAK;AAEnD,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,MAAM,MAAM,GAAG,QAAQ,WAAW;AAAA,MACpC,OAAO,EAAE,IAAI,aAAa;AAAA,MAC1B,QAAQ,EAAE,IAAI,KAAK;AAAA,IACvB,CAAC;AAED,QAAI,CAAC,KAAK;AACN,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACzC;AAEA,UAAM,mBAAmB,MAAM,oBAAoB,IAAI,YAAY;AACnE,UAAM,QAAQ,MAAM,qBAAqB,IAAI,WAAW;AAExD,UAAM,iBAAiB,MAAM,GAAG,YAAY,OAAO;AAAA,MAC/C,MAAM;AAAA,QACF,OAAO;AAAA,QACP,OAAO,YAAY;AAAA,QACnB,aAAa,YAAY;AAAA,QACzB;AAAA,QACA,MAAM,YAAY;AAAA,QAClB,OAAO,YAAY;AAAA,QACnB,OAAO;AAAA,QACP,MAAM;AAAA,UACF,QAAQ,YAAY,SAAS,IAAI,CAAC,SAAS,WAAW;AAAA,YAClD,MAAM;AAAA,YACN,OAAO;AAAA,UACX,EAAE;AAAA,QACN;AAAA,MACJ;AAAA,MACA,SAAS;AAAA,IACb,CAAC;AAED,WAAO,qBAAqB,cAAc;AAAA,EAC9C,CAAC;AACL;AAEO,MAAM,oBAAoB,OAAO,IAAY,UAA4B;AAC5E,QAAM,YAAY,YAAY,EAAE;AAChC,QAAM,cAAc,0BAA0B,KAAK;AAEnD,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,QAAQ,MAAM,qBAAqB,IAAI,WAAW;AAExD,UAAM,iBAAiB,MAAM,GAAG,YAAY,OAAO;AAAA,MAC/C,OAAO,EAAE,IAAI,UAAU;AAAA,MACvB,MAAM;AAAA,QACF,OAAO,YAAY;AAAA,QACnB,aAAa,YAAY;AAAA,QACzB;AAAA,QACA,MAAM,YAAY;AAAA,QAClB,OAAO,YAAY;AAAA,QACnB,MAAM;AAAA,UACF,YAAY,CAAC;AAAA,UACb,QAAQ,YAAY,SAAS,IAAI,CAAC,SAAS,WAAW;AAAA,YAClD,MAAM;AAAA,YACN,OAAO;AAAA,UACX,EAAE;AAAA,QACN;AAAA,MACJ;AAAA,MACA,SAAS;AAAA,IACb,CAAC;AAED,WAAO,qBAAqB,cAAc;AAAA,EAC9C,CAAC;AACL;AAEO,MAAM,oBAAoB,OAAO,OAAe;AACnD,QAAM,YAAY,YAAY,EAAE;AAEhC,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,UAAU,MAAM,GAAG,YAAY,WAAW;AAAA,MAC5C,OAAO,EAAE,IAAI,UAAU;AAAA,MACvB,QAAQ,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,IACpC,CAAC;AAED,QAAI,CAAC,SAAS;AACV,aAAO;AAAA,IACX;AAEA,UAAM,GAAG,YAAY,OAAO;AAAA,MACxB,OAAO,EAAE,IAAI,UAAU;AAAA,IAC3B,CAAC;AACD,UAAM,uBAAuB,IAAI,QAAQ,KAAK;AAE9C,WAAO;AAAA,EACX,CAAC;AACL;AAEO,MAAM,sBAAsB,OAAO,OAAe,eAAyB;AAC9E,QAAM,eAAe,YAAY,KAAK;AACtC,QAAM,iBAAiB,WAAW,IAAI,WAAW;AAEjD,SAAO,OAAO,aAAa,OAAO,OAAO;AACrC,UAAM,WAAW,MAAM,GAAG,YAAY,SAAS;AAAA,MAC3C,OAAO,EAAE,OAAO,aAAa;AAAA,MAC7B,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,MAChD,QAAQ,EAAE,IAAI,KAAK;AAAA,IACvB,CAAC;AACD,UAAM,oBAAoB,SAAS,IAAI,CAAC,YAAY,QAAQ,EAAE;AAE9D,0BAAsB,mBAAmB,cAAc;AAEvD,UAAM,QAAQ;AAAA,MACV,eAAe;AAAA,QAAI,CAAC,WAAW,UAC3B,GAAG,YAAY,OAAO;AAAA,UAClB,OAAO,EAAE,IAAI,UAAU;AAAA,UACvB,MAAM,EAAE,OAAO,MAAM;AAAA,QACzB,CAAC;AAAA,MACL;AAAA,IACJ;AAEA,UAAM,oBAAoB,MAAM,GAAG,YAAY,SAAS;AAAA,MACpD,OAAO,EAAE,OAAO,aAAa;AAAA,MAC7B,SAAS,CAAC,EAAE,OAAO,MAAM,GAAG,EAAE,WAAW,MAAM,CAAC;AAAA,MAChD,SAAS;AAAA,IACb,CAAC;AAED,WAAO,kBAAkB,IAAI,oBAAoB;AAAA,EACrD,CAAC;AACL;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/features/view/services/workspace.ts"],"sourcesContent":["import type { Note, Prisma, PropertyValueType } from '@prisma/client';\nimport {\n InvalidNotePropertyInputError,\n normalizePropertyKey,\n normalizeUrlValue,\n} from '~/features/note/services/properties.js';\nimport { buildNoteTagNamesWhere, type NoteTagMatchMode } from '~/features/note/services/tag-filter.js';\nimport models from '~/models.js';\n\nexport type ViewTagMatchMode = NoteTagMatchMode;\nexport type ViewDisplayType = 'list' | 'table' | 'calendar';\nexport type ViewTableColumn = 'title' | 'tags' | 'properties' | 'createdAt' | 'updatedAt';\nexport type ViewPropertyFilterOperator =\n | 'equals'\n | 'notEquals'\n | 'contains'\n | 'notContains'\n | 'before'\n | 'after'\n | 'exists'\n | 'notExists';\nexport type ViewSortBy = 'updatedAt' | 'createdAt' | 'title';\nexport type ViewSortOrder = 'asc' | 'desc';\n\nexport interface ViewDisplayOptionsRecord {\n tableColumns: ViewTableColumn[];\n}\n\nexport interface ViewPropertyFilterRecord {\n key: string;\n name: string;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n value: string | null;\n}\n\nexport interface ViewSectionRecord {\n id: string;\n tabId: string;\n title: string;\n displayType: ViewDisplayType;\n displayOptions: ViewDisplayOptionsRecord;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n order: number;\n}\n\nexport interface ViewTabRecord {\n id: string;\n title: string;\n order: number;\n sections: ViewSectionRecord[];\n}\n\nexport interface ViewWorkspaceRecord {\n activeTabId: string | null;\n tabs: ViewTabRecord[];\n}\n\nexport interface ViewSectionInput {\n title?: string;\n displayType?: ViewDisplayType;\n displayOptions?: ViewDisplayOptionsInput | null;\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n limit?: number;\n}\n\nexport interface ViewNotesQueryInput {\n tagNames?: string[] | null;\n mode?: ViewTagMatchMode;\n propertyFilters?: ViewPropertyFilterInput[] | null;\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n}\n\nexport interface ViewNotesQueryRecord {\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n}\n\nexport interface ViewPropertyFilterInput {\n key: string;\n operator: ViewPropertyFilterOperator;\n value?: string | null;\n valueType?: PropertyValueType | null;\n}\n\nexport interface ViewDisplayOptionsInput {\n tableColumns?: ViewTableColumn[] | null;\n}\n\nexport interface ViewSectionNotesResult {\n totalCount: number;\n notes: Note[];\n}\n\nconst VIEW_WORKSPACE_ID = 1;\n\nexport const DEFAULT_VIEW_SECTION_LIMIT = 5;\nexport const MIN_VIEW_SECTION_LIMIT = 1;\nexport const MAX_VIEW_SECTION_LIMIT = 20;\nexport const DEFAULT_VIEW_NOTES_QUERY_LIMIT = 20;\nexport const MAX_VIEW_NOTES_QUERY_LIMIT = 50;\nconst MAX_VIEW_PROPERTY_FILTERS = 10;\nconst DEFAULT_VIEW_DISPLAY_TYPE: ViewDisplayType = 'list';\nconst DEFAULT_VIEW_SORT_BY: ViewSortBy = 'updatedAt';\nconst DEFAULT_VIEW_SORT_ORDER: ViewSortOrder = 'desc';\nconst DEFAULT_VIEW_TABLE_COLUMNS: ViewTableColumn[] = ['title', 'tags', 'properties', 'createdAt', 'updatedAt'];\n\ntype ViewDbClient = typeof models | Prisma.TransactionClient;\n\nconst orderedViewSectionTagsInclude = {\n tags: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n },\n} satisfies Prisma.ViewSectionInclude;\n\nconst orderedViewTabSectionsInclude = {\n sections: {\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n },\n} satisfies Prisma.ViewTabInclude;\n\ntype DbViewSection = Prisma.ViewSectionGetPayload<{\n include: typeof orderedViewSectionTagsInclude;\n}>;\n\ntype DbViewTab = Prisma.ViewTabGetPayload<{\n include: typeof orderedViewTabSectionsInclude;\n}>;\n\nconst normalizeTagName = (value: string) => {\n const trimmedValue = value.trim();\n\n if (!trimmedValue) {\n return '';\n }\n\n if (trimmedValue.startsWith('@')) {\n return trimmedValue;\n }\n\n if (trimmedValue.startsWith('#')) {\n return `@${trimmedValue.slice(1)}`;\n }\n\n return `@${trimmedValue}`;\n};\n\nexport const normalizeViewTagNames = (values: string[]) => {\n const normalizedTagNames = values.flatMap((value) => value.split(','));\n\n return Array.from(new Set(normalizedTagNames.map(normalizeTagName).filter(Boolean)));\n};\n\ninterface StoredViewQuery {\n propertyFilters?: ViewPropertyFilterRecord[];\n sortBy?: ViewSortBy;\n sortOrder?: ViewSortOrder;\n displayOptions?: Partial<ViewDisplayOptionsRecord>;\n}\n\ninterface ParsedStoredViewQuery {\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n displayOptions: ViewDisplayOptionsRecord;\n}\n\nconst isViewPropertyFilterOperator = (value: unknown): value is ViewPropertyFilterOperator => {\n return (\n value === 'equals' ||\n value === 'notEquals' ||\n value === 'contains' ||\n value === 'notContains' ||\n value === 'before' ||\n value === 'after' ||\n value === 'exists' ||\n value === 'notExists'\n );\n};\n\nconst isPropertyValueType = (value: unknown): value is PropertyValueType => {\n return (\n value === 'text' ||\n value === 'url' ||\n value === 'number' ||\n value === 'date' ||\n value === 'boolean' ||\n value === 'select'\n );\n};\n\nconst isViewTableColumn = (value: unknown): value is ViewTableColumn => {\n return (\n value === 'title' ||\n value === 'tags' ||\n value === 'properties' ||\n value === 'createdAt' ||\n value === 'updatedAt'\n );\n};\n\nconst normalizeViewDisplayType = (value: ViewDisplayType | undefined): ViewDisplayType => {\n if (value === 'table' || value === 'calendar') {\n return value;\n }\n\n return DEFAULT_VIEW_DISPLAY_TYPE;\n};\n\nconst normalizeViewSortBy = (value: ViewSortBy | undefined): ViewSortBy => {\n return value === 'createdAt' || value === 'title' ? value : DEFAULT_VIEW_SORT_BY;\n};\n\nconst normalizeViewSortOrder = (value: ViewSortOrder | undefined): ViewSortOrder => {\n return value === 'asc' ? 'asc' : DEFAULT_VIEW_SORT_ORDER;\n};\n\nexport const normalizeViewTableColumns = (columns: ViewTableColumn[] | null | undefined): ViewTableColumn[] => {\n const normalizedColumns = (columns ?? []).filter(isViewTableColumn);\n const uniqueColumns = Array.from(new Set(normalizedColumns));\n\n if (uniqueColumns.length === 0) {\n return [...DEFAULT_VIEW_TABLE_COLUMNS];\n }\n\n return uniqueColumns.includes('title') ? uniqueColumns : ['title' as const, ...uniqueColumns];\n};\n\nexport const normalizeViewDisplayOptions = (\n options: ViewDisplayOptionsInput | Partial<ViewDisplayOptionsRecord> | null | undefined,\n): ViewDisplayOptionsRecord => {\n return {\n tableColumns: normalizeViewTableColumns(options?.tableColumns),\n };\n};\n\nconst normalizeFilterValue = ({\n value,\n valueType,\n operator,\n}: {\n value?: string | null;\n valueType: PropertyValueType;\n operator: ViewPropertyFilterOperator;\n}) => {\n if (operator === 'exists' || operator === 'notExists') {\n return null;\n }\n\n const normalizedValue = String(value ?? '').trim();\n\n if (!normalizedValue) {\n throw new InvalidNotePropertyInputError('Property filter value is required.');\n }\n\n if (valueType === 'number' && !Number.isFinite(Number(normalizedValue))) {\n throw new InvalidNotePropertyInputError('Number property filter value must be finite.');\n }\n\n if (valueType === 'boolean' && normalizedValue !== 'true' && normalizedValue !== 'false') {\n throw new InvalidNotePropertyInputError('Boolean property filter value must be true or false.');\n }\n\n if (valueType === 'date') {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(normalizedValue)) {\n throw new InvalidNotePropertyInputError('Date property filter values must use YYYY-MM-DD.');\n }\n\n const date = new Date(`${normalizedValue}T00:00:00.000Z`);\n\n if (Number.isNaN(date.getTime()) || date.toISOString().slice(0, 10) !== normalizedValue) {\n throw new InvalidNotePropertyInputError('Date property filter value is invalid.');\n }\n }\n\n if ((operator === 'before' || operator === 'after') && valueType !== 'date' && valueType !== 'number') {\n throw new InvalidNotePropertyInputError('Before and after filters require date or number properties.');\n }\n\n if ((operator === 'contains' || operator === 'notContains') && valueType !== 'text' && valueType !== 'url') {\n throw new InvalidNotePropertyInputError('Contains filters require text or url properties.');\n }\n\n if (valueType === 'url' && operator !== 'contains' && operator !== 'notContains') {\n return normalizeUrlValue(normalizedValue);\n }\n\n return normalizedValue;\n};\n\nexport const normalizeViewPropertyFilters = (filters: ViewPropertyFilterInput[] | null | undefined) => {\n const normalizedFilters = filters ?? [];\n\n if (normalizedFilters.length > MAX_VIEW_PROPERTY_FILTERS) {\n throw new InvalidNotePropertyInputError(`A view can have up to ${MAX_VIEW_PROPERTY_FILTERS} property filters.`);\n }\n\n return normalizedFilters\n .map((filter): ViewPropertyFilterRecord | null => {\n const key = normalizePropertyKey(filter.key);\n const valueType = filter.valueType;\n const operator = filter.operator;\n\n if (!isPropertyValueType(valueType)) {\n throw new InvalidNotePropertyInputError('Property filter value type is required.');\n }\n\n if (!isViewPropertyFilterOperator(operator)) {\n throw new InvalidNotePropertyInputError('Property filter operator is invalid.');\n }\n\n const storedName = (filter as { name?: unknown }).name;\n const name = typeof storedName === 'string' && storedName.trim() ? storedName.trim() : key;\n\n return {\n key,\n name,\n valueType,\n operator,\n value: normalizeFilterValue({\n value: filter.value,\n valueType,\n operator,\n }),\n };\n })\n .filter((filter): filter is ViewPropertyFilterRecord => filter !== null);\n};\n\nconst parseStoredViewQuery = (value: string | null): ParsedStoredViewQuery => {\n if (!value) {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n displayOptions: normalizeViewDisplayOptions(null),\n };\n }\n\n try {\n const parsed = JSON.parse(value) as Partial<StoredViewQuery>;\n\n return {\n propertyFilters: normalizeViewPropertyFilters(parsed.propertyFilters ?? []),\n sortBy: normalizeViewSortBy(parsed.sortBy),\n sortOrder: normalizeViewSortOrder(parsed.sortOrder),\n displayOptions: normalizeViewDisplayOptions(parsed.displayOptions),\n };\n } catch {\n return {\n propertyFilters: [],\n sortBy: DEFAULT_VIEW_SORT_BY,\n sortOrder: DEFAULT_VIEW_SORT_ORDER,\n displayOptions: normalizeViewDisplayOptions(null),\n };\n }\n};\n\nconst serializeStoredViewQuery = ({ propertyFilters, sortBy, sortOrder, displayOptions }: ParsedStoredViewQuery) => {\n return JSON.stringify({\n propertyFilters,\n sortBy,\n sortOrder,\n displayOptions,\n });\n};\n\nexport const clampViewSectionLimit = (value: number | undefined) => {\n const numericValue = typeof value === 'number' ? value : Number.NaN;\n\n if (!Number.isInteger(numericValue)) {\n return DEFAULT_VIEW_SECTION_LIMIT;\n }\n\n return Math.min(MAX_VIEW_SECTION_LIMIT, Math.max(MIN_VIEW_SECTION_LIMIT, numericValue));\n};\n\nexport const normalizeViewTabTitle = (title: string) => {\n const trimmedTitle = title.trim();\n\n return trimmedTitle || 'Untitled View';\n};\n\nconst buildDefaultSectionTitle = (tagNames: string[], propertyFilters: ViewPropertyFilterRecord[]) => {\n if (tagNames.length > 0) {\n return tagNames.slice(0, 2).join(' + ');\n }\n\n if (propertyFilters.length > 0) {\n return propertyFilters\n .slice(0, 2)\n .map((filter) => filter.name)\n .join(' + ');\n }\n\n return 'All notes';\n};\n\nexport const normalizeViewSectionInput = (input: ViewSectionInput) => {\n const tagNames = normalizeViewTagNames(input.tagNames ?? []);\n const propertyFilters = normalizeViewPropertyFilters(input.propertyFilters);\n const trimmedTitle = input.title?.trim() ?? '';\n const sortBy = normalizeViewSortBy(input.sortBy);\n const sortOrder = normalizeViewSortOrder(input.sortOrder);\n const displayOptions = normalizeViewDisplayOptions(input.displayOptions);\n\n return {\n title: trimmedTitle || buildDefaultSectionTitle(tagNames, propertyFilters),\n displayType: normalizeViewDisplayType(input.displayType),\n displayOptions,\n tagNames,\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters,\n sortBy,\n sortOrder,\n limit: clampViewSectionLimit(input.limit),\n } satisfies {\n title: string;\n displayType: ViewDisplayType;\n displayOptions: ViewDisplayOptionsRecord;\n tagNames: string[];\n mode: ViewTagMatchMode;\n propertyFilters: ViewPropertyFilterRecord[];\n sortBy: ViewSortBy;\n sortOrder: ViewSortOrder;\n limit: number;\n };\n};\n\nexport const normalizeViewNotesQueryInput = (input: ViewNotesQueryInput): ViewNotesQueryRecord => {\n return {\n tagNames: normalizeViewTagNames(input.tagNames ?? []),\n mode: input.mode === 'or' ? 'or' : 'and',\n propertyFilters: normalizeViewPropertyFilters(input.propertyFilters),\n sortBy: normalizeViewSortBy(input.sortBy),\n sortOrder: normalizeViewSortOrder(input.sortOrder),\n };\n};\n\nexport const normalizeViewNotesPagination = (pagination?: { limit?: number; offset?: number }) => {\n const numericLimit = Number(pagination?.limit ?? DEFAULT_VIEW_NOTES_QUERY_LIMIT);\n const limit = Number.isInteger(numericLimit)\n ? Math.min(MAX_VIEW_NOTES_QUERY_LIMIT, Math.max(1, numericLimit))\n : DEFAULT_VIEW_NOTES_QUERY_LIMIT;\n const numericOffset = Number(pagination?.offset ?? 0);\n const offset = Number.isInteger(numericOffset) ? Math.max(0, numericOffset) : 0;\n\n return { limit, offset };\n};\n\nexport const pickNextActiveViewTabId = (tabIds: number[], deletedTabId: number, currentActiveTabId: number | null) => {\n const remainingTabIds = tabIds.filter((tabId) => tabId !== deletedTabId);\n\n if (remainingTabIds.length === 0) {\n return null;\n }\n\n if (currentActiveTabId !== deletedTabId) {\n return currentActiveTabId;\n }\n\n return remainingTabIds[0] ?? null;\n};\n\nconst ensureValidReorderIds = (currentIds: number[], nextIds: number[]) => {\n if (currentIds.length !== nextIds.length) {\n throw new Error('Reorder payload must include every item exactly once.');\n }\n\n const currentIdSet = new Set(currentIds);\n const nextIdSet = new Set(nextIds);\n\n if (currentIdSet.size !== currentIds.length || nextIdSet.size !== nextIds.length) {\n throw new Error('Reorder payload contains duplicate ids.');\n }\n\n for (const id of currentIdSet) {\n if (!nextIdSet.has(id)) {\n throw new Error('Reorder payload must match the current item set.');\n }\n }\n};\n\nconst parseViewId = (id: string) => {\n const numericId = Number(id);\n\n if (!Number.isInteger(numericId) || numericId <= 0) {\n throw new Error('A valid id is required.');\n }\n\n return numericId;\n};\n\nconst serializeViewSection = (section: DbViewSection): ViewSectionRecord => {\n const query = parseStoredViewQuery(section.query);\n\n return {\n id: String(section.id),\n tabId: String(section.tabId),\n title: section.title,\n displayType: normalizeViewDisplayType(section.displayType as ViewDisplayType),\n displayOptions: query.displayOptions,\n tagNames: section.tags.map((tag) => tag.name),\n mode: section.mode as ViewTagMatchMode,\n propertyFilters: query.propertyFilters,\n sortBy: query.sortBy,\n sortOrder: query.sortOrder,\n limit: section.limit,\n order: section.order,\n };\n};\n\nconst serializeViewTab = (tab: DbViewTab): ViewTabRecord => ({\n id: String(tab.id),\n title: tab.title,\n order: tab.order,\n sections: tab.sections.map(serializeViewSection),\n});\n\nconst getOrderedViewTabs = async (db: ViewDbClient) => {\n return db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewTabSectionsInclude,\n });\n};\n\nconst ensureViewWorkspace = async (db: ViewDbClient) => {\n return db.viewWorkspace.upsert({\n where: { id: VIEW_WORKSPACE_ID },\n update: {},\n create: { id: VIEW_WORKSPACE_ID },\n });\n};\n\nconst readViewWorkspace = async (db: ViewDbClient): Promise<ViewWorkspaceRecord> => {\n const [workspace, tabs] = await Promise.all([ensureViewWorkspace(db), getOrderedViewTabs(db)]);\n\n const activeTabId =\n workspace.activeTabId !== null && tabs.some((tab) => tab.id === workspace.activeTabId)\n ? String(workspace.activeTabId)\n : tabs[0]\n ? String(tabs[0].id)\n : null;\n\n return {\n activeTabId,\n tabs: tabs.map(serializeViewTab),\n };\n};\n\nconst readViewSection = async (db: ViewDbClient, id: number): Promise<ViewSectionRecord | null> => {\n const section = await db.viewSection.findUnique({\n where: { id },\n include: orderedViewSectionTagsInclude,\n });\n\n return section ? serializeViewSection(section) : null;\n};\n\nexport const hydratePropertyFilters = async (\n db: ViewDbClient,\n filters: ViewPropertyFilterRecord[],\n options: { validateSelectOptions?: boolean } = {},\n) => {\n if (filters.length === 0) {\n return [];\n }\n\n const definitions = await db.propertyDefinition.findMany({\n where: { key: { in: filters.map((filter) => filter.key) } },\n select: {\n key: true,\n name: true,\n valueType: true,\n options: {\n select: {\n value: true,\n },\n },\n },\n });\n const definitionByKey = new Map(definitions.map((definition) => [definition.key, definition]));\n\n return filters.map((filter) => {\n const definition = definitionByKey.get(filter.key);\n\n if (!definition) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} is not defined.`);\n }\n\n if (definition.valueType !== filter.valueType) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} uses ${definition.valueType} values.`);\n }\n\n if (\n options.validateSelectOptions &&\n filter.valueType === 'select' &&\n filter.operator !== 'exists' &&\n filter.operator !== 'notExists'\n ) {\n const optionValue = normalizeSelectFilterValue(filter.value ?? '');\n\n if (!definition.options.some((option) => option.value === optionValue)) {\n throw new InvalidNotePropertyInputError(`Property ${filter.key} option ${optionValue} is not defined.`);\n }\n }\n\n return {\n ...filter,\n name: definition.name,\n };\n });\n};\n\nconst buildStoredViewQuery = async (db: ViewDbClient, section: ReturnType<typeof normalizeViewSectionInput>) => {\n const propertyFilters = await hydratePropertyFilters(db, section.propertyFilters, { validateSelectOptions: true });\n\n return serializeStoredViewQuery({\n propertyFilters,\n sortBy: section.sortBy,\n sortOrder: section.sortOrder,\n displayOptions: section.displayOptions,\n });\n};\n\nconst getNextTabOrder = async (db: ViewDbClient) => {\n const lastTab = await db.viewTab.findFirst({\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastTab ? lastTab.order + 1 : 0;\n};\n\nconst getNextSectionOrder = async (db: ViewDbClient, tabId: number) => {\n const lastSection = await db.viewSection.findFirst({\n where: { tabId },\n orderBy: [{ order: 'desc' }, { createdAt: 'desc' }],\n select: { order: true },\n });\n\n return lastSection ? lastSection.order + 1 : 0;\n};\n\nconst resequenceViewTabs = async (db: ViewDbClient) => {\n const tabs = await db.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n tabs.map((tab, index) =>\n db.viewTab.update({\n where: { id: tab.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nconst resequenceViewSections = async (db: ViewDbClient, tabId: number) => {\n const sections = await db.viewSection.findMany({\n where: { tabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n await Promise.all(\n sections.map((section, index) =>\n db.viewSection.update({\n where: { id: section.id },\n data: { order: index },\n }),\n ),\n );\n};\n\nexport const getViewWorkspace = async () => {\n return readViewWorkspace(models);\n};\n\nexport const getViewSectionById = async (id: string) => {\n return readViewSection(models, parseViewId(id));\n};\n\nconst normalizeSelectFilterValue = (value: string) => {\n return value.trim().toLowerCase().replace(/\\s+/g, '-');\n};\n\nconst buildPropertyFilterValueWhere = (filter: ViewPropertyFilterRecord): Prisma.NotePropertyWhereInput => {\n switch (filter.valueType) {\n case 'number': {\n const numberValue = Number(filter.value);\n\n if (filter.operator === 'before') {\n return { numberValue: { lt: numberValue } };\n }\n\n if (filter.operator === 'after') {\n return { numberValue: { gt: numberValue } };\n }\n\n if (filter.operator === 'notEquals') {\n return { numberValue: { not: numberValue } };\n }\n\n return { numberValue };\n }\n case 'date': {\n const dateValue = new Date(`${filter.value}T00:00:00.000Z`);\n\n if (filter.operator === 'before') {\n return { dateValue: { lt: dateValue } };\n }\n\n if (filter.operator === 'after') {\n return { dateValue: { gt: dateValue } };\n }\n\n if (filter.operator === 'notEquals') {\n return { dateValue: { not: dateValue } };\n }\n\n return { dateValue };\n }\n case 'boolean': {\n if (filter.operator === 'notEquals') {\n return { boolValue: { not: filter.value === 'true' } };\n }\n\n return { boolValue: filter.value === 'true' };\n }\n case 'select':\n if (filter.operator === 'notEquals') {\n return { option: { is: { value: { not: normalizeSelectFilterValue(filter.value ?? '') } } } };\n }\n\n return { option: { is: { value: normalizeSelectFilterValue(filter.value ?? '') } } };\n case 'url':\n case 'text':\n default: {\n const textValue = filter.value?.toLowerCase() ?? '';\n\n if (filter.operator === 'notEquals') {\n return { textValueNormalized: { not: textValue } };\n }\n\n if (filter.operator === 'contains') {\n return { textValueNormalized: { contains: textValue } };\n }\n\n if (filter.operator === 'notContains') {\n return { textValueNormalized: { not: { contains: textValue } } };\n }\n\n return { textValueNormalized: textValue };\n }\n }\n};\n\nexport const buildPropertyFilterWhere = (filter: ViewPropertyFilterRecord): Prisma.NoteWhereInput => {\n const definitionWhere = {\n definition: {\n is: {\n key: filter.key,\n },\n },\n } satisfies Prisma.NotePropertyWhereInput;\n\n if (filter.operator === 'notExists') {\n return {\n properties: {\n none: definitionWhere,\n },\n };\n }\n\n if (filter.operator === 'exists') {\n return {\n properties: {\n some: definitionWhere,\n },\n };\n }\n\n return {\n properties: {\n some: {\n ...definitionWhere,\n ...buildPropertyFilterValueWhere(filter),\n },\n },\n };\n};\n\nexport const buildViewNotesWhere = (\n query: Pick<ViewNotesQueryRecord, 'tagNames' | 'mode' | 'propertyFilters'>,\n): Prisma.NoteWhereInput => {\n const clauses: Prisma.NoteWhereInput[] = [];\n\n if (query.tagNames.length > 0) {\n clauses.push(buildNoteTagNamesWhere(query.tagNames, query.mode as NoteTagMatchMode));\n }\n\n for (const filter of query.propertyFilters) {\n clauses.push(buildPropertyFilterWhere(filter));\n }\n\n if (clauses.length === 0) {\n return {};\n }\n\n return { AND: clauses };\n};\n\nexport const buildViewSectionWhere = (section: ViewSectionRecord): Prisma.NoteWhereInput => {\n return buildViewNotesWhere(section);\n};\n\nconst buildViewNotesOrderBy = (\n query: Pick<ViewNotesQueryRecord, 'sortBy' | 'sortOrder'>,\n): Prisma.NoteOrderByWithRelationInput[] => {\n return [{ [query.sortBy]: query.sortOrder }, { id: 'asc' }];\n};\n\nconst buildViewSectionOrderBy = (section: ViewSectionRecord): Prisma.NoteOrderByWithRelationInput[] => {\n return buildViewNotesOrderBy(section);\n};\n\nexport const getViewSectionNotes = async (\n id: string,\n pagination: {\n limit: number;\n offset: number;\n },\n): Promise<ViewSectionNotesResult | null> => {\n const section = await models.viewSection.findUnique({\n where: { id: parseViewId(id) },\n include: orderedViewSectionTagsInclude,\n });\n\n if (!section) {\n return null;\n }\n\n const serializedSection = serializeViewSection(section);\n const where = buildViewSectionWhere(serializedSection);\n\n const [totalCount, notes] = await Promise.all([\n models.note.count({ where }),\n models.note.findMany({\n orderBy: buildViewSectionOrderBy(serializedSection),\n where,\n take: Number(pagination.limit),\n skip: Number(pagination.offset),\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const getNotesByPropertiesWithDb = async (\n db: ViewDbClient,\n input: ViewNotesQueryInput,\n pagination?: {\n limit?: number;\n offset?: number;\n },\n): Promise<ViewSectionNotesResult> => {\n const normalizedQuery = normalizeViewNotesQueryInput(input);\n\n if (normalizedQuery.propertyFilters.length === 0) {\n throw new InvalidNotePropertyInputError('At least one property filter is required.');\n }\n\n const query = {\n ...normalizedQuery,\n propertyFilters: await hydratePropertyFilters(db, normalizedQuery.propertyFilters, {\n validateSelectOptions: true,\n }),\n };\n const normalizedPagination = normalizeViewNotesPagination(pagination);\n const where = buildViewNotesWhere(query);\n\n const [totalCount, notes] = await Promise.all([\n db.note.count({ where }),\n db.note.findMany({\n orderBy: buildViewNotesOrderBy(query),\n where,\n take: normalizedPagination.limit,\n skip: normalizedPagination.offset,\n }),\n ]);\n\n return {\n totalCount,\n notes,\n };\n};\n\nexport const getNotesByProperties = async (\n input: ViewNotesQueryInput,\n pagination?: {\n limit?: number;\n offset?: number;\n },\n): Promise<ViewSectionNotesResult> => {\n return getNotesByPropertiesWithDb(models, input, pagination);\n};\n\nexport const createViewTab = async (title: string) => {\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const nextTabOrder = await getNextTabOrder(tx);\n const createdTab = await tx.viewTab.create({\n data: {\n title: normalizeViewTabTitle(title),\n order: nextTabOrder,\n },\n include: orderedViewTabSectionsInclude,\n });\n\n if (workspace.activeTabId === null) {\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: createdTab.id },\n });\n }\n\n return serializeViewTab(createdTab);\n });\n};\n\nexport const updateViewTab = async (id: string, title: string) => {\n const updatedTab = await models.viewTab.update({\n where: { id: parseViewId(id) },\n data: {\n title: normalizeViewTabTitle(title),\n },\n include: orderedViewTabSectionsInclude,\n });\n\n return serializeViewTab(updatedTab);\n};\n\nexport const deleteViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n\n if (!tabs.some((tab) => tab.id === tabId)) {\n return false;\n }\n\n await tx.viewTab.delete({ where: { id: tabId } });\n await resequenceViewTabs(tx);\n\n const nextActiveTabId = pickNextActiveViewTabId(\n tabs.map((tab) => tab.id),\n tabId,\n workspace.activeTabId,\n );\n\n await tx.viewWorkspace.update({\n where: { id: VIEW_WORKSPACE_ID },\n data: { activeTabId: nextActiveTabId },\n });\n\n return true;\n });\n};\n\nexport const setActiveViewTab = async (id: string) => {\n const tabId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const workspace = await ensureViewWorkspace(tx);\n const tab = await tx.viewTab.findUnique({\n where: { id: tabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n await tx.viewWorkspace.update({\n where: { id: workspace.id },\n data: { activeTabId: tabId },\n });\n\n return readViewWorkspace(tx);\n });\n};\n\nexport const reorderViewTabs = async (tabIds: string[]) => {\n const nextTabIds = tabIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const tabs = await tx.viewTab.findMany({\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentTabIds = tabs.map((tab) => tab.id);\n\n ensureValidReorderIds(currentTabIds, nextTabIds);\n\n await Promise.all(\n nextTabIds.map((tabId, index) =>\n tx.viewTab.update({\n where: { id: tabId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedTabs = await getOrderedViewTabs(tx);\n return reorderedTabs.map(serializeViewTab);\n });\n};\n\nexport const createViewSection = async (tabId: string, input: ViewSectionInput) => {\n const numericTabId = parseViewId(tabId);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const tab = await tx.viewTab.findUnique({\n where: { id: numericTabId },\n select: { id: true },\n });\n\n if (!tab) {\n throw new Error('View tab not found.');\n }\n\n const nextSectionOrder = await getNextSectionOrder(tx, numericTabId);\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const createdSection = await tx.viewSection.create({\n data: {\n tabId: numericTabId,\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n order: nextSectionOrder,\n tags: {\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(createdSection);\n });\n};\n\nexport const updateViewSection = async (id: string, input: ViewSectionInput) => {\n const sectionId = parseViewId(id);\n const nextSection = normalizeViewSectionInput(input);\n\n return models.$transaction(async (tx) => {\n const query = await buildStoredViewQuery(tx, nextSection);\n\n const updatedSection = await tx.viewSection.update({\n where: { id: sectionId },\n data: {\n title: nextSection.title,\n displayType: nextSection.displayType,\n query,\n mode: nextSection.mode,\n limit: nextSection.limit,\n tags: {\n deleteMany: {},\n create: nextSection.tagNames.map((tagName, index) => ({\n name: tagName,\n order: index,\n })),\n },\n },\n include: orderedViewSectionTagsInclude,\n });\n\n return serializeViewSection(updatedSection);\n });\n};\n\nexport const deleteViewSection = async (id: string) => {\n const sectionId = parseViewId(id);\n\n return models.$transaction(async (tx) => {\n const section = await tx.viewSection.findUnique({\n where: { id: sectionId },\n select: { id: true, tabId: true },\n });\n\n if (!section) {\n return false;\n }\n\n await tx.viewSection.delete({\n where: { id: sectionId },\n });\n await resequenceViewSections(tx, section.tabId);\n\n return true;\n });\n};\n\nexport const reorderViewSections = async (tabId: string, sectionIds: string[]) => {\n const numericTabId = parseViewId(tabId);\n const nextSectionIds = sectionIds.map(parseViewId);\n\n return models.$transaction(async (tx) => {\n const sections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n select: { id: true },\n });\n const currentSectionIds = sections.map((section) => section.id);\n\n ensureValidReorderIds(currentSectionIds, nextSectionIds);\n\n await Promise.all(\n nextSectionIds.map((sectionId, index) =>\n tx.viewSection.update({\n where: { id: sectionId },\n data: { order: index },\n }),\n ),\n );\n\n const reorderedSections = await tx.viewSection.findMany({\n where: { tabId: numericTabId },\n orderBy: [{ order: 'asc' }, { createdAt: 'asc' }],\n include: orderedViewSectionTagsInclude,\n });\n\n return reorderedSections.map(serializeViewSection);\n });\n};\n"],"mappings":"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","names":[]}
|
|
@@ -168,6 +168,255 @@ function preprocessMarkdownExplicitTags(markdown) {
|
|
|
168
168
|
placeholderToTag
|
|
169
169
|
};
|
|
170
170
|
}
|
|
171
|
+
const MARKDOWN_ANGLE_BRACKET_TOKEN_PATTERN = /<([^<>\n]+)>/g;
|
|
172
|
+
const MARKDOWN_NUMERIC_TILDE_RANGE_PATTERN = /(\d)~(?=\d)/g;
|
|
173
|
+
const MARKDOWN_FENCED_CODE_PATTERN = /^ {0,3}(`{3,}|~{3,})/;
|
|
174
|
+
const ANGLE_BRACKET_PLACEHOLDER_PREFIX = "\uE000OBANGLE";
|
|
175
|
+
const ANGLE_BRACKET_PLACEHOLDER_SUFFIX = "\uE001";
|
|
176
|
+
const NUMERIC_TILDE_RANGE_PLACEHOLDER_PREFIX = "\uE000OBTILDE";
|
|
177
|
+
const NUMERIC_TILDE_RANGE_PLACEHOLDER_SUFFIX = "\uE001";
|
|
178
|
+
function isMarkdownAutolinkAngleBracketText(innerText) {
|
|
179
|
+
if (innerText !== innerText.trim()) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
return /^[a-z][a-z0-9.+-]{1,31}:[^\s<>]*$/i.test(innerText) || /^[^\s@<>]+@[^\s@<>]+\.[^\s@<>]+$/.test(innerText);
|
|
183
|
+
}
|
|
184
|
+
function countLiteralAngleBracketTextTokens(markdown) {
|
|
185
|
+
const tokenCounts = /* @__PURE__ */ new Map();
|
|
186
|
+
for (const match of markdown.matchAll(MARKDOWN_ANGLE_BRACKET_TOKEN_PATTERN)) {
|
|
187
|
+
const token = match[0];
|
|
188
|
+
const innerText = match[1] ?? "";
|
|
189
|
+
if (!token || isMarkdownAutolinkAngleBracketText(innerText)) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
tokenCounts.set(token, (tokenCounts.get(token) ?? 0) + 1);
|
|
193
|
+
}
|
|
194
|
+
return tokenCounts;
|
|
195
|
+
}
|
|
196
|
+
function extractLiteralAngleBracketTextTokens(markdown) {
|
|
197
|
+
return [...countLiteralAngleBracketTextTokens(markdown).keys()];
|
|
198
|
+
}
|
|
199
|
+
function hasLiteralAngleBracketTextTokenLoss(sourceMarkdown, renderedMarkdown) {
|
|
200
|
+
const sourceCounts = countLiteralAngleBracketTextTokens(sourceMarkdown);
|
|
201
|
+
if (sourceCounts.size === 0) {
|
|
202
|
+
return false;
|
|
203
|
+
}
|
|
204
|
+
const renderedCounts = countLiteralAngleBracketTextTokens(renderedMarkdown);
|
|
205
|
+
for (const [token, sourceCount] of sourceCounts) {
|
|
206
|
+
if ((renderedCounts.get(token) ?? 0) < sourceCount) {
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
function countNumericTildeRangeMarkers(markdown) {
|
|
213
|
+
return [...markdown.matchAll(MARKDOWN_NUMERIC_TILDE_RANGE_PATTERN)].length;
|
|
214
|
+
}
|
|
215
|
+
function hasNumericTildeRangeMarkers(markdown) {
|
|
216
|
+
return countNumericTildeRangeMarkers(markdown) > 0;
|
|
217
|
+
}
|
|
218
|
+
function hasNumericTildeRangeMarkerLoss(sourceMarkdown, renderedMarkdown) {
|
|
219
|
+
const sourceCount = countNumericTildeRangeMarkers(sourceMarkdown);
|
|
220
|
+
return sourceCount > 0 && countNumericTildeRangeMarkers(renderedMarkdown) < sourceCount;
|
|
221
|
+
}
|
|
222
|
+
function protectMarkdownNumericTildeRanges(markdown) {
|
|
223
|
+
const protectedLines = [];
|
|
224
|
+
const placeholderToToken = /* @__PURE__ */ new Map();
|
|
225
|
+
let activeFence = null;
|
|
226
|
+
for (const line of markdown.split(/(?<=\n)/)) {
|
|
227
|
+
const { body: lineBody, lineEnding } = splitMarkdownLineEnding(line);
|
|
228
|
+
const fenceMatch = lineBody.match(MARKDOWN_FENCED_CODE_PATTERN);
|
|
229
|
+
if (activeFence) {
|
|
230
|
+
protectedLines.push(line);
|
|
231
|
+
if (isClosingFenceLine(lineBody, activeFence)) {
|
|
232
|
+
activeFence = null;
|
|
233
|
+
}
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
if (fenceMatch?.[1]) {
|
|
237
|
+
const marker = fenceMatch[1][0];
|
|
238
|
+
activeFence = {
|
|
239
|
+
marker,
|
|
240
|
+
length: fenceMatch[1].length
|
|
241
|
+
};
|
|
242
|
+
protectedLines.push(line);
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (/^(?: {4,}|\t)/.test(lineBody)) {
|
|
246
|
+
protectedLines.push(line);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
protectedLines.push(`${protectMarkdownLineNumericTildeRanges(lineBody, placeholderToToken)}${lineEnding}`);
|
|
250
|
+
}
|
|
251
|
+
return {
|
|
252
|
+
markdown: protectedLines.join(""),
|
|
253
|
+
placeholderToToken
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function protectMarkdownTextAngleBrackets(markdown) {
|
|
257
|
+
const protectedLines = [];
|
|
258
|
+
const placeholderToToken = /* @__PURE__ */ new Map();
|
|
259
|
+
let activeFence = null;
|
|
260
|
+
for (const line of markdown.split(/(?<=\n)/)) {
|
|
261
|
+
const { body: lineBody, lineEnding } = splitMarkdownLineEnding(line);
|
|
262
|
+
const fenceMatch = lineBody.match(MARKDOWN_FENCED_CODE_PATTERN);
|
|
263
|
+
if (activeFence) {
|
|
264
|
+
protectedLines.push(line);
|
|
265
|
+
if (isClosingFenceLine(lineBody, activeFence)) {
|
|
266
|
+
activeFence = null;
|
|
267
|
+
}
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
if (fenceMatch?.[1]) {
|
|
271
|
+
const marker = fenceMatch[1][0];
|
|
272
|
+
activeFence = {
|
|
273
|
+
marker,
|
|
274
|
+
length: fenceMatch[1].length
|
|
275
|
+
};
|
|
276
|
+
protectedLines.push(line);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (/^(?: {4,}|\t)/.test(lineBody)) {
|
|
280
|
+
protectedLines.push(line);
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
protectedLines.push(`${protectMarkdownLineTextAngleBrackets(lineBody, placeholderToToken)}${lineEnding}`);
|
|
284
|
+
}
|
|
285
|
+
return {
|
|
286
|
+
markdown: protectedLines.join(""),
|
|
287
|
+
placeholderToToken
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function splitMarkdownLineEnding(line) {
|
|
291
|
+
if (line.endsWith("\r\n")) {
|
|
292
|
+
return {
|
|
293
|
+
body: line.slice(0, -2),
|
|
294
|
+
lineEnding: "\r\n"
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (line.endsWith("\n")) {
|
|
298
|
+
return {
|
|
299
|
+
body: line.slice(0, -1),
|
|
300
|
+
lineEnding: "\n"
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
body: line,
|
|
305
|
+
lineEnding: ""
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function isClosingFenceLine(line, fence) {
|
|
309
|
+
const escapedMarker = fence.marker === "`" ? "`" : "~";
|
|
310
|
+
return new RegExp(`^ {0,3}${escapedMarker}{${fence.length},} *$`).test(line);
|
|
311
|
+
}
|
|
312
|
+
function protectMarkdownLineTextAngleBrackets(line, placeholderToToken) {
|
|
313
|
+
let result = "";
|
|
314
|
+
let cursor = 0;
|
|
315
|
+
while (cursor < line.length) {
|
|
316
|
+
const codeStart = line.indexOf("`", cursor);
|
|
317
|
+
if (codeStart === -1) {
|
|
318
|
+
result += replaceLiteralAngleBracketTextTokens(line.slice(cursor), placeholderToToken);
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
result += replaceLiteralAngleBracketTextTokens(line.slice(cursor, codeStart), placeholderToToken);
|
|
322
|
+
const delimiterLength = countRepeatedCharacter(line, codeStart, "`");
|
|
323
|
+
const codeEnd = line.indexOf("`".repeat(delimiterLength), codeStart + delimiterLength);
|
|
324
|
+
if (codeEnd === -1) {
|
|
325
|
+
result += replaceLiteralAngleBracketTextTokens(line.slice(codeStart), placeholderToToken);
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
const codeEndExclusive = codeEnd + delimiterLength;
|
|
329
|
+
result += line.slice(codeStart, codeEndExclusive);
|
|
330
|
+
cursor = codeEndExclusive;
|
|
331
|
+
}
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
334
|
+
function protectMarkdownLineNumericTildeRanges(line, placeholderToToken) {
|
|
335
|
+
let result = "";
|
|
336
|
+
let cursor = 0;
|
|
337
|
+
while (cursor < line.length) {
|
|
338
|
+
const protectedSpan = findNextMarkdownProtectedSpan(line, cursor);
|
|
339
|
+
if (!protectedSpan) {
|
|
340
|
+
result += replaceNumericTildeRangeMarkers(line.slice(cursor), placeholderToToken);
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
result += replaceNumericTildeRangeMarkers(line.slice(cursor, protectedSpan.start), placeholderToToken);
|
|
344
|
+
result += line.slice(protectedSpan.start, protectedSpan.end);
|
|
345
|
+
cursor = protectedSpan.end;
|
|
346
|
+
}
|
|
347
|
+
return result;
|
|
348
|
+
}
|
|
349
|
+
function findNextMarkdownProtectedSpan(line, cursor) {
|
|
350
|
+
const codeSpan = findNextInlineCodeSpan(line, cursor);
|
|
351
|
+
const linkDestinationSpan = findNextMarkdownLinkDestinationSpan(line, cursor);
|
|
352
|
+
if (!codeSpan) {
|
|
353
|
+
return linkDestinationSpan;
|
|
354
|
+
}
|
|
355
|
+
if (!linkDestinationSpan) {
|
|
356
|
+
return codeSpan;
|
|
357
|
+
}
|
|
358
|
+
return codeSpan.start <= linkDestinationSpan.start ? codeSpan : linkDestinationSpan;
|
|
359
|
+
}
|
|
360
|
+
function findNextInlineCodeSpan(line, cursor) {
|
|
361
|
+
const codeStart = line.indexOf("`", cursor);
|
|
362
|
+
if (codeStart === -1) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
const delimiterLength = countRepeatedCharacter(line, codeStart, "`");
|
|
366
|
+
const codeEnd = line.indexOf("`".repeat(delimiterLength), codeStart + delimiterLength);
|
|
367
|
+
if (codeEnd === -1) {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
start: codeStart,
|
|
372
|
+
end: codeEnd + delimiterLength
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function findNextMarkdownLinkDestinationSpan(line, cursor) {
|
|
376
|
+
const linkDestinationPrefix = line.indexOf("](", cursor);
|
|
377
|
+
if (linkDestinationPrefix === -1) {
|
|
378
|
+
return null;
|
|
379
|
+
}
|
|
380
|
+
const destinationStart = linkDestinationPrefix + 2;
|
|
381
|
+
const destinationEnd = line.indexOf(")", destinationStart);
|
|
382
|
+
if (destinationEnd === -1) {
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
return {
|
|
386
|
+
start: destinationStart,
|
|
387
|
+
end: destinationEnd
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
function replaceLiteralAngleBracketTextTokens(text, placeholderToToken) {
|
|
391
|
+
return text.replace(MARKDOWN_ANGLE_BRACKET_TOKEN_PATTERN, (match, innerText) => {
|
|
392
|
+
if (isMarkdownAutolinkAngleBracketText(innerText)) {
|
|
393
|
+
return match;
|
|
394
|
+
}
|
|
395
|
+
const placeholder = createAngleBracketPlaceholder(placeholderToToken.size);
|
|
396
|
+
placeholderToToken.set(placeholder, match);
|
|
397
|
+
return placeholder;
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function replaceNumericTildeRangeMarkers(text, placeholderToToken) {
|
|
401
|
+
return text.replace(MARKDOWN_NUMERIC_TILDE_RANGE_PATTERN, (match, leadingDigit) => {
|
|
402
|
+
const placeholder = createNumericTildeRangePlaceholder(placeholderToToken.size);
|
|
403
|
+
placeholderToToken.set(placeholder, "~");
|
|
404
|
+
return `${leadingDigit}${placeholder}`;
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
function createAngleBracketPlaceholder(index) {
|
|
408
|
+
return `${ANGLE_BRACKET_PLACEHOLDER_PREFIX}${index}${ANGLE_BRACKET_PLACEHOLDER_SUFFIX}`;
|
|
409
|
+
}
|
|
410
|
+
function createNumericTildeRangePlaceholder(index) {
|
|
411
|
+
return `${NUMERIC_TILDE_RANGE_PLACEHOLDER_PREFIX}${index}${NUMERIC_TILDE_RANGE_PLACEHOLDER_SUFFIX}`;
|
|
412
|
+
}
|
|
413
|
+
function countRepeatedCharacter(value, start, character) {
|
|
414
|
+
let cursor = start;
|
|
415
|
+
while (value[cursor] === character) {
|
|
416
|
+
cursor += 1;
|
|
417
|
+
}
|
|
418
|
+
return cursor - start;
|
|
419
|
+
}
|
|
171
420
|
function findTagPlaceholderAtCursor(text, cursor, placeholderToTag) {
|
|
172
421
|
for (const [placeholder, tagToken] of placeholderToTag.entries()) {
|
|
173
422
|
if (text.startsWith(placeholder, cursor)) {
|
|
@@ -197,6 +446,39 @@ function restoreRemainingTagPlaceholders(blocks, placeholderToTag) {
|
|
|
197
446
|
})
|
|
198
447
|
);
|
|
199
448
|
}
|
|
449
|
+
function restoreProtectedTextPlaceholders(blocks, placeholderToToken) {
|
|
450
|
+
if (placeholderToToken.size === 0) {
|
|
451
|
+
return blocks;
|
|
452
|
+
}
|
|
453
|
+
return mapBlocks(
|
|
454
|
+
blocks,
|
|
455
|
+
(content) => mapBlockContent(
|
|
456
|
+
content,
|
|
457
|
+
(inline) => restoreProtectedTextInValue(inline, placeholderToToken)
|
|
458
|
+
)
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
function restoreProtectedTextInValue(value, placeholderToToken) {
|
|
462
|
+
if (typeof value === "string") {
|
|
463
|
+
return restoreProtectedText(value, placeholderToToken);
|
|
464
|
+
}
|
|
465
|
+
if (Array.isArray(value)) {
|
|
466
|
+
return value.map((item) => restoreProtectedTextInValue(item, placeholderToToken));
|
|
467
|
+
}
|
|
468
|
+
if (value && typeof value === "object") {
|
|
469
|
+
return Object.fromEntries(
|
|
470
|
+
Object.entries(value).map(([key, item]) => [key, restoreProtectedTextInValue(item, placeholderToToken)])
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
return value;
|
|
474
|
+
}
|
|
475
|
+
function restoreProtectedText(text, placeholderToToken) {
|
|
476
|
+
let restoredText = text;
|
|
477
|
+
for (const [placeholder, token] of placeholderToToken.entries()) {
|
|
478
|
+
restoredText = restoredText.split(placeholder).join(token);
|
|
479
|
+
}
|
|
480
|
+
return restoredText;
|
|
481
|
+
}
|
|
200
482
|
function createTextInline(text, styles = {}) {
|
|
201
483
|
return {
|
|
202
484
|
type: "text",
|
|
@@ -331,13 +613,42 @@ async function blocksToMarkdown(contentJson) {
|
|
|
331
613
|
async function markdownToBlocksJson(markdown, deps = defaultMarkdownImportDeps) {
|
|
332
614
|
const editor = getEditor();
|
|
333
615
|
const preprocessedMarkdown = preprocessMarkdownExplicitTags(markdown);
|
|
334
|
-
const
|
|
335
|
-
const
|
|
336
|
-
|
|
616
|
+
const tildeProtectedMarkdown = protectMarkdownNumericTildeRanges(preprocessedMarkdown.markdown);
|
|
617
|
+
const contentJson = await parseMarkdownToContentJson(
|
|
618
|
+
editor,
|
|
619
|
+
tildeProtectedMarkdown.markdown,
|
|
337
620
|
deps,
|
|
338
|
-
preprocessedMarkdown.placeholderToTag
|
|
621
|
+
preprocessedMarkdown.placeholderToTag,
|
|
622
|
+
tildeProtectedMarkdown.placeholderToToken
|
|
623
|
+
);
|
|
624
|
+
if (extractLiteralAngleBracketTextTokens(preprocessedMarkdown.markdown).length === 0) {
|
|
625
|
+
return contentJson;
|
|
626
|
+
}
|
|
627
|
+
if (!hasLiteralAngleBracketTextTokenLoss(preprocessedMarkdown.markdown, await blocksToMarkdown(contentJson))) {
|
|
628
|
+
return contentJson;
|
|
629
|
+
}
|
|
630
|
+
const protectedMarkdown = protectMarkdownTextAngleBrackets(tildeProtectedMarkdown.markdown);
|
|
631
|
+
const placeholderToToken = new Map([
|
|
632
|
+
...tildeProtectedMarkdown.placeholderToToken,
|
|
633
|
+
...protectedMarkdown.placeholderToToken
|
|
634
|
+
]);
|
|
635
|
+
return parseMarkdownToContentJson(
|
|
636
|
+
editor,
|
|
637
|
+
protectedMarkdown.markdown,
|
|
638
|
+
deps,
|
|
639
|
+
preprocessedMarkdown.placeholderToTag,
|
|
640
|
+
placeholderToToken
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
async function parseMarkdownToContentJson(editor, markdown, deps, placeholderToTag, placeholderToProtectedTextToken = /* @__PURE__ */ new Map()) {
|
|
644
|
+
const blocks = await editor.tryParseMarkdownToBlocks(markdown);
|
|
645
|
+
const restoredBlocks = await restoreCustomInlineContent(blocks, deps, placeholderToTag);
|
|
646
|
+
const restoredTagBlocks = restoreRemainingTagPlaceholders(restoredBlocks, placeholderToTag);
|
|
647
|
+
const restoredProtectedTextBlocks = restoreProtectedTextPlaceholders(
|
|
648
|
+
restoredTagBlocks,
|
|
649
|
+
placeholderToProtectedTextToken
|
|
339
650
|
);
|
|
340
|
-
return JSON.stringify(
|
|
651
|
+
return JSON.stringify(restoredProtectedTextBlocks);
|
|
341
652
|
}
|
|
342
653
|
function extractTagIdsFromContentJson(contentJson) {
|
|
343
654
|
const blocks = parseBlockNoteContent(contentJson);
|
|
@@ -374,7 +685,11 @@ function countReferenceInlinesFromContentJson(contentJson) {
|
|
|
374
685
|
export {
|
|
375
686
|
blocksToMarkdown,
|
|
376
687
|
countReferenceInlinesFromContentJson,
|
|
688
|
+
extractLiteralAngleBracketTextTokens,
|
|
377
689
|
extractTagIdsFromContentJson,
|
|
690
|
+
hasLiteralAngleBracketTextTokenLoss,
|
|
691
|
+
hasNumericTildeRangeMarkerLoss,
|
|
692
|
+
hasNumericTildeRangeMarkers,
|
|
378
693
|
hasUnsupportedMarkdownBlocks,
|
|
379
694
|
markdownToBlocksJson
|
|
380
695
|
};
|