Skip to content

Commit

Permalink
fix: do not remove H1 from markdown content (#411)
Browse files Browse the repository at this point in the history
* fix: do not remove H1 from markdown content

* feat: `extract.heading`

* fix: improve UI

* fix: trim text content

* fix: handle string values
  • Loading branch information
farnabaz authored Jun 16, 2021
1 parent cc96365 commit 7e0689a
Show file tree
Hide file tree
Showing 26 changed files with 121 additions and 58 deletions.
2 changes: 1 addition & 1 deletion docs/content/1.get-started/1.installation.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Installation

> Setting up a beautiful website with Docus is one command away. 🤙
Setting up a beautiful website with Docus is one command away. 🤙

Docus is an opinionated [Nuxt](https://nuxtjs.org) application that allows you to generate **content-based websites** with ease.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/1.get-started/2.configuration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configuration

> Tailor Docus for your own identity easily. 🌈
Tailor Docus for your own identity easily. 🌈

## Website

Expand Down
2 changes: 1 addition & 1 deletion docs/content/2.writing/1.my-first-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ navigation:

# Writing my first page

> The fastest path to writing your content. 🏎
The fastest path to writing your content. 🏎

Let's walk through the creation of a simple introduction page.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/2.writing/2.syntax.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Syntax

> Docus syntax makes you love your components even more. 🤝
Docus syntax makes you love your components even more. 🤝

Docus writing experience is based on a specific syntax built upon Vue components.

Expand Down
6 changes: 3 additions & 3 deletions docs/content/2.writing/3.front-matter.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Front-matter

> Easily configure the rendering of your Markdown pages. 📝
Easily configure the rendering of your Markdown pages. 📝

Front-matter is used to transmit data to your components and templates, from any page or directory.

Expand Down Expand Up @@ -42,7 +42,7 @@ The **title** and **description** are automatically filled in from the Markdown
```md
# Title of the page

> Description of the page
Description of the page
```

You can overwrite them using the Front-matter:
Expand All @@ -55,7 +55,7 @@ description: Overwritten description

# Title of the page

> Description of the page
Description of the page
```

## Inheritance
Expand Down
2 changes: 1 addition & 1 deletion docs/content/2.writing/4.prose.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Prose

> Customizing your Markdown rendering has never been easier. 🧙‍♂️
Customizing your Markdown rendering has never been easier. 🧙‍♂️

Docus Markdown rendering preserves the HTML structure of your file.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.features/1.routing.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Filesystem routing

> A good looking website from any directory. 🔮
A good looking website from any directory. 🔮

Each markdown page in the `contentDir` directory will become a page and will be listed in the left navigation.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.features/2.localization.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Localization

> Enable i18n just by creating a directory. 🗺
Enable i18n just by creating a directory. 🗺

The first level of directories in the `content/` folder are the locales used with [nuxt-i18n](https://github.com/nuxt-community/i18n-module) as defined in your `nuxt.config.js`.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.features/3.assets.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Assets

> Easily import and optimize your assets with pre-defined modules. 🙈
Easily import and optimize your assets with pre-defined modules. 🙈

## Favicon and PWA Icon

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.features/4.social-image.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Social Images

> Docus automatically generates a social preview image for every document. 🤳
Docus automatically generates a social preview image for every document. 🤳

It uses the `social-image-preview` page to generate the images.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.features/5.deployment.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Deployment

> Deploy your documentation with Docus to any static hosting. 🪶
Deploy your documentation with Docus to any static hosting. 🪶

To generate the documentation for production, run the following command:

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.features/6.extend.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Extend

> Extend Docus with the power of Nuxt modules. 🚀
Extend Docus with the power of Nuxt modules. 🚀

Docus is based on Nuxt, so you can benefit from the existing ecosystem of [Nuxt Modules](https://modules.nuxtjs.org/).

Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.features/7.migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ navigation:

# Migrate from @nuxt/content-theme-docs

> Migrate from @nuxt/content-theme-docs to Docus. 🔋
Migrate from @nuxt/content-theme-docs to Docus. 🔋

By migrating to Docus, you will have a fresh new design for your documentation :sparkles:

Expand Down
2 changes: 1 addition & 1 deletion docs/content/4.theme/1.settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ navigation:

# Theme settings

> The default theme is entirely customizable, from a simple configuration file! ✨
The default theme is entirely customizable, from a simple configuration file! ✨

The default configuration sets defaults for every needed feature of your theme.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/4.theme/2.components.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Components

> Good looking components, ready to use in your website. 💄
Good looking components, ready to use in your website. 💄

Docus default theme comes with a lot of pre-defined components.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/4.theme/5.layout.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Layout

> Customize your website with slots or overwrite the layout components. 🧩
Customize your website with slots or overwrite the layout components. 🧩

With the power of the [Nuxt Components](https://github.com/nuxt/components#overwriting-components), every part of the template is fully customizable.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/4.theme/6.slots.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Slots

> Docus supports customizable slots in the template. 🧱
Docus supports customizable slots in the template. 🧱

Just create a component inside your `components` directory with the same name as the slot.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,20 +148,27 @@ function getSlotName(node) {
}
export default {
name: 'NuxtContent',
name: 'DocusContent',
functional: true,
props: {
document: {
type: Object,
type: [Object, String],
required: true
}
},
render(h, { data, props, parent }) {
render(h, { data, props, parent, _v }) {
const { document } = props
// Render simple string
if (typeof document === 'string') {
return _v(document)
}
const { body } = document || {}
if (!body || !body.children || !Array.isArray(body.children)) {
return
}
let classes = []
if (Array.isArray(data.class)) {
classes = data.class
Expand All @@ -171,7 +178,7 @@ export default {
} else {
classes = [data.class]
}
data.class = classes.concat('nuxt-content')
data.class = classes
data.props = Object.assign({ ...body.props }, data.props)
const children = body.children.map(child => processNode(child, h, document))
Expand All @@ -184,7 +191,11 @@ export default {
}
})
}
return h('div', data, children)
// detect root tag
const tag = body.tag || 'div'
return h(tag, data, children)
}
}
</script>
56 changes: 37 additions & 19 deletions src/core/utils/document.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { withoutTrailingSlash } from 'ufo'
import { DocusDocument, DocusMarkdownNode } from '../../types'
import { expandTags } from '../runtime/utils'
import { expandTags, flatUnwrap } from '../runtime/utils'

export function generatePosition(path: string, document: DocusDocument): string {
const position = path
Expand Down Expand Up @@ -33,38 +33,56 @@ export function isDraft(path: string): boolean {
}

export function processDocumentInfo(document: DocusDocument): DocusDocument {
if (document.title && document.description) {
return document
}
// There is no need to extract if both title and descriptio is provided by user
if (document.title && document.description) return document

const [first, second] = document.body.children
// top level `text` can be ignored
.filter(node => node.type !== 'text')

if (first && expandTags(['h1']).includes(first.tag)) {
if (!document.title) {
document.title = getTextContent(first)
Object.assign(first, {
type: 'text',
value: ''
})
// Remove anchor link
first.children = flatUnwrap(first.children, ['a'])

document.titleNode = { body: first }

// Remove node if heading extract is enables
if (document.extract?.heading !== false) {
Object.assign(first, {
type: 'text',
value: ''
})
}
}
// look for second element to find description
if (second && expandTags(['blockquote']).includes(second.tag)) {
if (second && expandTags(['p']).includes(second.tag)) {
if (!document.description) {
document.description = getTextContent(second)
Object.assign(second, {
type: 'text',
value: ''
})
document.descriptionNode = { body: second }

// Remove node if heading extract is enables
if (document.extract?.heading !== false) {
Object.assign(second, {
type: 'text',
value: ''
})
}
}
}
} else if (first && first.type === 'blockquote') {
} else if (first && expandTags(['p']).includes(first.tag)) {
if (!document.description) {
document.description = getTextContent(first)
Object.assign(first, {
type: 'text',
value: ''
})
document.descriptionNode = { body: first }

// Remove node if heading extract is enables
if (document.extract?.heading !== false) {
Object.assign(first, {
type: 'text',
value: ''
})
}
}
}
return document
Expand All @@ -77,7 +95,7 @@ function getTextContent(node: DocusMarkdownNode): string {
if (node.children) {
text = text + node.children.map(child => getTextContent(child)).join('')
}
return text
return text.trim()
}

function padLeft(value: string, length: number): string {
Expand Down
2 changes: 1 addition & 1 deletion src/defaultTheme/components/atoms/InjectContent.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<NuxtContent :document="page" />
<DocusContent :document="page" />
</template>

<script>
Expand Down
46 changes: 36 additions & 10 deletions src/defaultTheme/components/organisms/PageContent.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div>
<section class="xl:mb-4 mt-4 xl:mt-0 px-4 sm:px-6">
<section v-if="showHeading" class="xl:mb-4 mt-4 xl:mt-0 px-4 sm:px-6">
<div class="flex items-center justify-between">
<InjectComponent
v-if="page.icon"
Expand All @@ -9,9 +9,10 @@
>
<span class="text-3rem">{{ page.icon }}</span>
</InjectComponent>
<h1 class="flex-1 text-4xl font-semibold tracking-tight text-gray-900 dark:text-gray-100">
{{ page.title }}
</h1>

<DocusContent v-if="page.titleNode" id="headline" :document="page.titleNode" />
<ProseH1 v-else id="headline">{{ page.title }}</ProseH1>

<span
v-if="page.draft"
class="
Expand All @@ -27,15 +28,17 @@
bg-yellow-100
rounded-full
items-flex
dark:bg-yellow-800 dark:text-yellow-400
dark:bg-yellow-800
dark:text-yellow-400
"
>Draft</span
>
<Badge v-if="page.badge" class="font-medium">{{ page.badge }}</Badge>
</div>
<p v-if="page.description" class="mt-4 text-lg font-medium text-gray-500 dark:text-gray-400">
{{ page.description }}
</p>
<template v-if="page.description">
<DocusContent v-if="page.descriptionNode" id="lead" :document="page.descriptionNode" />
<ProseParagraph id="lead">{{ page.description }}</ProseParagraph>
</template>
<hr
v-if="$scopedSlots['mobile-toc'] || page.description"
class="mt-4 border-gray-100 dark:border-gray-800 dark:border-opacity-50"
Expand All @@ -45,20 +48,43 @@
<slot name="mobile-toc" />

<div class="px-4 sm:px-6 mt-4">
<NuxtContent :document="page" class="docus-content" />
<DocusContent :document="page" class="docus-content" />
</div>
</div>
</template>

<script>
import { defineComponent } from '@nuxtjs/composition-api'
import { computed, defineComponent } from '@nuxtjs/composition-api'
export default defineComponent({
props: {
page: {
type: Object,
required: true
}
},
setup(props) {
const showHeading = computed(() => !props.page.extract || props.page.extract.heading !== false)
return {
showHeading
}
}
})
</script>

<style scoped lang="postcss">
.docus-content {
::v-deep {
& > h1:first-child {
margin-top: 0;
}
}
}
#headline {
@apply m-0 flex-1 text-4xl font-semibold tracking-tight text-gray-900 dark:text-gray-100;
}
#lead {
@apply mt-4 mb-0 text-lg font-medium text-gray-500 dark:text-gray-400;
}
</style>
Loading

0 comments on commit 7e0689a

Please sign in to comment.