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

Element: Add types #21248

Merged
merged 14 commits into from
Apr 4, 2020
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"@types/lodash": "4.14.149",
"@types/prettier": "1.19.0",
"@types/qs": "6.9.1",
"@types/react-dom": "16.9.5",
"@types/requestidlecallback": "0.3.1",
"@types/sprintf-js": "1.1.2",
"@wordpress/babel-plugin-import-jsx-pragma": "file:packages/babel-plugin-import-jsx-pragma",
Expand Down
1 change: 1 addition & 0 deletions packages/element/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Master

- Include TypeScript type declarations ([#21248](https://github.com/WordPress/gutenberg/pull/21248))
- Graduated `__experimentalCreateInterpolateElement` function to stable api: `createInterpolateElement` (see [20699](https://github.com/WordPress/gutenberg/pull/20699))

## 2.10.0 (2019-12-19)
Expand Down
18 changes: 8 additions & 10 deletions packages/element/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ _Related_

_Parameters_

- _child_ `WPElement`: Any renderable child, such as an element, string, or fragment.
- _child_ (unknown type): Any renderable child, such as an element, string, or fragment.
- _container_ `HTMLElement`: DOM node into which element should be rendered.

<a name="createRef" href="#createRef">#</a> **createRef**
Expand All @@ -199,7 +199,7 @@ Finds the dom node of a React component.

_Parameters_

- _component_ `WPComponent`: Component's instance.
- _component_ (unknown type): Component's instance.

<a name="forwardRef" href="#forwardRef">#</a> **forwardRef**

Expand Down Expand Up @@ -289,21 +289,19 @@ aside from `children` are passed.

_Parameters_

- _props_ `Object`:
- _props.children_ `string`: HTML to render.
- _props.props_ `Object`: Any additonal props to be set on the containing div.
- _props_ `RawHTMLProps`: Children should be a string of HTML. Other props will be passed through to div wrapper.

_Returns_

- `WPComponent`: Dangerously-rendering component.
- `JSX.Element`: Dangerously-rendering component.

<a name="render" href="#render">#</a> **render**

Renders a given element into the target DOM node.

_Parameters_

- _element_ `WPElement`: Element to render.
- _element_ (unknown type): Element to render.
- _target_ `HTMLElement`: DOM node into which element should be rendered.

<a name="renderToString" href="#renderToString">#</a> **renderToString**
Expand All @@ -312,9 +310,9 @@ Serializes a React element to string.

_Parameters_

- _element_ `WPElement`: Element to serialize.
- _context_ `?Object`: Context object.
- _legacyContext_ `?Object`: Legacy context object.
- _element_ (unknown type): Element to serialize.
- _context_ `[Object]`: Context object.
- _legacyContext_ `[Object]`: Legacy context object.

_Returns_

Expand Down
1 change: 1 addition & 0 deletions packages/element/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"main": "build/index.js",
"module": "build-module/index.js",
"react-native": "src/index",
"types": "build-types",
"sideEffects": false,
"dependencies": {
"@babel/runtime": "^7.8.3",
Expand Down
50 changes: 35 additions & 15 deletions packages/element/src/create-interpolate-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*/
import { createElement, cloneElement, Fragment, isValidElement } from 'react';

/** @typedef {import('./react').WPElement} WPElement */

let indoc, offset, output, stack;

/**
Expand All @@ -22,28 +24,46 @@ let indoc, offset, output, stack;
*/
const tokenizer = /<(\/)?(\w+)\s*(\/)?>/g;

/**
* The stack frame tracking parse progress.
*
* @typedef Frame
*
* @property {WPElement} element A parent element which may still have
* @property {number} tokenStart Offset at which parent element first
* appears.
* @property {number} tokenLength Length of string marking start of parent
* element.
* @property {number} [prevOffset] Running offset at which parsing should
* continue.
* @property {number} [leadingTextStart] Offset at which last closing element
* finished, used for finding text between
* elements.
* @property {WPElement[]} children Children.
*/

/**
* Tracks recursive-descent parse state.
*
* This is a Stack frame holding parent elements until all children have been
* parsed.
*
* @private
* @param {WPElement} element A parent element which may still have
* nested children not yet parsed.
* @param {number} tokenStart Offset at which parent element first
* appears.
* @param {number} tokenLength Length of string marking start of parent
* element.
* @param {number} prevOffset Running offset at which parsing should
* continue.
* @param {number} leadingTextStart Offset at which last closing element
* finished, used for finding text between
* elements
* @param {WPElement} element A parent element which may still have
* nested children not yet parsed.
* @param {number} tokenStart Offset at which parent element first
* appears.
* @param {number} tokenLength Length of string marking start of parent
* element.
* @param {number} [prevOffset] Running offset at which parsing should
* continue.
* @param {number} [leadingTextStart] Offset at which last closing element
* finished, used for finding text between
* elements.
*
* @return {Frame} The stack frame tracking parse progress.
*/
function Frame(
function createFrame(
element,
tokenStart,
tokenLength,
Expand Down Expand Up @@ -175,14 +195,14 @@ function proceed( conversionMap ) {

// otherwise we found an inner element
addChild(
new Frame( conversionMap[ name ], startOffset, tokenLength )
createFrame( conversionMap[ name ], startOffset, tokenLength )
);
offset = startOffset + tokenLength;
return true;

case 'opener':
stack.push(
new Frame(
createFrame(
conversionMap[ name ],
startOffset,
tokenLength,
Expand Down Expand Up @@ -210,7 +230,7 @@ function proceed( conversionMap ) {
);
stackTop.children.push( text );
stackTop.prevOffset = startOffset + tokenLength;
const frame = new Frame(
const frame = createFrame(
stackTop.element,
stackTop.tokenStart,
stackTop.tokenLength,
Expand Down
12 changes: 8 additions & 4 deletions packages/element/src/raw-html.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
*/
import { createElement } from './react';

// Disable reason: JSDoc linter doesn't seem to parse the union (`&`) correctly.
/* eslint-disable jsdoc/valid-types */
/** @typedef {{children: string} & import('react').ComponentPropsWithoutRef<'div'>} RawHTMLProps */
/* eslint-enable jsdoc/valid-types */

/**
* Component used as equivalent of Fragment with unescaped HTML, in cases where
* it is desirable to render dangerous HTML without needing a wrapper element.
* To preserve additional props, a `div` wrapper _will_ be created if any props
* aside from `children` are passed.
*
* @param {Object} props
* @param {string} props.children HTML to render.
* @param {Object} props.props Any additonal props to be set on the containing div.
* @param {RawHTMLProps} props Children should be a string of HTML. Other props
* will be passed through to div wrapper.
*
* @return {WPComponent} Dangerously-rendering component.
* @return {JSX.Element} Dangerously-rendering component.
Comment on lines -16 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wondered how this worked.

Turns out it doesn't:

[0] /home/travis/build/WordPress/gutenberg/packages/element/src/raw-html.js
[0]   20:0  warning  The type 'JSX' is undefined  jsdoc/no-undefined-types

https://travis-ci.com/github/WordPress/gutenberg/jobs/314225929

I thought these rules were upgraded to be errors in #20427. I think this one might have been missed? (cc @sainthkh)

I know we have a handful of temporary exceptions for custom types, but pretty sure those are hard-coded to be exceptions and could still exist even if the rule were upgraded from warning to error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a concern with restoring the element types? #21781

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It happened because I missed this one rule:

'jsdoc/no-undefined-types': [
'warn',

I opened an issue that fixes it: #21942.

*/
export default function RawHTML( { children, ...props } ) {
// The DIV wrapper will be stripped by serializer, unless there are
Expand Down
6 changes: 3 additions & 3 deletions packages/element/src/react-platform.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
*
* @see https://github.com/facebook/react/issues/10309#issuecomment-318433235
*
* @param {WPElement} child Any renderable child, such as an element,
* @param {import('./react').WPElement} child Any renderable child, such as an element,
* string, or fragment.
* @param {HTMLElement} container DOM node into which element should be rendered.
*/
Expand All @@ -22,14 +22,14 @@ export { createPortal };
/**
* Finds the dom node of a React component.
*
* @param {WPComponent} component Component's instance.
* @param {import('./react').WPComponent} component Component's instance.
*/
export { findDOMNode };

/**
* Renders a given element into the target DOM node.
*
* @param {WPElement} element Element to render.
* @param {import('./react').WPElement} element Element to render.
* @param {HTMLElement} target DOM node into which element should be rendered.
*/
export { render };
Expand Down
2 changes: 1 addition & 1 deletion packages/element/src/react.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { isString } from 'lodash';
/**
* Object containing a React component.
*
* @typedef {import('react').Component} WPComponent
* @typedef {import('react').ComponentType} WPComponent
*/

/**
Expand Down
Loading