Skip to content

Commit

Permalink
DOCSP-8430: Improve role rendering (#154)
Browse files Browse the repository at this point in the history
  • Loading branch information
sophstad authored Feb 11, 2020
1 parent a655dbb commit 1ff41f4
Show file tree
Hide file tree
Showing 38 changed files with 296 additions and 460 deletions.
8 changes: 2 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
]
},
Expand Down
14 changes: 7 additions & 7 deletions src/components/ComponentFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 11 additions & 1 deletion src/components/DocumentBody.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<React.Fragment>
Expand All @@ -15,6 +23,7 @@ const DocumentBody = ({ addPillstrip, footnotes, pillstrips, refDocMapping, slug
nodeData={child}
refDocMapping={refDocMapping}
pillstrips={pillstrips}
slug={slug}
slugTitleMapping={slugTitleMapping}
substitutions={substitutions}
/>
Expand All @@ -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),
};
Expand Down
5 changes: 4 additions & 1 deletion src/components/Link.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import { isPreviewMode } from '../utils/is-preview-mode';
// Since DOM elements <a> 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 <a> for others
if (!isPreviewMode() && to && !external) {
if (!isPreviewMode() && to && !external && !anchor) {
if (!to.startsWith('/')) to = `/${to}`;
return (
<GatsbyLink to={to} activeClassName={activeClassName} partiallyActive={partiallyActive} {...other}>
Expand Down
41 changes: 39 additions & 2 deletions src/components/RefRole.js
Original file line number Diff line number Diff line change
@@ -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 = () => <span>RefRole</span>;
const RefRole = ({ nodeData: { children, domain, fileid, name, target, url }, slug }) => {
// Render intersphinx target links
if (url) {
return (
<Link to={url} className="reference external">
{children.map((node, i) => (
<ComponentFactory key={i} nodeData={node} />
))}
</Link>
);
}

// Render internal target links
const link = fileid === slug ? `#${target}` : `${fileid}#${target}`;
return (
<Link to={link} className="reference internal">
<span className={`${domain} ${domain}-ref`}>
{children.map((node, i) => (
<ComponentFactory key={i} nodeData={node} />
))}
</span>
</Link>
);
};

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;
23 changes: 11 additions & 12 deletions src/components/Reference.js
Original file line number Diff line number Diff line change
@@ -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 }) => (
<Link className="reference external" to={nodeData.refuri}>
{getNestedValue(['children', 0, 'value'], nodeData)}
</Link>
);
const Reference = ({ nodeData }) => {
return (
<Link className="reference external" to={nodeData.refuri}>
{nodeData.children.map((element, index) => (
<ComponentFactory key={index} nodeData={element} />
))}
</Link>
);
};

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,
};
Expand Down
29 changes: 29 additions & 0 deletions src/components/Roles/Abbr.js
Original file line number Diff line number Diff line change
@@ -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 title={expansion}>{abbr}</abbr>;
};

Abbr.propTypes = {
nodeData: PropTypes.shape({
children: PropTypes.arrayOf(
PropTypes.shape({
value: PropTypes.string.isRequired,
})
).isRequired,
}).isRequired,
};

export default Abbr;
35 changes: 0 additions & 35 deletions src/components/Roles/Api.js

This file was deleted.

25 changes: 9 additions & 16 deletions src/components/Roles/Class.js
Original file line number Diff line number Diff line change
@@ -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 (
<a href={`${baseUrl}${target}`} className="reference external">
<code className="xref py py-class docutils literal notranslate">
<span className="pre">{labelDisplay}</span>
</code>
</a>
);
};
const RoleClass = ({ nodeData: { children, target } }) => (
<a href={`${target}`} className="reference external">
{children.map((node, i) => (
<ComponentFactory key={i} nodeData={node} />
))}
</a>
);

RoleClass.propTypes = {
nodeData: PropTypes.shape({
label: PropTypes.shape({
value: PropTypes.string,
}),
target: PropTypes.string.isRequired,
children: PropTypes.arrayOf(PropTypes.node).isRequired,
}).isRequired,
};

Expand Down
11 changes: 4 additions & 7 deletions src/components/Roles/Doc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<Link to={target} className="reference internal">
Expand Down
21 changes: 21 additions & 0 deletions src/components/Roles/File.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import PropTypes from 'prop-types';
import ComponentFactory from '../ComponentFactory';

const RoleFile = ({ nodeData: { children } }) => (
<code className="file docutils literal">
<span className="pre">
{children.map((node, i) => (
<ComponentFactory key={i} nodeData={node} />
))}
</span>
</code>
);

RoleFile.propTypes = {
nodeData: PropTypes.shape({
children: PropTypes.arrayOf(PropTypes.node).isRequired,
}).isRequired,
};

export default RoleFile;
17 changes: 9 additions & 8 deletions src/components/Roles/GUILabel.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React from 'react';
import PropTypes from 'prop-types';
import ComponentFactory from '../ComponentFactory';

const RoleGUILabel = ({
nodeData: {
label: { value },
},
}) => <span className="guilabel">{value}</span>;
const RoleGUILabel = ({ nodeData: { children } }) => (
<span className="guilabel">
{children.map((node, i) => (
<ComponentFactory key={i} nodeData={node} />
))}
</span>
);

RoleGUILabel.propTypes = {
nodeData: PropTypes.shape({
label: PropTypes.shape({
value: PropTypes.string.isRequired,
}).isRequired,
children: PropTypes.array.isRequired,
}).isRequired,
};

Expand Down
14 changes: 6 additions & 8 deletions src/components/Roles/Manual.js
Original file line number Diff line number Diff line change
@@ -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 (
<a href={`${REF_TARGETS.manual}${target.replace('/manual', '')}`} className="reference external">
{labelDisplay}
{children.map((node, i) => (
<ComponentFactory key={i} nodeData={node} />
))}
</a>
);
};

RoleManual.propTypes = {
nodeData: PropTypes.shape({
label: PropTypes.shape({
value: PropTypes.string,
}),
target: PropTypes.string.isRequired,
children: PropTypes.arrayOf(PropTypes.node).isRequired,
}).isRequired,
};

Expand Down
Loading

0 comments on commit 1ff41f4

Please sign in to comment.