docs: make widget docs editable (#1782)

* make widget docs editable

* update widget doc frontmatter keys

* improve docs preview

* fix formatting

* fix preview

* add prism highlighting for previews

* fix formatting

* restore cms branch
This commit is contained in:
Shawn Erquhart
2018-10-01 20:00:57 -04:00
committed by GitHub
parent c261163eab
commit 6e453b3f08
25 changed files with 143 additions and 162 deletions

View File

@ -1,16 +1,45 @@
import React from 'react';
import CMS from 'netlify-cms';
import dayjs from 'dayjs';
import Prism from 'prismjs';
import { BlogPostTemplate } from '../templates/blog-post';
import { DocsTemplate } from '../templates/doc-page';
import WidgetDoc from '../components/widget-doc';
import Release from '../components/release';
import WhatsNew from '../components/whats-new';
import Notification from '../components/notification';
import '../css/lib/prism.css';
import '../css/imports/docs.css';
import '../css/imports/whatsnew.css';
import '../css/imports/header.css';
const withHighlight = WrappedComponent =>
class Highlight extends React.Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}
highlight() {
Prism.highlightAllUnder(this.ref.current);
}
componentDidMount() {
this.highlight();
}
componentDidUpdate() {
this.highlight();
}
render() {
return (
<div className="language-markup" ref={this.ref}>
<WrappedComponent {...this.props} />
</div>
);
}
};
const BlogPostPreview = ({ entry, widgetFor }) => {
const data = entry.get('data');
return (
@ -27,6 +56,10 @@ const DocsPreview = ({ entry, widgetFor }) => (
<DocsTemplate title={entry.getIn(['data', 'title'])} body={widgetFor('body')} />
);
const WidgetDocPreview = ({ entry, widgetFor }) => (
<WidgetDoc visible={true} label={entry.get('label')} body={widgetFor('body')} />
);
const ReleasePreview = ({ entry }) => (
<WhatsNew>
{entry.getIn(['data', 'updates']).map((release, idx) => (
@ -50,7 +83,8 @@ const NotificationPreview = ({ entry }) =>
</Notification>
));
CMS.registerPreviewTemplate('blog', BlogPostPreview);
CMS.registerPreviewTemplate('docs', DocsPreview);
CMS.registerPreviewTemplate('blog', withHighlight(BlogPostPreview));
CMS.registerPreviewTemplate('docs', withHighlight(DocsPreview));
CMS.registerPreviewTemplate('widget_docs', withHighlight(WidgetDocPreview));
CMS.registerPreviewTemplate('releases', ReleasePreview);
CMS.registerPreviewTemplate('notifications', NotificationPreview);

View File

@ -0,0 +1,11 @@
import React from 'react';
import classnames from 'classnames';
const WidgetDoc = ({ visible, label, body, html }) => (
<div className={classnames('widget', { widget_open: visible })}>
<h3>{label}</h3>
{body ? body : <div dangerouslySetInnerHTML={{ __html: html }} />}
</div>
);
export default WidgetDoc;

View File

@ -1,5 +1,6 @@
import React, { Component } from 'react';
import classnames from 'classnames';
import WidgetDoc from './widget-doc';
import '../css/imports/widgets.css';
@ -13,7 +14,7 @@ class Widgets extends Component {
const hash = window.location.hash ? window.location.hash.replace('#', '') : '';
const widgetsContainHash = widgets.edges.some(w => w.node.frontmatter.target === hash);
const widgetsContainHash = widgets.edges.some(w => w.node.frontmatter.title === hash);
if (widgetsContainHash) {
return this.setState({
@ -22,18 +23,18 @@ class Widgets extends Component {
}
this.setState({
currentWidget: widgets.edges[0].node.frontmatter.target,
currentWidget: widgets.edges[0].node.frontmatter.title,
});
}
handleWidgetChange = (event, target) => {
handleWidgetChange = (event, title) => {
event.preventDefault();
this.setState(
{
currentWidget: target,
currentWidget: title,
},
() => {
window.history.pushState(null, null, `#${target}`);
window.history.pushState(null, null, `#${title}`);
},
);
};
@ -47,14 +48,14 @@ class Widgets extends Component {
<section className="widgets">
<div className="widgets__cloud">
{widgets.edges.map(({ node }) => {
const { label, target } = node.frontmatter;
const { label, title } = node.frontmatter;
return (
<button
key={target}
key={title}
className={classnames('widgets__item', {
widgets__item_active: currentWidget === target,
widgets__item_active: currentWidget === title,
})}
onClick={event => this.handleWidgetChange(event, target)}
onClick={event => this.handleWidgetChange(event, title)}
>
{label}
</button>
@ -63,18 +64,10 @@ class Widgets extends Component {
</div>
<div className="widgets__container">
{widgets.edges.map(({ node }) => {
const { label, target } = node.frontmatter;
return (
<div
key={label}
className={classnames('widget', {
widget_open: currentWidget === target,
})}
>
<h3>{label}</h3>
<div dangerouslySetInnerHTML={{ __html: node.html }} />
</div>
);
const { frontmatter, html } = node;
const { title, label } = frontmatter;
const isVisible = currentWidget === title;
return <WidgetDoc key={label} visible={isVisible} label={label} html={html} />;
})}
</div>
</section>

View File

@ -1,120 +0,0 @@
/**
* prism.js tomorrow night eighties for JavaScript, CoffeeScript, CSS and HTML
* Based on https://github.com/chriskempson/tomorrow-theme
* @author Rose Pritchard
*/
code[class*='language-'],
pre[class*='language-'] {
color: #ccc;
background: none;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre[class*='language-'] {
padding: 1em;
margin: 0.5em 0;
overflow: auto;
}
:not(pre) > code[class*='language-'],
pre[class*='language-'] {
background: #2d2d2d;
}
/* Inline code */
:not(pre) > code[class*='language-'] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
.token.comment,
.token.block-comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #999;
}
.token.punctuation {
color: #ccc;
}
.token.tag,
.token.attr-name,
.token.namespace,
.token.deleted {
color: #e2777a;
}
.token.function-name {
color: #6196cc;
}
.token.boolean,
.token.number,
.token.function {
color: #f08d49;
}
.token.property,
.token.class-name,
.token.constant,
.token.symbol {
color: #f8c555;
}
.token.selector,
.token.important,
.token.atrule,
.token.keyword,
.token.builtin {
color: #cc99cd;
}
.token.string,
.token.char,
.token.attr-value,
.token.regex,
.token.variable {
color: #7ec699;
}
.token.operator,
.token.entity,
.token.url {
color: #67cdcc;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.token.inserted {
color: green;
}

View File

@ -1,6 +1,7 @@
import React from 'react';
import Helmet from 'react-helmet';
import { graphql } from 'gatsby';
import 'prismjs/themes/prism-tomorrow.css';
import Layout from '../components/layout';
import EditLink from '../components/edit-link';
@ -8,7 +9,6 @@ import Widgets from '../components/widgets';
import DocsNav from '../components/docs-nav';
import MobileNav from '../components/mobile-nav';
import '../css/lib/prism.css';
import '../css/imports/docs.css';
const toMenu = (menu, nav) =>
@ -124,8 +124,8 @@ export const pageQuery = graphql`
edges {
node {
frontmatter {
title
label
target
}
html
}