Skip to content

feat(project): support front-matter with Editor #122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 8, 2022
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 components/molecules/FilesTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<div
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"
:class="{
[`pl-${6 + (level * 3)}`]: true,
[`pl-[${24 + (level * 12)}px]`]: true,
'u-bg-gray-100 u-border-gray-800 u-text-gray-900': isSelected(file),
'border-transparent u-text-gray-500 hover:u-text-gray-900 hover:u-bg-gray-50': !isSelected(file)
}"
Expand Down
37 changes: 37 additions & 0 deletions composables/useMarkdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as matter from 'gray-matter'
import flat from 'flat'

export const useMarkdown = () => {
function parseFrontMatter (content) {
// @ts-ignore
const { data, content: c, ...rest } = matter.default ? matter.default(content) : matter(content)

// unflatten frontmatter data
// convert `parent.child` keys into `parent: { child: ... }`
const unflattenData = flat.unflatten(data || {}, {})

return {
content: c.replace(/^\n/, ''),
matter: unflattenData,
...rest
}
}

function stringifyFrontMatter (content, data = {}) {
// flatten frontmatter data
// convert `parent: { child: ... }` into flat keys `parent.child`
data = flat.flatten(data, {
// preserve arrays and their contents as is and do not waltk through arrays
// flatten array will be like `parent.0.child` and `parent.1.child` with is not readable
safe: true
})

// eslint-disable-next-line import/no-named-as-default-member
return matter.stringify(`\n${content}`, data)
}

return {
parseFrontMatter,
stringifyFrontMatter
}
}
2 changes: 1 addition & 1 deletion nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default defineNuxtConfig({
require('@tailwindcss/typography')
],
content: ['presets/*.ts'],
safelist: [3, 6, 9, 12, 15, 18, 21, 24, 27, 30].map(number => `pl-${number}`)
safelist: [24, 36, 48, 60, 72, 84, 96, 108, 120].map(number => `pl-[${number}px]`)
}
}
})
25 changes: 19 additions & 6 deletions pages/@[team]/[project]/content.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
/>
</template>

<DocusEditor v-model="content" />
<DocusEditor :model-value="parsedContent" @update:model-value="saveContent" />
</ProjectPage>
</template>

Expand All @@ -34,12 +34,16 @@ const props = defineProps({
})

const client = useStrapiClient()
const { parseFrontMatter, stringifyFrontMatter } = useMarkdown()

const branch: Ref<Branch> = ref(null)
const file: Ref<File> = ref(null)
const content: Ref<string> = ref('')
const updatedContent: Ref<string> = ref('')
const parsedContent: Ref<string> = ref('')
const parsedMatter: Ref<string> = ref('')

const { data: branches, refresh: refreshBranches } = await useAsyncData('files', () => client<Branch[]>(`/projects/${props.project.id}/branches`))
const { data: branches, refresh: refreshBranches } = await useAsyncData('branches', () => client<Branch[]>(`/projects/${props.project.id}/branches`))

const { data: files, refresh: refreshFiles } = await useAsyncData('files', () => client<File[]>(`/projects/${props.project.id}/files`, {
params: {
Expand All @@ -56,9 +60,7 @@ watch(files, () => {

// Select branch when branches changes
watch(branches, () => {
const branchName = localStorage.getItem(`projects-${props.project.id}-branch`)

selectBranch((branchName && branches.value.find(branch => branch.name === branchName)) || branches.value.find(branch => branch.name === props.project.repository.default_branch) || branches.value[0])
selectBranch(branches.value.find(branch => branch.name === props.project.repository.default_branch) || branches.value[0])
}, { immediate: true })

// Fetch content when file changes
Expand All @@ -75,6 +77,18 @@ watch(file, async () => {
// Fetch files when branch changes
watch(branch, async () => await refreshFiles())

// Split markdown front-matter when content changes
watch(content, () => {
const { content: c, matter } = parseFrontMatter(content.value)

parsedContent.value = c
parsedMatter.value = matter
}, { immediate: true })

function saveContent (content) {
updatedContent.value = stringifyFrontMatter(content, parsedMatter.value)
}

function findFileFromPath (path, files) {
for (const file of files) {
if (file.path === path) {
Expand All @@ -93,6 +107,5 @@ function selectFile (f: File) {

function selectBranch (b: Branch) {
branch.value = b
localStorage.setItem(`projects-${props.project.id}-branch`, branch.value?.name)
}
</script>
8 changes: 8 additions & 0 deletions plugins/fix-gray-matter.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Buffer } from 'buffer'
import { defineNuxtPlugin } from '#imports'

// TODO: remove this fix when https://github.com/jonschlinkert/gray-matter/pull/132 is merged
// `Buffer` is not globally available
export default defineNuxtPlugin(() => {
Object.assign(window, { Buffer })
})