Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
},
"dependencies": {
"@iconify-json/lucide": "^1.2.71",
"@nuxtjs/mdc": "0.18.0",
"@nuxtjs/mdc": "https://pkg.pr.new/@nuxtjs/mdc@bf09212",
"defu": "^6.1.4",
"destr": "^2.0.5",
"unstorage": "^1.17.1"
Expand Down
57 changes: 55 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/app/src/components/content/ContentEditorCode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const language = computed(() => {
})

const { editor, setContent: setEditorContent } = useMonaco(editorRef, {
uri: 'file://' + (document.value?.id || ''),
language,
readOnly: props.readOnly,
colorMode: ui.colorMode,
Expand Down
5 changes: 4 additions & 1 deletion src/app/src/composables/useMonaco.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { editor as Editor } from 'modern-monaco/editor-core'
import { setupMonaco } from '../utils/monaco'

export interface UseMonacoOptions {
uri?: string
language: Ref<string> | string
initialContent?: string
readOnly?: boolean
Expand Down Expand Up @@ -60,7 +61,9 @@ export function useMonaco(target: Ref<HTMLElement | undefined>, options: UseMona

// Create and attach model
const language = unref(options.language)
editor.value.setModel(monaco.editor.createModel(initialContent, language))
const existingModel = options.uri && monaco.editor.getModel(options.uri)
const model = existingModel || monaco.editor.createModel(initialContent, language, options.uri)
editor.value.setModel(model)

// Watch for color mode changes
watch(options.colorMode, (newMode) => {
Expand Down
4 changes: 3 additions & 1 deletion src/app/src/utils/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export async function generateContentFromMarkdownDocument(document: DatabasePage
}
})

return await stringifyMarkdown(body, removeReservedKeysFromDocument(document), {
const markdown = await stringifyMarkdown(body, removeReservedKeysFromDocument(document), {
plugins: {
remarkMDC: {
options: {
Expand All @@ -206,4 +206,6 @@ export async function generateContentFromMarkdownDocument(document: DatabasePage
},
},
})

return typeof markdown === 'string' ? markdown.replace(/&#x2A;/g, '*') : markdown
}
18 changes: 17 additions & 1 deletion src/app/src/utils/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { type DatabasePageItem, ContentFileExtension } from '../types'
import { stringify } from 'minimark/stringify'
import type { MDCRoot } from '@nuxtjs/mdc'
import type { MarkdownRoot } from '@nuxt/content'
import { isDeepEqual } from './object'

export function isEqual(document1: DatabasePageItem, document2: DatabasePageItem) {
function withoutLastStyles(body: MarkdownRoot) {
Expand Down Expand Up @@ -35,7 +36,7 @@ export function isEqual(document1: DatabasePageItem, document2: DatabasePageItem
}
}

if (JSON.stringify(documentData1) !== JSON.stringify(documentData2)) {
if (!isDeepEqual(refineDocumentData(documentData1), refineDocumentData(documentData2))) {
return false
}

Expand All @@ -49,3 +50,18 @@ export function isEqual(document1: DatabasePageItem, document2: DatabasePageItem

return true
}

function refineDocumentData(doc: Record<string, unknown>) {
if (doc.seo) {
const seo = doc.seo as Record<string, unknown>
doc.seo = {
...seo,
title: seo.title || doc.title,
description: seo.description || doc.description,
}
}
// documents with same id are being compared, so it is safe to remove `path` and `__hash__`
Reflect.deleteProperty(doc, '__hash__')
Reflect.deleteProperty(doc, 'path')
return doc
}
7 changes: 6 additions & 1 deletion src/app/src/utils/draft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { DatabaseItem, MediaItem, DatabasePageItem, DraftItem, BaseItem, Co
import { DraftStatus, ContentFileExtension, TreeRootId } from '../types'
import { isEqual } from './database'
import { studioFlags } from '../composables/useStudio'
import { generateContentFromDocument } from './content'
import { generateContentFromDocument, generateDocumentFromContent } from './content'
import { fromBase64ToUTF8 } from '../utils/string'

export async function checkConflict(draftItem: DraftItem<DatabaseItem | MediaItem>): Promise<ContentConflict | undefined> {
Expand All @@ -28,6 +28,11 @@ export async function checkConflict(draftItem: DraftItem<DatabaseItem | MediaIte

const localContent = await generateContentFromDocument(draftItem.original as DatabaseItem) as string
const githubContent = fromBase64ToUTF8(draftItem.githubFile.content)
const githubDocument = await generateDocumentFromContent(draftItem.id, githubContent) as DatabaseItem

if (isEqual(draftItem.original as DatabasePageItem, githubDocument as DatabasePageItem)) {
return
}

if (localContent.trim() === githubContent.trim()) {
return
Expand Down
15 changes: 15 additions & 0 deletions src/app/src/utils/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,18 @@ export const pick = (obj: Record<string, unknown>, keys: string | string[]) => {
return Object.fromEntries(Object.entries(obj)
.filter(([key]) => keys.includes(key)))
}

export function isDeepEqual(obj1: Record<string, unknown>, obj2: Record<string, unknown>) {
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return obj1 === obj2

const keys1 = Object.keys(obj1).filter(k => obj1[k] != null)
const keys2 = Object.keys(obj2).filter(k => obj2[k] != null)

if (keys1.length !== keys2.length) return false

for (const key of keys1) {
if (!isDeepEqual(obj1[key] as Record<string, unknown>, obj2[key] as Record<string, unknown>)) return false
}

return true
}
11 changes: 10 additions & 1 deletion src/module/src/runtime/utils/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,19 @@ export function normalizeDocument(document: DatabaseItem) {
// we can remove it to avoid duplication
if (document.seo) {
const seo = document.seo as Record<string, unknown>
if ((!seo.title || seo.title === document.title) && (!seo.description || seo.description === document.description)) {

if (!seo.title || seo.title === document.title) {
Reflect.deleteProperty(document.seo, 'title')
}
if (!seo.description || seo.description === document.description) {
Reflect.deleteProperty(document.seo, 'description')
}

if (Object.keys(seo).length === 0) {
Reflect.deleteProperty(document, 'seo')
}
}

return document
}

Expand Down
Loading