Skip to content

Commit 850a795

Browse files
feat(project): support front-matter with Editor (#122)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
1 parent caffa9b commit 850a795

File tree

5 files changed

+66
-8
lines changed

5 files changed

+66
-8
lines changed

components/molecules/FilesTree.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div
55
class="group border-r-2 py-2 pr-6 flex items-center text-sm font-medium focus:u-bg-gray-50 focus:outline-none w-full cursor-pointer"
66
:class="{
7-
[`pl-${6 + (level * 3)}`]: true,
7+
[`pl-[${24 + (level * 12)}px]`]: true,
88
'u-bg-gray-100 u-border-gray-800 u-text-gray-900': isSelected(file),
99
'border-transparent u-text-gray-500 hover:u-text-gray-900 hover:u-bg-gray-50': !isSelected(file)
1010
}"

composables/useMarkdown.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as matter from 'gray-matter'
2+
import flat from 'flat'
3+
4+
export const useMarkdown = () => {
5+
function parseFrontMatter (content) {
6+
// @ts-ignore
7+
const { data, content: c, ...rest } = matter.default ? matter.default(content) : matter(content)
8+
9+
// unflatten frontmatter data
10+
// convert `parent.child` keys into `parent: { child: ... }`
11+
const unflattenData = flat.unflatten(data || {}, {})
12+
13+
return {
14+
content: c.replace(/^\n/, ''),
15+
matter: unflattenData,
16+
...rest
17+
}
18+
}
19+
20+
function stringifyFrontMatter (content, data = {}) {
21+
// flatten frontmatter data
22+
// convert `parent: { child: ... }` into flat keys `parent.child`
23+
data = flat.flatten(data, {
24+
// preserve arrays and their contents as is and do not waltk through arrays
25+
// flatten array will be like `parent.0.child` and `parent.1.child` with is not readable
26+
safe: true
27+
})
28+
29+
// eslint-disable-next-line import/no-named-as-default-member
30+
return matter.stringify(`\n${content}`, data)
31+
}
32+
33+
return {
34+
parseFrontMatter,
35+
stringifyFrontMatter
36+
}
37+
}

nuxt.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export default defineNuxtConfig({
7272
require('@tailwindcss/typography')
7373
],
7474
content: ['presets/*.ts'],
75-
safelist: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30].map(number => `pl-${number}`)
75+
safelist: [24, 36, 48, 60, 72, 84, 96, 108, 120].map(number => `pl-[${number}px]`)
7676
}
7777
}
7878
})

pages/@[team]/[project]/content.vue

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
/>
1515
</template>
1616

17-
<DocusEditor v-model="content" />
17+
<DocusEditor :model-value="parsedContent" @update:model-value="saveContent" />
1818
</ProjectPage>
1919
</template>
2020

@@ -34,12 +34,16 @@ const props = defineProps({
3434
})
3535
3636
const client = useStrapiClient()
37+
const { parseFrontMatter, stringifyFrontMatter } = useMarkdown()
3738
3839
const branch: Ref<Branch> = ref(null)
3940
const file: Ref<File> = ref(null)
4041
const content: Ref<string> = ref('')
42+
const updatedContent: Ref<string> = ref('')
43+
const parsedContent: Ref<string> = ref('')
44+
const parsedMatter: Ref<string> = ref('')
4145
42-
const { data: branches, refresh: refreshBranches } = await useAsyncData('files', () => client<Branch[]>(`/projects/${props.project.id}/branches`))
46+
const { data: branches, refresh: refreshBranches } = await useAsyncData('branches', () => client<Branch[]>(`/projects/${props.project.id}/branches`))
4347
4448
const { data: files, refresh: refreshFiles } = await useAsyncData('files', () => client<File[]>(`/projects/${props.project.id}/files`, {
4549
params: {
@@ -56,9 +60,7 @@ watch(files, () => {
5660
5761
// Select branch when branches changes
5862
watch(branches, () => {
59-
const branchName = localStorage.getItem(`projects-${props.project.id}-branch`)
60-
61-
selectBranch((branchName && branches.value.find(branch => branch.name === branchName)) || branches.value.find(branch => branch.name === props.project.repository.default_branch) || branches.value[0])
63+
selectBranch(branches.value.find(branch => branch.name === props.project.repository.default_branch) || branches.value[0])
6264
}, { immediate: true })
6365
6466
// Fetch content when file changes
@@ -75,6 +77,18 @@ watch(file, async () => {
7577
// Fetch files when branch changes
7678
watch(branch, async () => await refreshFiles())
7779
80+
// Split markdown front-matter when content changes
81+
watch(content, () => {
82+
const { content: c, matter } = parseFrontMatter(content.value)
83+
84+
parsedContent.value = c
85+
parsedMatter.value = matter
86+
}, { immediate: true })
87+
88+
function saveContent (content) {
89+
updatedContent.value = stringifyFrontMatter(content, parsedMatter.value)
90+
}
91+
7892
function findFileFromPath (path, files) {
7993
for (const file of files) {
8094
if (file.path === path) {
@@ -93,6 +107,5 @@ function selectFile (f: File) {
93107
94108
function selectBranch (b: Branch) {
95109
branch.value = b
96-
localStorage.setItem(`projects-${props.project.id}-branch`, branch.value?.name)
97110
}
98111
</script>

plugins/fix-gray-matter.client.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { Buffer } from 'buffer'
2+
import { defineNuxtPlugin } from '#imports'
3+
4+
// TODO: remove this fix when https://github.com/jonschlinkert/gray-matter/pull/132 is merged
5+
// `Buffer` is not globally available
6+
export default defineNuxtPlugin(() => {
7+
Object.assign(window, { Buffer })
8+
})

0 commit comments

Comments
 (0)