Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOP-632: Render options #164

Merged
merged 2 commits into from
Mar 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions src/components/Literal.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import React from 'react';
import PropTypes from 'prop-types';
import { getNestedValue } from '../utils/get-nested-value';
import ComponentFactory from './ComponentFactory';

const Literal = ({ nodeData }) => (
<code className="docutils literal notranslate">
<span className="pre">{getNestedValue(['children', 0, 'value'], nodeData)}</span>
const Literal = ({ nodeData: { children } }) => (
<code>
{children.map((node, i) => (
<ComponentFactory nodeData={node} key={i} />
))}
</code>
);

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

Expand Down
105 changes: 68 additions & 37 deletions src/components/Target.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,79 @@
import React from 'react';
import PropTypes from 'prop-types';
import ComponentFactory from './ComponentFactory';
import { getNestedValue } from '../utils/get-nested-value';

// Based on condition isValid, split array into two arrays: [[valid, invalid]]
const partition = (array, isValid) => {
return array.reduce(
([pass, fail], elem) => {
return isValid(elem) ? [[...pass, elem], fail] : [pass, [...fail, elem]];
},
[[], []]
);
};

const TargetIdentifier = ({ nodeData: { ids } }) => (
<React.Fragment>
{ids.map((id, index) => (
<span key={index} id={id} />
))}
</React.Fragment>
);

TargetIdentifier.propTypes = {
nodeData: PropTypes.shape({
ids: PropTypes.arrayOf(PropTypes.string).isRequired,
}).isRequired,
};

const DescriptionTerm = ({ children, targetIdentifiers, ...rest }) => {
const id = getNestedValue([0, 'ids', 0], targetIdentifiers);
return (
<dt id={id}>
{children.map((child, j) => (
<ComponentFactory key={j} {...rest} nodeData={child} />
))}
<a href={`#${id}`} className="headerlink" title="Permalink to this definition">
</a>
</dt>
);
};

DescriptionTerm.propTypes = {
children: PropTypes.arrayOf(PropTypes.object).isRequired,
targetIdentifiers: PropTypes.arrayOf(
PropTypes.shape({
ids: PropTypes.arrayOf(PropTypes.string).isRequired,
})
).isRequired,
};

const Target = ({ nodeData: { children, name, target }, ...rest }) => {
// If directive_argument node is not present, render target_identifiers as empty spans
// Otherwise, render directive_argument as a dictionary node and attach the first
// ID to the description term field
const [targetIdentifiers, dictList] = partition(children, elem => elem.type === 'target_identifier');
const [[descriptionTerm], descriptionDetails] = partition(dictList, elem => elem.type === 'directive_argument');

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 = <span id={target} />;
} else if (node.type === 'directive_argument') {
directiveArgument = (
<dt id={target}>
{node.children.map((child, j) => (
<ComponentFactory key={j} nodeData={child} />
))}
<a href={`#${target}`} className="headerlink" title="Permalink to this definition">
</a>
</dt>
);
} else {
childNodes.push(node);
}
});

const renderDictList = directiveArgument || childNodes.length > 0;
return (
<React.Fragment>
{targetRefTitle}
{renderDictList && (
{dictList.length > 0 ? (
<dl className={name}>
{directiveArgument}
{childNodes.length > 0 && (
<dd>
{children.map((node, i) => (
<ComponentFactory nodeData={node} key={i} />
))}
</dd>
)}
{descriptionTerm && <DescriptionTerm {...rest} {...descriptionTerm} targetIdentifiers={targetIdentifiers} />}
<dd>
{descriptionDetails.map((node, i) => (
<ComponentFactory {...rest} nodeData={node} key={i} />
))}
</dd>
</dl>
) : (
<React.Fragment>
{targetIdentifiers.map((node, i) => (
<TargetIdentifier key={i} nodeData={node} />
))}
</React.Fragment>
)}
</React.Fragment>
);
Expand All @@ -51,7 +83,6 @@ Target.propTypes = {
nodeData: PropTypes.shape({
children: PropTypes.arrayOf(PropTypes.object).isRequired,
name: PropTypes.string.isRequired,
target: PropTypes.string.isRequired,
}).isRequired,
};

Expand Down
16 changes: 16 additions & 0 deletions tests/unit/Target.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { render } from 'enzyme';
import Target from '../../src/components/Target';

// data for this component
import mockData from './data/Target.test.json';

it('renders correctly with a directive_argument node', () => {
const tree = render(<Target nodeData={mockData.a} />);
expect(tree).toMatchSnapshot();
});

it('renders correctly with no directive_argument nodes', () => {
const tree = render(<Target nodeData={mockData.b} />);
expect(tree).toMatchSnapshot();
});
10 changes: 2 additions & 8 deletions tests/unit/__snapshots__/DefinitionList.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,8 @@ exports[`DefinitionList renders correctly 1`] = `
class="first docutils"
>
<dt>
<code
class="docutils literal notranslate"
>
<span
class="pre"
>
MongoDefaultPartitioner
</span>
<code>
MongoDefaultPartitioner
</code>
</dt>
<dd>
Expand Down
23 changes: 15 additions & 8 deletions tests/unit/__snapshots__/Literal.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly 1`] = `
<code
className="docutils literal notranslate"
>
<span
className="pre"
>
N. Virginia (us-east-1)
</span>
<code>
<ComponentFactory
key="0"
nodeData={
Object {
"position": Object {
"start": Object {
"line": 3,
},
},
"type": "text",
"value": "N. Virginia (us-east-1)",
}
}
/>
</code>
`;
49 changes: 49 additions & 0 deletions tests/unit/__snapshots__/Target.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly with a directive_argument node 1`] = `
<dl
class="option"
>
<dt
id="--config"
>
<code>
--config &lt;filename&gt;, -f &lt;filename&gt;
</code>
<a
class="headerlink"
href="#--config"
title="Permalink to this definition"
>
</a>
</dt>
<dd>
<p>
Specifies a configuration file for runtime configuration options. The
configuration file is the preferred method for runtime configuration of
mongos. The options are equivalent to the command-line
configuration options. See
<a
class="reference internal"
href="/reference/configuration-options"
>
/reference/configuration-options
</a>
for
more information.
</p>
<p>
Ensure the configuration file uses ASCII encoding. The mongos
instance does not support configuration files with non-ASCII encoding,
including UTF-8.
</p>
</dd>
</dl>
`;

exports[`renders correctly with no directive_argument nodes 1`] = `
<span
id="php-language-center"
/>
`;
Loading