The next-tinacms-markdown
package provides a set of methods for editing content sourced from Markdown files.
useLocalMarkdownForm( markdownFile, options? ):[values, form]
- A React Hook for registering local forms with function components.useGlobalMarkdownForm( markdownFile, options? ):[values, form]
- A React Hook for registering global forms with function components.markdownForm( Component, options? ): Component
- A React Higher-Order Component for registering local forms with class or function components.The hooks, useLocalMarkdownForm
& useGlobalMarkdownForm
, work similarly. The biggest difference between them is whether they register local or global forms wih the CMS.
Arguments
markdownFile
: Both hooks expect an object as the first argument that matches the following interface:// A datastructure representing a MarkdownFile file stored in Git
export interface MarkdownFile {
fileRelativePath: string
frontmatter: any
markdownBody: string
}
options
: The second argument is an optional configuration object that can include options to customize the form.Return Values
values
: An object containing the current values from frontmatter
and markdownBody
. You can use these values to render content.form
: A reference to the Form
registered to the CMS. Most of the time you won't need to work directly with the Form
, so you won't see it used in the example.The useLocalMarkdownForm
hook will connect the return data from getInitialProps
with Tina, then return the frontmatter
and markdownBody
values to be rendered.
/*
** 1. Import `useLocalMarkdownForm`
*/
import { useLocalMarkdownForm } from 'next-tinacms-markdown'
import matter from 'gray-matter'
import ReactMarkdown from 'react-markdown'
import Layout from '../components/Layout'
export default function Info(props) {
/*
** Optional — define an options object
** to customize the form
*/
const formOptions = {
label: 'Home Page',
fields: [
{ label: 'Name', name: 'frontmatter.name', component: 'text' },
{
name: 'markdownBody',
label: 'Home Page Content',
component: 'markdown',
},
],
}
/*
** 2. Call `useLocalMarkdownForm` and pass in the
** `data` object returned from `getInitialProps`,
** along with any form options.
*/
const [data] = useLocalMarkdownForm(props.markdownFile, formOptions)
/*
** 3. Render content from your Markdown source file
** with the returned `data` object.
*/
return (
<Layout>
<section>
<h1>{data.frontmatter.name}<h2>
<ReactMarkdown>{data.markdownBody}</ReactMarkdown>
</section>
</Layout>
)
}
Info.getInitialProps = async function() {
const infoData = await import(`../data/info.md`)
const data = matter(infoData.default)
return {
/*
** 4. Make sure your return data matches this shape
*/
markdownFile: {
fileRelativePath: `data/info.md`,
frontmatter: data.data,
markdownBody: data.content,
},
}
}
You can use
gray-matter
to parse the YAML frontmatter when importing a raw Markdown file.
markdownForm
accepts two arguments: a component and an form configuration object. The component being passed is expected to receive data as props that matches the markdownFile
interface outlined below.
// A datastructure representing a MarkdownFile file stored in Git
export interface MarkdownFile {
fileRelativePath: string
frontmatter: any
markdownBody: string
}
markdownForm
returns the original component with a local form registered with Tina. Below is the same example from useLocalMarkdownForm
, but refactored to use the HOC.
/*
** 1. import `markdownForm`
*/
import { markdownForm } from 'next-tinacms-markdown'
import ReactMarkdown from 'react-markdown'
import matter from 'gray-matter'
import Layout from '../components/Layout'
function Info(props) {
const data = props.markdownFile
return (
<Layout>
<section>
<h1>{data.frontmatter.name}<h2>
<ReactMarkdown>{data.markdownBody}</ReactMarkdown>
</section>
</Layout>
)
}
/*
** Optional — define an options object
** to customize the form
*/
const formOptions = {
//...
}
/*
** 2. Wrap your component with `markdownForm`,
** pass in optional form field config object
** and declare a new variable to hold the
** returned component
*/
const EditableInfo = markdownForm(Info, formOptions)
/*
** 3. Export the 'editable' version of the
** original component
*/
export default EditableInfo
/*
** 4. Call your data fetching method
** on the 'editable' component
*/
EditableInfo.getInitialProps = async function() {
const configData = await import(`../data/config.json`)
const infoData = await import(`../data/info.md`)
const data = matter(infoData.default)
return {
title: configData.title,
description: configData.description,
/*
** 5. Structure your return object
** with this shape. Make sure
** to use the `markdownFile`
** property name
*/
markdownFile: {
fileRelativePath: `data/info.md`,
frontmatter: data.data,
markdownBody: data.content,
},
}
}