Docs/userguide switching

This commit is contained in:
Aaron Carlino 2019-12-05 13:38:21 +13:00
parent fd6dcf27be
commit 8fee23cd54
17 changed files with 642 additions and 85 deletions

View File

@ -2,22 +2,38 @@ require("prismjs/themes/prism-okaidia.css");
require("./src/theme/assets/scss/theme.scss");
require('./src/theme/assets/fontawesome/css/all.css');
require('./src/theme/assets/search/algolia.css');
const smoothScroll = require('smooth-scroll');
const Layout = require('./src/components/Layout').default;
const React = require('react');
const Layout = require('./src/components/Layout').default;
const NodeProvider = require('./src/components/NodeProvider').default;
const { setCurrentPath } = require('./src/utils/nodes');
const smoothScroll = require('smooth-scroll');
if (typeof window !== "undefined") {
smoothScroll('a[href*="#"]')
}
/**
* Ensures the chrome doesn't rerender every page load, which makes the sidebar reset its scroll.
*/
exports.wrapPageElement = ({ element, props }) => {
return <Layout {...props}>{element}</Layout>
return (
<NodeProvider {...props}>
<Layout {...props}>
{element}
</Layout>
</NodeProvider>
);
};
exports.onRouteUpdate = ({location}) => {
if (window.ga && process.env.NODE_ENV === 'production') {
window.ga('send', 'pageview');
}
anchorScroll(location);
return true;
};
exports.shouldUpdateScroll = ({
routerProps: { location },
}) => {

View File

@ -1,4 +1,5 @@
const path = require('path');
const userhelpImports = require('./userhelp-imports');
module.exports = {
siteMetadata: {
@ -17,8 +18,13 @@ module.exports = {
{
resolve: `gatsby-source-git`,
options: {
<<<<<<< HEAD
name: `4`,
remote: `https://github.com/silverstripe/silverstripe-framework.git`,
=======
name: `docs--4`,
remote: `/Users/acarlino/Sites/gatsby-docs-4`,
>>>>>>> Docs/userguide switching
branch: `4`,
patterns: `docs/en/**`
}
@ -26,24 +32,40 @@ module.exports = {
{
resolve: `gatsby-source-git`,
options: {
name: `3`,
name: `docs--3`,
remote: `https://github.com/silverstripe/silverstripe-framework.git`,
branch: `3.7`,
patterns: `docs/en/**`
}
},
{
resolve: `gatsby-source-filesystem`,
resolve: `gatsby-source-git`,
options: {
name: `watcher--ss3`,
path: `${__dirname}/.cache/gatsby-source-git/3/docs/en`
name: `user--4`,
remote: `https://github.com/silverstripe/silverstripe-userhelp-content.git`,
branch: `4`,
patterns: `docs/en/**`
}
},
{
resolve: `gatsby-source-git`,
options: {
name: `user--3`,
remote: `https://github.com/silverstripe/silverstripe-userhelp-content.git`,
branch: `3`,
patterns: `docs/en/**`
}
<<<<<<< HEAD
},
=======
},
// ...userhelpImports
>>>>>>> Docs/userguide switching
{
resolve: `gatsby-source-filesystem`,
options: {
name: `watcher--ss4`,
path: `${__dirname}/.cache/gatsby-source-git/4/docs/en`
name: `watcher`,
path: `${__dirname}/.cache/gatsby-source-git/`
}
},
{

View File

@ -3,23 +3,35 @@ const fs = require('fs');
const { createFilePath } = require(`gatsby-source-filesystem`);
const fileToTitle = require('./src/utils/fileToTitle');
const createSlug = (filePath, version) => {
const parts = filePath.split('/');
const langIndex = parts.indexOf('en');
parts.splice(langIndex + 1, 0, version);
return parts
.map(part => part.replace(/^\d+_/, ''))
.join('/')
.toLowerCase()
const createSlug = ({path, version, category, thirdparty}) => {
const [_, lang, ...rest] = path.split('/');
const parts = [
lang,
version,
// use suburl "userhelp" for all user docs
category === 'user' && 'userhelp',
// thirdparty modules are under /optional_features/ (coupling)
thirdparty && `optional_features/${thirdparty}`,
...rest,
].filter(p => p);
const slug = parts
.map(part => part.replace(/^\d+_/, ''))
.join('/')
.toLowerCase();
return `/${slug}/`;
};
exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNodeId, createContentDigest }) => {
const parseName = name => name.split('--');
exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNodeId, createContentDigest }) => {
if (node.internal.type !== 'MarkdownRemark') {
return;
}
const { createNode } = actions;
const fileNode = getNode(node.parent);
const version = fileNode.sourceInstanceName;
const [category, version, thirdparty] = parseName(fileNode.sourceInstanceName);
// The gatsby-source-filesystem plugins are registered to collect from the same path
// that the git source writes to, so we get the watch task (hot reload on content changes)
@ -27,7 +39,7 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
// we bail out if we already have the file. However, we need to ensure
// the file is injected into the template as a dependency, so when the content changes,
// the pages get refreshed on the fly.
if (version.match(/^watcher--/)) {
if (category === 'watcher') {
const existing = getNodesByType('SilverstripeDocument')
.find(n => n.fileAbsolutePath === node.fileAbsolutePath);
@ -37,7 +49,7 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
existing.watchFile___NODE = node.id;
return;
}
}
}
const filePath = createFilePath({
node,
@ -50,7 +62,12 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
fileTitle = path.basename(path.dirname(node.fileAbsolutePath));
}
const docTitle = fileToTitle(fileTitle);
const slug = createSlug(filePath, version);
const slug = createSlug({
path: filePath,
version,
category,
thirdparty,
});
const parentSlug = `${path.resolve(slug, '../')}/`;
const unhideSelf = false;
@ -61,6 +78,7 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
slug,
parentSlug,
unhideSelf,
category,
...node.frontmatter,
};

View File

@ -1,13 +1,27 @@
const Layout = require('./src/components/Layout').default;
const React = require('react');
const Layout = require('./src/components/Layout').default;
const NodeProvider = require('./src/components/NodeProvider').default;
const { setCurrentPath } = require('./src/utils/nodes');
/**
* Applies the node provider (static query of all documents)
* Ensures the chrome doesn't rerender every page load, which makes the sidebar reset its scroll.
*/
exports.wrapPageElement = ({ element, props }) => {
return <Layout {...props}>{element}</Layout>
return (
<NodeProvider>
<Layout {...props}>
{element}
</Layout>
</NodeProvider>
);
};
exports.onRenderBody = ({ setPostBodyComponents, setHeadComponents }) => {
exports.onRenderBody = ({ pathname, setPostBodyComponents, setHeadComponents }) => {
setCurrentPath(pathname);
// Rules that cannot be touched by purgecss because they come in from client side rendering
setHeadComponents([
setHeadComponents([
<style key='prism-css' type="text/css" dangerouslySetInnerHTML={{
__html: `
:not(pre) > code[class*="language-"] {

View File

@ -1,35 +1,37 @@
import React, { StatelessComponent, ReactElement } from 'react';
import SearchBox from './SearchBox';
import { Link, navigate } from 'gatsby';
import { Link } from 'gatsby';
import logo from '../images/silverstripe-logo.svg';
import { getNodes, getHomePage, getCurrentNode, getCurrentVersion } from '../utils/nodes';
import useHierarchy from '../hooks/useHierarchy';
interface HeaderProps {
handleSidebarToggle(e: EventTarget): void
}
const handleNavigate = (e: any): void => {
if (typeof window === 'undefined') {
return;
}
const currentNode = getCurrentNode();
const ver = e.target.value;
if (currentNode) {
const newPath = currentNode.slug.replace(/^\/en\/[0-9]+\//, `/en/${ver}/`);
const otherNode = getNodes().find(n => n.slug === newPath);
// This has to be a hard refresh, because the sidebar needs to unmount
if (otherNode) {
window.location.href = otherNode.slug;
} else {
window.location.href = `/en/${ver}`;
}
}
}
const Header: StatelessComponent<HeaderProps> = ({ handleSidebarToggle }): ReactElement => {
const { getNodes, getHomePage, getCurrentNode, getCurrentVersion } = useHierarchy();
const home = getHomePage();
const handleNavigate = (e: any): void => {
if (typeof window === 'undefined') {
return;
}
const currentNode = getCurrentNode();
const ver = e.target.value;
if (currentNode) {
const newPath = currentNode.slug.replace(/^\/en\/[0-9]+\//, `/en/${ver}/`);
const otherNode = getNodes().find(n => n.slug === newPath);
// This has to be a hard refresh, because the sidebar needs to unmount
if (otherNode) {
window.location.href = otherNode.slug;
} else {
window.location.href = `/en/${ver}`;
}
}
};
return (
<header role="banner" className="header fixed-top">
<div className="branding docs-branding">

View File

@ -1,7 +1,6 @@
import React, { StatelessComponent, useState, ReactNode } from "react";
import Header from './Header';
import Sidebar from './Sidebar';
import { setCurrentNode } from '../utils/nodes';
interface LayoutProps {
children?: ReactNode
@ -9,15 +8,10 @@ interface LayoutProps {
slug: string;
}
}
const Layout: StatelessComponent<LayoutProps> = ({ children, pathContext: { slug } }) => {
const Layout: StatelessComponent<LayoutProps> = ({ children }) => {
const [isToggled, setSidebarOpen] = useState(false);
const handleNavigate = () => setSidebarOpen(false);
// This is a wrapper component that only gets mounted once.
// These two method calls set the initial state for SSR. From here on,
// the state is updated each time the docs template renders
setCurrentNode(slug);
return (
<>
<Header handleSidebarToggle={() => setSidebarOpen(!isToggled)} />

View File

@ -1,9 +1,9 @@
import React, { StatelessComponent, ReactElement } from 'react';
import { getNavChildren, getHomePage, getCurrentNode } from '../utils/nodes';
import { SilverstripeDocument } from '../types';
import { Link } from 'gatsby';
import classnames from 'classnames';
import { LinkGetProps } from '@reach/router';
import useHierarchy from '../hooks/useHierarchy';
interface NavProps {
onNavigate?(e: React.MouseEvent): void;
@ -21,16 +21,40 @@ const getLinkProps = (props: LinkGetProps): {} => {
};
const Nav:StatelessComponent<NavProps> = ({ onNavigate }): ReactElement => {
const {
getNavChildren,
getHomePage,
getCurrentNode,
getCurrentCategory,
getCurrentVersion
} = useHierarchy();
const currentNode = getCurrentNode();
const top = getHomePage();
const category = getCurrentCategory();
const handleCategory = (e) => {
const v = getCurrentVersion();
if (e.target.value === 'user') {
window.location.href = `/en/${v}/userhelp/`;
} else {
window.location.href = `/en/${v}/`;
}
}
if (!top) {
return <nav />;
}
const topLevel = getNavChildren(top).filter(node => node.category === category);
return (
<nav role="navigation" id="docs-nav" className="docs-nav navbar">
<input type="radio" checked={category === 'docs'} value="docs" onChange={handleCategory} id="docs-switch" />
<label htmlFor="docs-switch">Docs</label> |
<input type="radio" checked={category === 'user'} value="user" onChange={handleCategory} id="user-switch" />
<label htmlFor="user-switch">Userguide</label>
<ul className="section-items list-unstyled nav flex-column pb-3">
{getNavChildren(top).map((node: SilverstripeDocument) => {
{topLevel.map((node: SilverstripeDocument) => {
const { slug, title } = node;
const childItems = getNavChildren(node);
return (

View File

@ -0,0 +1,68 @@
import React, { StatelessComponent, ReactElement } from 'react';
import NodeContext from '../contexts/NodeContext';
import { useStaticQuery, graphql } from 'gatsby';
import { HierarchyQuery } from '../types';
import {
getChildren,
getCurrentNode,
getCurrentVersion,
getHomePage,
getNavChildren,
getNodes,
getParent,
getSiblings,
getCurrentCategory,
initialise,
setCurrentPath,
} from '../utils/nodes';
const NodeProvider: StatelessComponent<{}> = ({ children, location: { pathname } }): ReactElement => {
const result:HierarchyQuery = useStaticQuery(graphql`
{
allSilverstripeDocument {
nodes {
title
summary
isIndex
introduction
icon
iconBrand
hideChildren
slug
parentSlug
fileTitle
fileAbsolutePath
category
}
}
}
`
);
if (!getNodes()) {
const nodes = result.allSilverstripeDocument.nodes.map(node => ({
...node,
}));
initialise(nodes);
}
setCurrentPath(pathname);
return (
<NodeContext.Provider value={{
getChildren,
getCurrentNode,
getCurrentVersion,
getHomePage,
getNavChildren,
getNodes,
getParent,
getSiblings,
getCurrentCategory,
}}>
{children}
</NodeContext.Provider>
)
};
export default NodeProvider;

View File

@ -7,7 +7,7 @@
import React, { StatelessComponent } from "react";
import Helmet from "react-helmet";
import { useStaticQuery, graphql } from "gatsby";
import { getCurrentVersion } from '../utils/nodes';
import { getCurrentVersion, getCurrentCategory } from '../utils/nodes';
interface MetaProp {
name: string,
@ -77,11 +77,20 @@ const SEO: StatelessComponent<SEOProps> = ({ description, lang, meta, title }) =
{
name: `docsearch:version`,
content: getCurrentVersion(),
<<<<<<< HEAD
},
{
name: `docsearch:context`,
content: site.siteMetadata.context,
},
=======
},
{
name: `docsearch:category`,
content: getCurrentCategory(),
}
>>>>>>> Docs/userguide switching
].concat(meta)}
/>
);

View File

@ -1,7 +1,7 @@
import React from 'react'
import { StatelessComponent, ReactElement, useEffect } from 'react';
import { navigateTo } from "gatsby-link"
import { getCurrentVersion } from '../utils/nodes';
import useHierarchy from '../hooks/useHierarchy';
interface SearchBoxProps {
identifier: string;
@ -17,6 +17,7 @@ const autocompleteSelected = (e) => {
};
const SearchBox: StatelessComponent<SearchBoxProps> = ({ identifier }): ReactElement|null => {
const { getCurrentVersion } = useHierarchy();
useEffect(() => {
if (typeof window === 'undefined') return;
if (!process.env.GATSBY_DOCSEARCH_API_KEY) {

View File

@ -0,0 +1,5 @@
import React from 'react';
const NodeContext = React.createContext(null);
export default NodeContext;

25
src/hooks/useHierarchy.ts Normal file
View File

@ -0,0 +1,25 @@
import { useContext } from 'react';
import NodeContext from '../contexts/NodeContext';
import { SilverstripeDocument } from '../types';
interface NodeFunctions {
initialise(nodes: SilverstripeDocument[]): undefined;
getChildren(node: SilverstripeDocument, includeFolders: boolean): SilverstripeDocument[];
getSiblings(node: SilverstripeDocument): SilverstripeDocument[];
getNodes(): SilverstripeDocument[];
getParent(node: SilverstripeDocument): SilverstripeDocument|null;
getCurrentNode(): SilverstripeDocument|null;
getHomePage(): SilverstripeDocument|null;
getNavChildren(node: SilverstripeDocument): SilverstripeDocument[];
getCurrentVersion(): string;
getCurrentCategory(): string;
setCurrentNode(slug: string): undefined;
};
const useHierarchy = (): NodeFunctions => {
const hierarchy = useContext(NodeContext);
return hierarchy;
};
export default useHierarchy;

View File

@ -1,9 +1,8 @@
import React, { StatelessComponent, ReactElement, useEffect } from 'react';
import React, { StatelessComponent, ReactElement } from 'react';
import { graphql } from 'gatsby';
import SEO from '../components/SEO';
import { SingleFileQuery } from '../types';
import parseHTML from '../utils/parseHTML';
import { setCurrentNode } from '../utils/nodes';
const Template: StatelessComponent<SingleFileQuery> = (result): ReactElement => {
const currentNode = result.data.silverstripeDocument;
@ -13,12 +12,9 @@ const Template: StatelessComponent<SingleFileQuery> = (result): ReactElement =>
} else {
html = currentNode.parent.html;
}
const { title, slug } = currentNode;
const { title } = currentNode;
const { relativePath, gitRemote: { ref, webLink } } = currentNode.parent.parent;
const editLink = `${webLink}/edit/${ref}/${relativePath}`;
useEffect(() => {
setCurrentNode(slug);
}, []);
return (
<>
<SEO title={title} />

View File

@ -22,6 +22,10 @@ export interface SinglePage {
}
};
enum DocCategory {
'docs' = 'docs',
'user' = 'user',
}
export interface SilverstripeDocument {
title: string;
@ -38,6 +42,7 @@ export interface SilverstripeDocument {
summary: string;
fileTitle: string;
fileAbsolutePath: string;
category: DocCategory;
}
export interface HierarchyQuery {

View File

@ -1,21 +1,28 @@
import { useStaticQuery } from 'gatsby';
import { graphql } from 'gatsby';
import { HierarchyQuery, SilverstripeDocument } from '../types';
import { SilverstripeDocument } from '../types';
import sortFiles from './sortFiles';
let __nodes: SilverstripeDocument[] | undefined;
let __currentNode: SilverstripeDocument | null = null;
let __nodes: SilverstripeDocument[];
let __currentVersion: string | null = null;
let __currentCategory: string | null = null;
let __home: SilverstripeDocument | null = null;
let __path: string | null = null;
const childrenMap = new Map();
const navChildrenMap = new Map();
const siblingMap = new Map();
const parentMap = new Map();
const nodeMap = new Map();
/**
* Hydrate these functions with the list of all nodes
* @param nodes
*/
const initialise = (nodes: SilverstripeDocument[]) => __nodes = nodes;
/**
* Get all documents in the source
*/
<<<<<<< HEAD
const getNodes = (): SilverstripeDocument[] => {
if (__nodes) {
return __nodes;
@ -47,6 +54,9 @@ const getNodes = (): SilverstripeDocument[] => {
return __nodes;
};
=======
const getNodes = (): SilverstripeDocument[] => __nodes;
>>>>>>> Docs/userguide switching
/**
* Get the children of a given node
@ -132,7 +142,20 @@ const getParent = (node: SilverstripeDocument): SilverstripeDocument | null => {
/**
* Get the current node. Must be set by setCurrentNode(string: slug)
*/
const getCurrentNode = (): SilverstripeDocument | null => __currentNode;
const getCurrentNode = (): SilverstripeDocument | null => {
if (!__path) {
return null;
}
if (nodeMap.has(__path)) {
return nodeMap.get(__path) || null;
}
const node = getNodes().find(n => n.slug === __path) || null;
nodeMap.set(__path, node);
return nodeMap.get(__path);
}
/**
* Get the home page
@ -143,7 +166,8 @@ const getHomePage = (): SilverstripeDocument | null => {
}
const nodes = getNodes();
const version = getCurrentVersion();
const homePage = nodes.find(n => n.slug === `/en/${version}/`) || null;
let slug = `/en/${version}/`;
const homePage = nodes.find(n => n.slug === slug) || null;
__home = homePage;
@ -159,19 +183,15 @@ const getCurrentVersion = (): string => __currentVersion || '4';
* Set the current node by its slug.
* @param slug
*/
const setCurrentNode = (slug: string): void => {
const currentNode = getNodes().find(n => n.slug === slug) || null;
__currentNode = currentNode;
if (currentNode) {
const matches = currentNode.slug.match(/^\/en\/([0-9]+)\//);
if (matches) {
__currentVersion = matches[1];
}
}
const setCurrentPath = (path: string) => {
__path = path;
const [_, lang, version, category] = path.split('/');
__currentVersion = version;
__currentCategory = category === 'userhelp' ? 'user' : 'docs';
};
export {
initialise,
getNodes,
getChildren,
getSiblings,
@ -180,5 +200,5 @@ export {
getHomePage,
getNavChildren,
getCurrentVersion,
setCurrentNode
setCurrentPath
};

View File

@ -1,6 +1,6 @@
import { ReactElement, createElement } from 'react';
import ChildrenOf from '../components/ChildrenOf';
import { getCurrentNode } from '../utils/nodes';
import { getCurrentNode } from './nodes';
/**
* Turn [CHILDREN ... ] into a proper React component.

338
userhelp-imports.js Normal file
View File

@ -0,0 +1,338 @@
module.exports = [
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--versionedfiles`,
remote: `https://github.com/silverstripe-australia/silverstripe-versionedfiles`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* advancedworkflow ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--setting_up_advancedworkflow`,
remote: `https://github.com/symbiote/silverstripe-advancedworkflow`,
branch: `4`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--setting_up_advancedworkflow`,
remote: `https://github.com/symbiote/silverstripe-advancedworkflow`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* registry ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--online_databases_and_registries`,
remote: `https://github.com/silverstripe/silverstripe-registry`,
branch: `1.0`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--online_databases_and_registries`,
remote: `https://github.com/silverstripe/silverstripe-registry`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* forum ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--forums`,
remote: `https://github.com/silverstripe/silverstripe-forum`,
branch: `0.8`,
patterns: `docs/en/userguide/**`
}
},
/******* contentreview ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--content_review`,
remote: `https://github.com/silverstripe/silverstripe-contentreview`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* blog ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--blogs`,
remote: `https://github.com/silverstripe/silverstripe-blog`,
branch: `2`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--blogs`,
remote: `https://github.com/silverstripe/silverstripe-blog`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* userforms ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--forms`,
remote: `https://github.com/silverstripe/silverstripe-userforms`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* translatable ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--working_with_translations`,
remote: `https://github.com/silverstripe/silverstripe-translatable`,
branch: `2.1`,
patterns: `docs/en/userguide/**`
}
},
/******* subsites ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--working_with_multiple_websites`,
remote: `https://github.com/silverstripe/silverstripe-subsites`,
branch: `1.1`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--working_with_multiple_websites`,
remote: `https://github.com/silverstripe/silverstripe-subsites`,
branch: `1.1`,
patterns: `docs/en/userguide/**`
}
},
/******* secureassets ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--securing_files`,
remote: `https://github.com/silverstripe/silverstripe-secureassets`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* taxonomy ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--taxonomies`,
remote: `https://github.com/silverstripe/silverstripe-taxonomy`,
branch: `1`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--taxonomies`,
remote: `https://github.com/silverstripe/silverstripe-taxonomy`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* iframe ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--iframe`,
remote: `https://github.com/silverstripe/silverstripe-iframe`,
branch: `1.0`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--iframe`,
remote: `https://github.com/silverstripe/silverstripe-iframe`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* versionfeed ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--site_wide_rss_feeds`,
remote: `https://github.com/silverstripe/silverstripe-versionfeed`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--site_wide_rss_feeds`,
remote: `https://github.com/silverstripe/silverstripe-versionfeed`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* dms ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--document_management_system`,
remote: `https://github.com/silverstripe/silverstripe-dms`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* elemental ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--content_blocks`,
remote: `https://github.com/dnadesign/silverstripe-elemental`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* maintenance ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--modules_report`,
remote: `https://github.com/bringyourownideas/silverstripe-maintenance`,
branch: `1`,
patterns: `docs/en/userguide/**`
}
},
/******* sharedraftcontent ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--share_draft_content`,
remote: `https://github.com/silverstripe/silverstripe-sharedraftcontent`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* documentconverter ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--document_converter`,
remote: `https://github.com/silverstripe/silverstripe-documentconverter`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* ckan-registry ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--ckan_registry`,
remote: `https://github.com/silverstripe/silverstripe-ckan-registry`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* mfa ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--multi-factor_authentication`,
remote: `https://github.com/silverstripe/silverstripe-mfa`,
branch: `master`,
patterns: `docs/en/userguide/**`
}
}
];