diff --git a/docs-tools b/docs-tools index 0462c619d..5fc12d302 160000 --- a/docs-tools +++ b/docs-tools @@ -1 +1 @@ -Subproject commit 0462c619d6b8f7f5036faa5751687509d8f8fb73 +Subproject commit 5fc12d302ef48cada139ec0ec63eb53c9cf00435 diff --git a/package.json b/package.json index 081c365b2..db143cab3 100644 --- a/package.json +++ b/package.json @@ -36,12 +36,8 @@ }, "lint-staged": { "*.js": [ - "eslint --fix", - "prettier --write", - "git add" - ], - "*.{json,md,mdx}": [ - "prettier --write", + "npm run format:fix", + "npm run lint:fix", "git add" ] }, diff --git a/src/components/ComponentFactory.js b/src/components/ComponentFactory.js index 1a67dd972..ec1335271 100644 --- a/src/components/ComponentFactory.js +++ b/src/components/ComponentFactory.js @@ -47,27 +47,26 @@ import Subscript from './Subscript'; import Superscript from './Superscript'; import Image from './Image'; import RefRole from './RefRole'; +import Target from './Target'; +import RoleAbbr from './Roles/Abbr'; import RoleClass from './Roles/Class'; import RoleDoc from './Roles/Doc'; +import RoleFile from './Roles/File'; import RoleGUILabel from './Roles/GUILabel'; -import RoleProgram from './Roles/Program'; -import RoleRef from './Roles/Ref'; -import RoleTerm from './Roles/Term'; const IGNORED_NAMES = ['default-domain', 'toctree']; -const IGNORED_TYPES = ['comment', 'substitution_definition', 'target']; +const IGNORED_TYPES = ['comment', 'substitution_definition']; export default class ComponentFactory extends Component { constructor() { super(); this.roles = { + abbr: RoleAbbr, class: RoleClass, doc: RoleDoc, + file: RoleFile, guilabel: RoleGUILabel, - program: RoleProgram, - ref: RoleRef, - term: RoleTerm, }; this.componentMap = { admonition: Admonition, @@ -111,6 +110,7 @@ export default class ComponentFactory extends Component { superscript: Superscript, tabs: Tabs, 'tabs-pillstrip': TabsPillstrip, + target: Target, text: Text, title_reference: TitleReference, topic: Topic, diff --git a/src/components/DocumentBody.js b/src/components/DocumentBody.js index 23c5f4bac..ed6ef7baf 100644 --- a/src/components/DocumentBody.js +++ b/src/components/DocumentBody.js @@ -3,7 +3,15 @@ import PropTypes from 'prop-types'; import ComponentFactory from './ComponentFactory'; import { getNestedValue } from '../utils/get-nested-value'; -const DocumentBody = ({ addPillstrip, footnotes, pillstrips, refDocMapping, slugTitleMapping, substitutions }) => { +const DocumentBody = ({ + addPillstrip, + footnotes, + pillstrips, + refDocMapping, + slug, + slugTitleMapping, + substitutions, +}) => { const pageNodes = getNestedValue(['ast', 'children'], refDocMapping) || []; return ( @@ -15,6 +23,7 @@ const DocumentBody = ({ addPillstrip, footnotes, pillstrips, refDocMapping, slug nodeData={child} refDocMapping={refDocMapping} pillstrips={pillstrips} + slug={slug} slugTitleMapping={slugTitleMapping} substitutions={substitutions} /> @@ -32,6 +41,7 @@ DocumentBody.propTypes = { children: PropTypes.array, }).isRequired, }).isRequired, + slug: PropTypes.string.isRequired, slugTitleMapping: PropTypes.objectOf(PropTypes.oneOfType([PropTypes.array, PropTypes.string])), substitutions: PropTypes.objectOf(PropTypes.array), }; diff --git a/src/components/Link.js b/src/components/Link.js index 8c3ed76b5..ffd829fab 100644 --- a/src/components/Link.js +++ b/src/components/Link.js @@ -11,10 +11,13 @@ import { isPreviewMode } from '../utils/is-preview-mode'; // Since DOM elements cannot receive activeClassName and partiallyActive, // destructure the prop here and pass it only to GatsbyLink. const Link = ({ children, to, activeClassName, partiallyActive, ...other }) => { + if (!to) to = ''; // Assume that external links begin with http:// or https:// const external = /^http(s)?:\/\//.test(to); + const anchor = to.startsWith('#'); + // Use Gatsby Link for internal links, and for others - if (!isPreviewMode() && to && !external) { + if (!isPreviewMode() && to && !external && !anchor) { if (!to.startsWith('/')) to = `/${to}`; return ( diff --git a/src/components/RefRole.js b/src/components/RefRole.js index 1f8d09d2b..f4ac5d464 100644 --- a/src/components/RefRole.js +++ b/src/components/RefRole.js @@ -1,6 +1,43 @@ import React from 'react'; +import PropTypes from 'prop-types'; +import ComponentFactory from './ComponentFactory'; +import Link from './Link'; -// TODO: Properly render ref_role nodes with links and labels -const RefRole = () => RefRole; +const RefRole = ({ nodeData: { children, domain, fileid, name, target, url }, slug }) => { + // Render intersphinx target links + if (url) { + return ( + + {children.map((node, i) => ( + + ))} + + ); + } + + // Render internal target links + const link = fileid === slug ? `#${target}` : `${fileid}#${target}`; + return ( + + + {children.map((node, i) => ( + + ))} + + + ); +}; + +RefRole.propTypes = { + nodeData: PropTypes.shape({ + children: PropTypes.arrayOf(PropTypes.node).isRequired, + domain: PropTypes.string.isRequired, + fileid: PropTypes.string, + name: PropTypes.string.isRequired, + target: PropTypes.string.isRequired, + url: PropTypes.string, + }).isRequired, + slug: PropTypes.string.isRequired, +}; export default RefRole; diff --git a/src/components/Reference.js b/src/components/Reference.js index d516b2cb5..2ab3530b8 100644 --- a/src/components/Reference.js +++ b/src/components/Reference.js @@ -1,22 +1,21 @@ import React from 'react'; import PropTypes from 'prop-types'; +import ComponentFactory from './ComponentFactory'; import Link from './Link'; -import { getNestedValue } from '../utils/get-nested-value'; -const Reference = ({ nodeData }) => ( - - {getNestedValue(['children', 0, 'value'], nodeData)} - -); +const Reference = ({ nodeData }) => { + return ( + + {nodeData.children.map((element, index) => ( + + ))} + + ); +}; Reference.propTypes = { nodeData: PropTypes.shape({ - children: PropTypes.arrayOf( - PropTypes.shape({ - type: PropTypes.string.isRequired, - value: PropTypes.string, - }) - ).isRequired, + children: PropTypes.array.isRequired, refuri: PropTypes.string.isRequired, }).isRequired, }; diff --git a/src/components/Roles/Abbr.js b/src/components/Roles/Abbr.js new file mode 100644 index 000000000..089960ac8 --- /dev/null +++ b/src/components/Roles/Abbr.js @@ -0,0 +1,29 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const Abbr = ({ + nodeData: { + children: [{ value }], + }, +}) => { + if (!value) { + return null; + } + + // Abbreviations appear as "ABBR (Full Name Here)", so separate this into `abbr` and `expansion` + let [abbr, expansion] = value.split('('); + expansion = expansion.split(')')[0]; + return {abbr}; +}; + +Abbr.propTypes = { + nodeData: PropTypes.shape({ + children: PropTypes.arrayOf( + PropTypes.shape({ + value: PropTypes.string.isRequired, + }) + ).isRequired, + }).isRequired, +}; + +export default Abbr; diff --git a/src/components/Roles/Api.js b/src/components/Roles/Api.js deleted file mode 100644 index a51719a79..000000000 --- a/src/components/Roles/Api.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -const RoleApi = ({ - nodeData: { - label: { value }, - name, - target, - }, -}) => { - let href; - if (name === 'java-sync-api') { - href = `http://mongodb.github.io/mongo-java-driver/3.7/javadoc/${target}`; - } else if (name === 'csharp-api') { - href = `https://mongodb.github.io/mongo-csharp-driver/2.5/apidocs/html/${target}.htm`; - } - - return ( - - {value} - - ); -}; - -RoleApi.propTypes = { - nodeData: PropTypes.shape({ - label: PropTypes.shape({ - value: PropTypes.string.isRequired, - }).isRequired, - name: PropTypes.oneOf(['java-sync-api', 'csharp-api']).isRequired, - target: PropTypes.string.isRequired, - }).isRequired, -}; - -export default RoleApi; diff --git a/src/components/Roles/Class.js b/src/components/Roles/Class.js index 6ca0ddfd8..b0b311d36 100644 --- a/src/components/Roles/Class.js +++ b/src/components/Roles/Class.js @@ -1,25 +1,18 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { getNestedValue } from '../../utils/get-nested-value'; +import ComponentFactory from '../ComponentFactory'; -const baseUrl = 'https://api.mongodb.com/python/current/api/pymongo/results.html#'; -const RoleClass = ({ nodeData: { label, target } }) => { - const labelDisplay = getNestedValue(['value'], label) || target; - return ( - - - {labelDisplay} - - - ); -}; +const RoleClass = ({ nodeData: { children, target } }) => ( + + {children.map((node, i) => ( + + ))} + +); RoleClass.propTypes = { nodeData: PropTypes.shape({ - label: PropTypes.shape({ - value: PropTypes.string, - }), - target: PropTypes.string.isRequired, + children: PropTypes.arrayOf(PropTypes.node).isRequired, }).isRequired, }; diff --git a/src/components/Roles/Doc.js b/src/components/Roles/Doc.js index 23a7a2f59..705087d39 100644 --- a/src/components/Roles/Doc.js +++ b/src/components/Roles/Doc.js @@ -4,13 +4,10 @@ import { formatText } from '../../utils/format-text'; import { getNestedValue } from '../../utils/get-nested-value'; import Link from '../Link'; -const RoleDoc = ({ nodeData: { label, target }, slugTitleMapping }) => { - let labelDisplay = getNestedValue(['value'], label); - if (!labelDisplay) { - const key = target.startsWith('/') ? target.slice(1) : target; - const text = getNestedValue([key], slugTitleMapping); - labelDisplay = text ? formatText(slugTitleMapping[key]) : target; - } +const RoleDoc = ({ nodeData: { target }, slugTitleMapping }) => { + const key = target.startsWith('/') ? target.slice(1) : target; + const text = getNestedValue([key], slugTitleMapping); + const labelDisplay = text ? formatText(slugTitleMapping[key]) : target; return ( diff --git a/src/components/Roles/File.js b/src/components/Roles/File.js new file mode 100644 index 000000000..274f1098a --- /dev/null +++ b/src/components/Roles/File.js @@ -0,0 +1,21 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ComponentFactory from '../ComponentFactory'; + +const RoleFile = ({ nodeData: { children } }) => ( + + + {children.map((node, i) => ( + + ))} + + +); + +RoleFile.propTypes = { + nodeData: PropTypes.shape({ + children: PropTypes.arrayOf(PropTypes.node).isRequired, + }).isRequired, +}; + +export default RoleFile; diff --git a/src/components/Roles/GUILabel.js b/src/components/Roles/GUILabel.js index 180310188..8c8da50b5 100644 --- a/src/components/Roles/GUILabel.js +++ b/src/components/Roles/GUILabel.js @@ -1,17 +1,18 @@ import React from 'react'; import PropTypes from 'prop-types'; +import ComponentFactory from '../ComponentFactory'; -const RoleGUILabel = ({ - nodeData: { - label: { value }, - }, -}) => {value}; +const RoleGUILabel = ({ nodeData: { children } }) => ( + + {children.map((node, i) => ( + + ))} + +); RoleGUILabel.propTypes = { nodeData: PropTypes.shape({ - label: PropTypes.shape({ - value: PropTypes.string.isRequired, - }).isRequired, + children: PropTypes.array.isRequired, }).isRequired, }; diff --git a/src/components/Roles/Manual.js b/src/components/Roles/Manual.js index fe845189c..41f362635 100644 --- a/src/components/Roles/Manual.js +++ b/src/components/Roles/Manual.js @@ -1,23 +1,21 @@ import React from 'react'; import PropTypes from 'prop-types'; +import ComponentFactory from '../ComponentFactory'; import { REF_TARGETS } from '../../constants'; -import { getNestedValue } from '../../utils/get-nested-value'; -const RoleManual = ({ nodeData: { label, target } }) => { - const labelDisplay = getNestedValue(['value'], label) || target; +const RoleManual = ({ nodeData: { children, target } }) => { return ( - {labelDisplay} + {children.map((node, i) => ( + + ))} ); }; RoleManual.propTypes = { nodeData: PropTypes.shape({ - label: PropTypes.shape({ - value: PropTypes.string, - }), - target: PropTypes.string.isRequired, + children: PropTypes.arrayOf(PropTypes.node).isRequired, }).isRequired, }; diff --git a/src/components/Roles/Program.js b/src/components/Roles/Program.js deleted file mode 100644 index e5b904028..000000000 --- a/src/components/Roles/Program.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { getNestedValue } from '../../utils/get-nested-value'; - -const RoleProgram = ({ nodeData: { label, target } }) => { - const labelDisplay = getNestedValue(['value'], label) || target; - return {labelDisplay}; -}; - -RoleProgram.propTypes = { - nodeData: PropTypes.shape({ - label: PropTypes.shape({ - value: PropTypes.string, - }), - target: PropTypes.string.isRequired, - }).isRequired, -}; - -export default RoleProgram; diff --git a/src/components/Roles/Ref.js b/src/components/Roles/Ref.js deleted file mode 100644 index 9806b2e71..000000000 --- a/src/components/Roles/Ref.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { REF_LABELS, REF_TARGETS } from '../../constants'; -import { getNestedValue } from '../../utils/get-nested-value'; - -const RoleRef = ({ nodeData: { label, target } }) => { - let labelDisplay; - if (label) { - labelDisplay = getNestedValue(['value'], label) || target; - } else { - labelDisplay = REF_LABELS[target] || target; - } - // make sure target is hardcoded in list for now - // TODO: chat w andrew about how to move forward with sphinx inventory files - if (!REF_TARGETS[target]) { - console.error(`ERROR: ROLE TARGET DOES NOT EXIST => ${target}`); - return ''; - } - return ( - - {labelDisplay} - - ); -}; - -RoleRef.propTypes = { - nodeData: PropTypes.shape({ - label: PropTypes.shape({ - value: PropTypes.string, - }), - target: PropTypes.string.isRequired, - }).isRequired, -}; - -export default RoleRef; diff --git a/src/components/Roles/Term.js b/src/components/Roles/Term.js deleted file mode 100644 index c82276262..000000000 --- a/src/components/Roles/Term.js +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { REF_TARGETS } from '../../constants'; -import { getNestedValue } from '../../utils/get-nested-value'; - -const RoleTerm = ({ nodeData: { label, target } }) => { - const labelDisplay = getNestedValue(['value'], label) || target; - return ( - - {labelDisplay} - - ); -}; - -RoleTerm.propTypes = { - nodeData: PropTypes.shape({ - label: PropTypes.shape({ - value: PropTypes.string, - }), - target: PropTypes.string.isRequired, - }).isRequired, -}; - -export default RoleTerm; diff --git a/src/components/Target.js b/src/components/Target.js new file mode 100644 index 000000000..a5844a49d --- /dev/null +++ b/src/components/Target.js @@ -0,0 +1,58 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ComponentFactory from './ComponentFactory'; + +const Target = ({ nodeData: { children, name, target } }) => { + // Identify special child nodes (target_ref_title and directive_argument) and render properly. + // Render the remaining children nodes as standard children. + const childNodes = []; + let targetRefTitle, + directiveArgument = null; + children.forEach(node => { + if (node.type === 'target_ref_title') { + targetRefTitle = ; + } else if (node.type === 'directive_argument') { + directiveArgument = ( +
+ {node.children.map((child, j) => ( + + ))} + + ΒΆ + +
+ ); + } else { + childNodes.push(node); + } + }); + + const renderDictList = directiveArgument || childNodes.length > 0; + return ( + + {targetRefTitle} + {renderDictList && ( +
+ {directiveArgument} + {childNodes.length > 0 && ( +
+ {children.map((node, i) => ( + + ))} +
+ )} +
+ )} +
+ ); +}; + +Target.propTypes = { + nodeData: PropTypes.shape({ + children: PropTypes.arrayOf(PropTypes.node).isRequired, + name: PropTypes.string.isRequired, + target: PropTypes.string.isRequired, + }).isRequired, +}; + +export default Target; diff --git a/src/components/VersionDropdown.js b/src/components/VersionDropdown.js index a0dfafbf9..39e4a2b33 100644 --- a/src/components/VersionDropdown.js +++ b/src/components/VersionDropdown.js @@ -67,7 +67,7 @@ const VersionDropdown = ({ title="Select version" > {prefixVersion(currentBranch)} - + {!hidden && (