Initial commit of userdocs merge

This commit is contained in:
Aaron Carlino 2019-12-13 10:52:39 +13:00
parent 8fee23cd54
commit c4f5133531
22 changed files with 658 additions and 441 deletions

View File

@ -2,8 +2,9 @@
# doc.silverstripe.org # doc.silverstripe.org
This repository contains the source code powering [SilverStripe's This repository contains the source code powering [the Silverstripe CMS
developer documentation website](https://docs.silverstripe.org). developer documentation website](https://docs.silverstripe.org) and
[userhelp website](https://userhelp.silverstripe.org).
This application is build on [Gatsby](https://gatsbyjs.com), a static This application is build on [Gatsby](https://gatsbyjs.com), a static
site generator based on [React](https://reactjs.org). It sources content site generator based on [React](https://reactjs.org). It sources content
@ -61,6 +62,20 @@ gatsby serve
These commands will give you an exact representation of how the site will run on a production server, with These commands will give you an exact representation of how the site will run on a production server, with
statically generated html files and server-side rendering. statically generated html files and server-side rendering.
## Toggling between docs and userhelp
Whether the application uses the `docs.silverstripe.org` content or `userhelp.silverstripe.org` is determined
by the environment variable, `DOCS_CONTEXT`. You can set this in the `.env.development` file, or use one of
the script shortcuts:
```
yarn dev-docs
yarn dev-user
yarn build-docs
yarn build-user
```
## Developing ## Developing
From within `path/to/ssdocs`, run the command From within `path/to/ssdocs`, run the command
@ -85,7 +100,7 @@ your content changes, since the remote repositories are the source of truth.
## Deploying content changes ## Deploying content changes
Once your contribution has been merged into the master branch, it will be deployed to production via a Once your contribution has been merged into the master branch, it will be deployed to production via a
Github action in the `silverstripe-framework` repository. Github action in the repository that holds the markdown files (e.g. `silverstripe/silverstripe-framework` for docs).
## Deploying app changes ## Deploying app changes
@ -93,11 +108,12 @@ Once your change is merged in to the `master` branch of this repository, it will
## Contribution ## Contribution
To contribute an improvement to the https://docs.silverstripe.org functionality or To contribute an improvement to the https://docs.silverstripe.org or https://userhelp.silverstripe.org functionality or
theme, submit a pull request on the [GitHub project](https://github.com/silverstripe/doc.silverstripe.org). Any approved pull requests will make theme, submit a pull request on the [GitHub project](https://github.com/silverstripe/doc.silverstripe.org). Any approved pull requests will make
their way onto the https://docs.silverstripe.org site in the next release. their way onto the https://docs.silverstripe.org or https://userhelp.silverstripe.org sites in the next release.
If you wish to edit the documentation content, submit a pull request If you wish to edit the documentation content, submit a pull request
on the on the
[framework Github project](https://github.com/silverstripe/silverstripe-framework). Updated [framework Github project](https://github.com/silverstripe/silverstripe-framework) or the
documentation content is uploaded daily to [doc.silverstripe.org](https://docs.silverstripe.org) via a build hook. [userhelp documentation](https://github.com/silverstripe/silverstripe-userhelp-content) repository
or corresponding module.

View File

@ -5,7 +5,6 @@ require('./src/theme/assets/search/algolia.css');
const React = require('react'); const React = require('react');
const Layout = require('./src/components/Layout').default; const Layout = require('./src/components/Layout').default;
const NodeProvider = require('./src/components/NodeProvider').default; const NodeProvider = require('./src/components/NodeProvider').default;
const { setCurrentPath } = require('./src/utils/nodes');
const smoothScroll = require('smooth-scroll'); const smoothScroll = require('smooth-scroll');
if (typeof window !== "undefined") { if (typeof window !== "undefined") {

View File

@ -1,5 +1,7 @@
const path = require('path'); const path = require('path');
const userhelpImports = require('./userhelp-imports'); const sources = process.env.DOCS_CONTEXT === 'user'
? require('./sources-user')
: require('./sources-docs');
module.exports = { module.exports = {
siteMetadata: { siteMetadata: {
@ -14,6 +16,7 @@ module.exports = {
`gatsby-plugin-sass`, `gatsby-plugin-sass`,
`gatsby-plugin-sharp`, `gatsby-plugin-sharp`,
`gatsby-plugin-sitemap`, `gatsby-plugin-sitemap`,
<<<<<<< HEAD
`gatsby-plugin-netlify`, `gatsby-plugin-netlify`,
{ {
resolve: `gatsby-source-git`, resolve: `gatsby-source-git`,
@ -61,13 +64,18 @@ module.exports = {
}, },
// ...userhelpImports // ...userhelpImports
>>>>>>> Docs/userguide switching >>>>>>> Docs/userguide switching
=======
...sources.slice(0, 4),
>>>>>>> Initial commit of userdocs merge
{ {
resolve: `gatsby-source-filesystem`, resolve: `gatsby-source-filesystem`,
options: { options: {
name: `watcher`, name: `watcher`,
path: `${__dirname}/.cache/gatsby-source-git/` // In dev mode, watch all the source files. Otherwise, point it at a meaningless directory
path: `${__dirname}/.cache/gatsby-source-git/`,
} }
}, },
{ {
resolve: 'gatsby-transformer-remark', resolve: 'gatsby-transformer-remark',
options: { options: {
@ -82,12 +90,22 @@ module.exports = {
} }
} }
}, },
`gatsby-remark-copy-linked-files`,
{ {
resolve: `gatsby-remark-images`, resolve: `gatsby-remark-images`,
options: { options: {
maxWidth: 850, maxWidth: 850,
linkImagesToOriginal: false,
}, },
<<<<<<< HEAD
=======
},
{
resolve: `gatsby-remark-copy-linked-files`,
options: {
// Links to markdown files should be considered links to pages, not downloads.
ignoreFileExtensions: [`md`],
}
>>>>>>> Initial commit of userdocs merge
}, },
] ]
} }

View File

@ -3,15 +3,13 @@ const fs = require('fs');
const { createFilePath } = require(`gatsby-source-filesystem`); const { createFilePath } = require(`gatsby-source-filesystem`);
const fileToTitle = require('./src/utils/fileToTitle'); const fileToTitle = require('./src/utils/fileToTitle');
const createSlug = ({path, version, category, thirdparty}) => { const createSlug = ({path, version, thirdparty}) => {
const [_, lang, ...rest] = path.split('/'); const rest = path.split('/');
const parts = [ const parts = [
lang, 'en',
version, version,
// use suburl "userhelp" for all user docs // thirdparty modules are explicitly pathed
category === 'user' && 'userhelp', thirdparty,
// thirdparty modules are under /optional_features/ (coupling)
thirdparty && `optional_features/${thirdparty}`,
...rest, ...rest,
].filter(p => p); ].filter(p => p);
@ -33,7 +31,7 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
const fileNode = getNode(node.parent); const fileNode = getNode(node.parent);
const [category, version, thirdparty] = parseName(fileNode.sourceInstanceName); const [category, version, thirdparty] = parseName(fileNode.sourceInstanceName);
// The gatsby-source-filesystem plugins are registered to collect from the same path // The gatsby-sgatsbource-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) // that the git source writes to, so we get the watch task (hot reload on content changes)
// But we don't want duplicate document pages for each source plugin, so // But we don't want duplicate document pages for each source plugin, so
// we bail out if we already have the file. However, we need to ensure // we bail out if we already have the file. However, we need to ensure
@ -47,14 +45,14 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
// Pair the document with its watched file so we can inject it into the template // Pair the document with its watched file so we can inject it into the template
// as a dependency. // as a dependency.
existing.watchFile___NODE = node.id; existing.watchFile___NODE = node.id;
return;
} }
return;
} }
const basePath = category === 'user' ? `docs/en/userguide` : `docs/en`;
const filePath = createFilePath({ const filePath = createFilePath({
node, node,
getNode, getNode,
basePath: `docs` basePath,
}); });
let fileTitle = path.basename(node.fileAbsolutePath, '.md'); let fileTitle = path.basename(node.fileAbsolutePath, '.md');
const isIndex = fileTitle === 'index'; const isIndex = fileTitle === 'index';
@ -65,12 +63,21 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
const slug = createSlug({ const slug = createSlug({
path: filePath, path: filePath,
version, version,
category,
thirdparty, thirdparty,
}); });
const parentSlug = `${path.resolve(slug, '../')}/`; const parentSlug = `${path.resolve(slug, '../')}/`;
const unhideSelf = false; const unhideSelf = false;
// Most of these don't exist in userhelp, so force them into the schema by un-nulling them.
const frontmatter = {
introduction: ``,
icon: `file-alt`,
iconBrand: ``,
hideChildren: false,
...node.frontmatter,
};
const docData = { const docData = {
isIndex, isIndex,
filePath, filePath,
@ -79,7 +86,11 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
parentSlug, parentSlug,
unhideSelf, unhideSelf,
category, category,
<<<<<<< HEAD
...node.frontmatter, ...node.frontmatter,
=======
...frontmatter,
>>>>>>> Initial commit of userdocs merge
}; };
if (!docData.title || docData.title === '') { if (!docData.title || docData.title === '') {
@ -104,10 +115,16 @@ exports.onCreateNode = async ({ node, getNode, getNodesByType, actions, createNo
}; };
<<<<<<< HEAD
exports.createPages = async ({ actions, graphql, getNodesByType }) => { exports.createPages = async ({ actions, graphql, getNodesByType }) => {
const { createPage, createRedirect } = actions; const { createPage, createRedirect } = actions;
const docTemplate = path.resolve(`src/templates/docs-template.tsx`); const docTemplate = path.resolve(`src/templates/docs-template.tsx`);
=======
exports.createPages = async ({ actions, graphql }) => {
const { createPage } = actions;
const docsTemplate = path.resolve(`src/templates/docs-template.tsx`)
>>>>>>> Initial commit of userdocs merge
const result = await graphql(` const result = await graphql(`
{ {
allSilverstripeDocument { allSilverstripeDocument {
@ -126,7 +143,7 @@ exports.createPages = async ({ actions, graphql, getNodesByType }) => {
.forEach(node => { .forEach(node => {
createPage({ createPage({
path: node.slug, path: node.slug,
component: docTemplate, component: docsTemplate,
context: { context: {
id: node.id, id: node.id,
slug: node.slug, slug: node.slug,

View File

@ -1,7 +1,6 @@
const React = require('react'); const React = require('react');
const Layout = require('./src/components/Layout').default; const Layout = require('./src/components/Layout').default;
const NodeProvider = require('./src/components/NodeProvider').default; const NodeProvider = require('./src/components/NodeProvider').default;
const { setCurrentPath } = require('./src/utils/nodes');
/** /**
* Applies the node provider (static query of all documents) * Applies the node provider (static query of all documents)
@ -9,7 +8,7 @@ const { setCurrentPath } = require('./src/utils/nodes');
*/ */
exports.wrapPageElement = ({ element, props }) => { exports.wrapPageElement = ({ element, props }) => {
return ( return (
<NodeProvider> <NodeProvider {...props}>
<Layout {...props}> <Layout {...props}>
{element} {element}
</Layout> </Layout>
@ -17,9 +16,7 @@ exports.wrapPageElement = ({ element, props }) => {
); );
}; };
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 // 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={{ <style key='prism-css' type="text/css" dangerouslySetInnerHTML={{

View File

@ -74,7 +74,11 @@
"start": "npm run develop", "start": "npm run develop",
"serve": "gatsby serve", "serve": "gatsby serve",
"type-check": "tsc --noEmit", "type-check": "tsc --noEmit",
"lint": "tslint --project ." "lint": "tslint --project .",
"dev-docs": "DOCS_CONTEXT=docs gatsby develop",
"dev-user": "DOCS_CONTEXT=user gatsby develop",
"build-docs": "DOCS_CONTEXT=docs gatsby build",
"build-user": "DOCS_CONTEXT=user gatsby build"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

20
sources-docs.js Normal file
View File

@ -0,0 +1,20 @@
module.exports = [
{
resolve: `gatsby-source-git`,
options: {
name: `docs--4`,
remote: `https://github.com/silverstripe/silverstripe-framework.git`,
branch: `4`,
patterns: `docs/en/**`
}
},
{
resolve: `gatsby-source-git`,
options: {
name: `docs--3`,
remote: `https://github.com/silverstripe/silverstripe-framework.git`,
branch: `3.7`,
patterns: `docs/en/**`
}
},
];

447
sources-user.js Normal file
View File

@ -0,0 +1,447 @@
module.exports = [
/******* main content *********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4`,
remote: `https://github.com/silverstripe/silverstripe-userhelp-content.git`,
//branch: `4`,
branch: `pulls/4/new-docs`,
patterns: `docs/en/**`
}
},
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3`,
remote: `https://github.com/silverstripe/silverstripe-userhelp-content.git`,
//branch: `3`,
branch: `pulls/3/new-docs`,
patterns: `docs/en/**`
}
},
/******* versionedfiles ********/
// v3
{
// Running a fork. Switch remote back once merged.
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/versionedfiles`,
//remote: `https://github.com/silverstripe-australia/silverstripe-versionedfiles`,
remote: `https://github.com/silverstripe/silverstripe-versionedfiles`,
// branch: `master`,
branch: `pulls/master/new-docs`,
patterns: `docs/en/userguide/**`
}
},
/******* advancedworkflow ********/
// v3
{
// Running a fork. Switch remote back once merged.
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/setting_up_advancedworkflow`,
//remote: `https://github.com/symbiote/silverstripe-advancedworkflow`,
//branch: `4`,
remote: `https://github.com/silverstripe/silverstripe-advancedworkflow`,
branch: `pulls/4/new-docs`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/setting_up_advancedworkflow`,
// remote: `https://github.com/symbiote/silverstripe-advancedworkflow`,
// branch: `master`,
remote: `https://github.com/silverstripe/silverstripe-advancedworkflow`,
branch: `pulls/master/new-docs`,
patterns: `docs/en/userguide/**`
}
},
/******* registry ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/online_databases_and_registries`,
remote: `https://github.com/silverstripe/silverstripe-registry`,
//branch: `1.0`,
branch: `pulls/1.0/new-docs`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/online_databases_and_registries`,
remote: `https://github.com/silverstripe/silverstripe-registry`,
// branch: `master`,
branch: `pulls/master/new-docs`,
patterns: `docs/en/userguide/**`
}
},
/******* forum ********/
// v3
{
// Fork. Remove once PR is merged.
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/forums`,
remote: `https://github.com/unclecheese/silverstripe-forum`,
//branch: `0.8`,
branch: `pulls/0.8/new-docs`,
patterns: `docs/en/userguide/**`
}
},
/******* contentreview ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/content_review`,
remote: `https://github.com/silverstripe/silverstripe-contentreview`,
// branch: `master`,
branch: `pulls/master/new-docs`,
patterns: `docs/en/userguide/**`
}
},
/******* blog ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/blogs`,
remote: `https://github.com/silverstripe/silverstripe-blog`,
//branch: `2`,
branch: `pulls/2/new-docs`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/blogs`,
remote: `https://github.com/silverstripe/silverstripe-blog`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* userforms ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/forms`,
remote: `https://github.com/silverstripe/silverstripe-userforms`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* translatable ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/working_with_translations`,
remote: `https://github.com/silverstripe/silverstripe-translatable`,
//branch: `2.1`,
branch: `pulls/2.1/new-docs`,
patterns: `docs/en/userguide/**`
}
},
/******* subsites ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/working_with_multiple_websites`,
remote: `https://github.com/silverstripe/silverstripe-subsites`,
//branch: `1.1`,
branch: `pulls/1.1/new-docs`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/working_with_multiple_websites`,
remote: `https://github.com/silverstripe/silverstripe-subsites`,
//branch: `1.1`,
branch: `pulls/1.1/new-docs`,
patterns: `docs/en/userguide/**`
}
},
/******* secureassets ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/securing_files`,
remote: `https://github.com/silverstripe/silverstripe-secureassets`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* taxonomy ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/taxonomies`,
remote: `https://github.com/silverstripe/silverstripe-taxonomy`,
branch: `pulls/1/new-docs`,
// branch: `1`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/taxonomies`,
remote: `https://github.com/silverstripe/silverstripe-taxonomy`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* iframe ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/iframe`,
remote: `https://github.com/silverstripe/silverstripe-iframe`,
//branch: `1.0`,
branch: `pulls/1.0/new-docs`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/iframe`,
remote: `https://github.com/silverstripe/silverstripe-iframe`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* versionfeed ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/site_wide_rss_feeds`,
remote: `https://github.com/silverstripe/silverstripe-versionfeed`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/site_wide_rss_feeds`,
remote: `https://github.com/silverstripe/silverstripe-versionfeed`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* dms ********/
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--optional_features/document_management_system`,
remote: `https://github.com/silverstripe/silverstripe-dms`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* elemental ********/
// v4
{
// Fork. Replace when PR is merged.
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/content_blocks`,
remote: `https://github.com/dnadesign/silverstripe-elemental`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* maintenance ********/
// v4
{
// Fork. Replace when PR is merged.
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/modules_report`,
//remote: `https://github.com/bringyourownideas/silverstripe-maintenance`,
remote: `https://github.com/silverstripe/silverstripe-maintenance`,
branch: `pulls/1/new-docs`,
// branch: `1`,
patterns: `docs/en/userguide/**`
}
},
/******* sharedraftcontent ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/share_draft_content`,
remote: `https://github.com/silverstripe/silverstripe-sharedraftcontent`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* documentconverter ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/document_converter`,
remote: `https://github.com/silverstripe/silverstripe-documentconverter`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* ckan-registry ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/ckan_registry`,
remote: `https://github.com/silverstripe/silverstripe-ckan-registry`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******* mfa ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--optional_features/multi-factor_authentication`,
remote: `https://github.com/silverstripe/silverstripe-mfa`,
branch: `pulls/master/new-docs`,
// branch: `master`,
patterns: `docs/en/userguide/**`
}
},
/******** securityreport ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--managing_your_website/reports/security_report`,
remote: `https://github.com/silverstripe/silverstripe-securityreport`,
branch: `pulls/master/new-docs`,
//branch: `master`,
patterns: `docs/en/userguide/**`,
}
},
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--managing_your_website/reports/security_report`,
remote: `https://github.com/silverstripe/silverstripe-securityreport`,
branch: `pulls/master/new-docs`,
//branch: `master`,
patterns: `docs/en/userguide/**`,
}
},
/******** sitewide-content-report ********/
// v4
{
resolve: `gatsby-source-git`,
options: {
name: `user--4--managing_your_website/reports/sitewide_content_report`,
remote: `https://github.com/silverstripe/silverstripe-sitewidecontent-report`,
branch: `pulls/master/new-docs`,
//branch: `master`,
patterns: `docs/en/userguide/**`,
}
},
// v3
{
resolve: `gatsby-source-git`,
options: {
name: `user--3--managing_your_website/reports/sitewide_content_report`,
remote: `https://github.com/silverstripe/silverstripe-sitewidecontent-report`,
branch: `pulls/2.0/new-docs`,
//branch: `2.0`,
patterns: `docs/en/userguide/**`,
}
},
];

View File

@ -0,0 +1,35 @@
import React, { StatelessComponent } from 'react';
import { SilverstripeDocument } from '../types';
import SEO from './SEO';
import parseHTML from '../utils/parseHTML';
interface DocsPageProps {
title: string;
html: string;
relPath: string;
branch: string;
gitURL: string;
};
const DocsPage: StatelessComponent<DocsPageProps> = ({ title, html, branch, relPath, gitURL }): ReactElement => {
const editLink = `${gitURL}/edit/${branch}/${relPath}`;
return (
<>
<SEO title={title} />
{parseHTML(html)}
{editLink &&
<div className="github-edit">
<a target="_blank" href={editLink} title="Edit on Github">
<i className="fas fa-pen fa-fw" />{` `}
Edit on Github
</a>
</div>
}
</>
);
};
export default DocsPage;

View File

@ -1,6 +1,6 @@
import React, { StatelessComponent, ReactElement } from 'react'; import React, { StatelessComponent, ReactElement } from 'react';
import SearchBox from './SearchBox'; import SearchBox from './SearchBox';
import { Link } from 'gatsby'; import { Link, navigate } from 'gatsby';
import logo from '../images/silverstripe-logo.svg'; import logo from '../images/silverstripe-logo.svg';
import useHierarchy from '../hooks/useHierarchy'; import useHierarchy from '../hooks/useHierarchy';
@ -25,9 +25,9 @@ const Header: StatelessComponent<HeaderProps> = ({ handleSidebarToggle }): React
const otherNode = getNodes().find(n => n.slug === newPath); const otherNode = getNodes().find(n => n.slug === newPath);
// This has to be a hard refresh, because the sidebar needs to unmount // This has to be a hard refresh, because the sidebar needs to unmount
if (otherNode) { if (otherNode) {
window.location.href = otherNode.slug; navigate(otherNode.slug);
} else { } else {
window.location.href = `/en/${ver}`; navigate(`/en/${ver}`);
} }
} }
}; };

View File

@ -1,6 +1,7 @@
import React, { StatelessComponent, useState, ReactNode } from "react"; import React, { StatelessComponent, useState, useEffect, ReactNode } from "react";
import Header from './Header'; import Header from './Header';
import Sidebar from './Sidebar'; import Sidebar from './Sidebar';
import useHierarchy from '../hooks/useHierarchy';
interface LayoutProps { interface LayoutProps {
children?: ReactNode children?: ReactNode
@ -9,9 +10,10 @@ interface LayoutProps {
} }
} }
const Layout: StatelessComponent<LayoutProps> = ({ children }) => { const Layout: StatelessComponent<LayoutProps> = ({ children }) => {
const { setCurrentPath } = useHierarchy();
const [isToggled, setSidebarOpen] = useState(false); const [isToggled, setSidebarOpen] = useState(false);
const handleNavigate = () => setSidebarOpen(false); const handleNavigate = () => setSidebarOpen(false);
return ( return (
<> <>
<Header handleSidebarToggle={() => setSidebarOpen(!isToggled)} /> <Header handleSidebarToggle={() => setSidebarOpen(!isToggled)} />

View File

@ -25,34 +25,17 @@ const Nav:StatelessComponent<NavProps> = ({ onNavigate }): ReactElement => {
getNavChildren, getNavChildren,
getHomePage, getHomePage,
getCurrentNode, getCurrentNode,
getCurrentCategory,
getCurrentVersion
} = useHierarchy(); } = useHierarchy();
const currentNode = getCurrentNode(); const currentNode = getCurrentNode();
const top = getHomePage(); 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) { if (!top) {
return <nav />; return <nav />;
} }
const topLevel = getNavChildren(top).filter(node => node.category === category); const topLevel = getNavChildren(top);
return ( return (
<nav role="navigation" id="docs-nav" className="docs-nav navbar"> <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"> <ul className="section-items list-unstyled nav flex-column pb-3">
{topLevel.map((node: SilverstripeDocument) => { {topLevel.map((node: SilverstripeDocument) => {
const { slug, title } = node; const { slug, title } = node;

View File

@ -11,12 +11,11 @@ import {
getNodes, getNodes,
getParent, getParent,
getSiblings, getSiblings,
getCurrentCategory,
initialise, initialise,
setCurrentPath, setCurrentPath,
} from '../utils/nodes'; } from '../utils/nodes';
const NodeProvider: StatelessComponent<{}> = ({ children, location: { pathname } }): ReactElement => { const NodeProvider: StatelessComponent<{}> = ({ children, pageContext: { slug } }): ReactElement => {
const result:HierarchyQuery = useStaticQuery(graphql` const result:HierarchyQuery = useStaticQuery(graphql`
{ {
allSilverstripeDocument { allSilverstripeDocument {
@ -42,12 +41,11 @@ const NodeProvider: StatelessComponent<{}> = ({ children, location: { pathname }
const nodes = result.allSilverstripeDocument.nodes.map(node => ({ const nodes = result.allSilverstripeDocument.nodes.map(node => ({
...node, ...node,
})); }));
initialise(nodes); initialise(nodes);
} }
setCurrentPath(pathname);
setCurrentPath(slug);
return ( return (
<NodeContext.Provider value={{ <NodeContext.Provider value={{
getChildren, getChildren,
@ -58,7 +56,6 @@ const NodeProvider: StatelessComponent<{}> = ({ children, location: { pathname }
getNodes, getNodes,
getParent, getParent,
getSiblings, getSiblings,
getCurrentCategory,
}}> }}>
{children} {children}
</NodeContext.Provider> </NodeContext.Provider>

View File

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

View File

@ -31,7 +31,10 @@ const SearchBox: StatelessComponent<SearchBoxProps> = ({ identifier }): ReactEle
if(window.docsearch){ if(window.docsearch){
window.docsearch({ window.docsearch({
algoliaOptions: { algoliaOptions: {
facetFilters: [`version:${getCurrentVersion()}`], facetFilters: [
`version:${getCurrentVersion()}`,
`context:${process.env.DOCS_CONTEXT}`,
],
hitsPerPage: 5, hitsPerPage: 5,
}, },
apiKey: process.env.GATSBY_DOCSEARCH_API_KEY, apiKey: process.env.GATSBY_DOCSEARCH_API_KEY,

View File

@ -12,7 +12,6 @@ interface NodeFunctions {
getHomePage(): SilverstripeDocument|null; getHomePage(): SilverstripeDocument|null;
getNavChildren(node: SilverstripeDocument): SilverstripeDocument[]; getNavChildren(node: SilverstripeDocument): SilverstripeDocument[];
getCurrentVersion(): string; getCurrentVersion(): string;
getCurrentCategory(): string;
setCurrentNode(slug: string): undefined; setCurrentNode(slug: string): undefined;
}; };

View File

@ -1,33 +1,23 @@
import React, { StatelessComponent, ReactElement } from 'react'; import React, { StatelessComponent, ReactElement } from 'react';
import { graphql } from 'gatsby'; import { graphql } from 'gatsby';
import SEO from '../components/SEO'; import DocsPage from '../components/DocsPage';
import { SingleFileQuery } from '../types'; import { SingleFileQuery } from '../types';
import parseHTML from '../utils/parseHTML';
const Template: StatelessComponent<SingleFileQuery> = (result): ReactElement => { const Template: StatelessComponent<SingleFileQuery> = (result): ReactElement => {
const currentNode = result.data.silverstripeDocument; const currentNode = result.data.silverstripeDocument;
let html; const { title, slug } = currentNode;
if (currentNode.watchFile) { const { html } = currentNode.watchFile;
html = currentNode.watchFile.html; const { relativePath, gitRemote } = currentNode.parent.parent;
} else { const { ref, href } = gitRemote;
html = currentNode.parent.html; console.log('rendering the template for ', slug, html.substring(0, 25));
}
const { title } = currentNode;
const { relativePath, gitRemote: { ref, webLink } } = currentNode.parent.parent;
const editLink = `${webLink}/edit/${ref}/${relativePath}`;
return ( return (
<> <DocsPage
<SEO title={title} /> title={title}
{parseHTML(html)} html={html}
<div className="github-edit"> relPath={relativePath}
<a target="_blank" href={editLink} title="Edit on Github"> branch={ref}
<i className="fas fa-pen fa-fw" />{` `} gitURL={href}
Edit on Github />
</a>
</div>
</>
); );
}; };
@ -50,7 +40,6 @@ export const pageQuery = graphql`
relativePath relativePath
gitRemote { gitRemote {
ref ref
webLink
sourceInstanceName sourceInstanceName
} }
} }

View File

@ -15,6 +15,7 @@ export interface SinglePage {
parent: { parent: {
relativePath: string; relativePath: string;
gitRemote: { gitRemote: {
href: string;
ref: string; ref: string;
webLink: string; webLink: string;
} }

View File

@ -3,10 +3,9 @@ import sortFiles from './sortFiles';
let __nodes: SilverstripeDocument[]; let __nodes: SilverstripeDocument[];
let __currentVersion: string | null = null; let __currentVersion: string | null = null;
let __currentCategory: string | null = null;
let __home: SilverstripeDocument | null = null;
let __path: string | null = null; let __path: string | null = null;
const homeMap = new Map();
const childrenMap = new Map(); const childrenMap = new Map();
const navChildrenMap = new Map(); const navChildrenMap = new Map();
const siblingMap = new Map(); const siblingMap = new Map();
@ -161,17 +160,19 @@ const getCurrentNode = (): SilverstripeDocument | null => {
* Get the home page * Get the home page
*/ */
const getHomePage = (): SilverstripeDocument | null => { const getHomePage = (): SilverstripeDocument | null => {
if (__home) {
return __home;
}
const nodes = getNodes(); const nodes = getNodes();
const version = getCurrentVersion(); const version = getCurrentVersion();
let slug = `/en/${version}/`; let slug = `/en/${version}/`;
<<<<<<< HEAD
=======
if (homeMap.has(slug)) {
return homeMap.get(slug) || null;
}
>>>>>>> Initial commit of userdocs merge
const homePage = nodes.find(n => n.slug === slug) || null; const homePage = nodes.find(n => n.slug === slug) || null;
homeMap.set(slug, homePage);
__home = homePage; return homeMap.get(slug);
return __home;
}; };
/** /**
@ -180,14 +181,18 @@ const getHomePage = (): SilverstripeDocument | null => {
const getCurrentVersion = (): string => __currentVersion || '4'; const getCurrentVersion = (): string => __currentVersion || '4';
/** /**
<<<<<<< HEAD
* Set the current node by its slug. * Set the current node by its slug.
* @param slug * @param slug
=======
* Set the current path, with some side effects for version
* @param slug
>>>>>>> Initial commit of userdocs merge
*/ */
const setCurrentPath = (path: string) => { const setCurrentPath = (path: string) => {
__path = path; __path = path || `/`;
const [_, lang, version, category] = path.split('/'); const [_, lang, version] = __path.split('/');
__currentVersion = version; __currentVersion = version;
__currentCategory = category === 'userhelp' ? 'user' : 'docs';
}; };
export { export {

View File

@ -4,12 +4,22 @@ import { Link } from 'gatsby';
import rewriteAPILink from './rewriteAPILink'; import rewriteAPILink from './rewriteAPILink';
import { getCurrentNode, getCurrentVersion } from '../utils/nodes'; import { getCurrentNode, getCurrentVersion } from '../utils/nodes';
import path from 'path'; import path from 'path';
import { SilverstripeDocument } from '../types';
interface LinkAttributes { interface LinkAttributes {
href?: string; href?: string;
}; };
const relativeLink = (currentNode: SilverstripeDocument, href: string): string => {
const slug = path.join(currentNode.isIndex ? currentNode.slug : currentNode.parentSlug, href);
if (!slug.endsWith('/')) {
return `${slug}/`
}
return slug;
};
/** /**
* Ensure links use the Gatsby <Link /> component. Client-side routing FTW * Ensure links use the Gatsby <Link /> component. Client-side routing FTW
* *
@ -80,10 +90,23 @@ const rewriteLink = (
// Relative to page // Relative to page
if (currentNode && currentNode.parentSlug) { if (currentNode && currentNode.parentSlug) {
// Relative links to markdown files should be resolved to their pretty urls.
if (href.endsWith('.md')) {
return createElement(
Link,
{
to: relativeLink(currentNode, href.replace(/\.md$/, '')),
className: 'gatsby-link',
},
domToReact(children, parseOptions)
)
}
return createElement( return createElement(
Link, Link,
{ {
to: path.join(currentNode.parentSlug, href), to: relativeLink(currentNode, href),
className: 'gatsby-link' className: 'gatsby-link'
}, },
domToReact(children, parseOptions) domToReact(children, parseOptions)

View File

@ -2,7 +2,7 @@ import { SilverstripeDocument } from "../types";
const sortFiles = (a: SilverstripeDocument, b: SilverstripeDocument): number => { const sortFiles = (a: SilverstripeDocument, b: SilverstripeDocument): number => {
if (a.isIndex !== b.isIndex) { if (a.isIndex !== b.isIndex) {
return a.isIndex ? -1 : 1; //return a.isIndex ? -1 : 1;
} }
return a.fileAbsolutePath > b.fileAbsolutePath ? 1 : -1; return a.fileAbsolutePath > b.fileAbsolutePath ? 1 : -1;
}; };

View File

@ -1,338 +0,0 @@
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/**`
}
}
];