Skip to content

Commit

Permalink
Merge a45e41f into a748b52
Browse files Browse the repository at this point in the history
  • Loading branch information
Himenon committed Nov 10, 2018
2 parents a748b52 + a45e41f commit b857968
Show file tree
Hide file tree
Showing 23 changed files with 1,021 additions and 291 deletions.
8 changes: 7 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
"request": "launch",
"name": "express:session",
"program": "${workspaceFolder}/lib/express-session/oneshot.js"
}
},
{
"type": "node",
"request": "launch",
"name": "remark:react:latest",
"program": "${workspaceFolder}/lib/remark-react-latest/sample.js"
},
]
}
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
<summary>gray-matter</summary>
https://github.com/jonschlinkert/gray-matter
</details>
<details>
<summary>mdx</summary>
<p>https://github.com/mdx-js/mdx</p>
<p>@mdx-js/tag: https://github.com/mdx-js/mdx/tree/master/packages/tag</p>
<p>@mdx-js/mdx: https://github.com/mdx-js/mdx/tree/master/packages/mdx</p>
</details>
<details>
<summary>remark</summary>
https://github.com/gnab/remark
Expand All @@ -32,6 +38,10 @@
<summary>remark-react</summary>
https://github.com/mapbox/remark-react
</details>
<details>
<summary>remark-rehype</summary>
https://github.com/remarkjs/remark-rehype
</details>
<details>
<summary>section-matter</summary>
https://github.com/jonschlinkert/section-matter
Expand Down
18 changes: 14 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"test": "jest -c jest.config.json --detectOpenHandles",
"test:coverage": "yarn run test -- --coverage && cat ./coverage/lcov.info | npx coveralls",
"test:watch": "yarn run test -- --watchAll --verbose false",
"test:mdx": "jest -c jest.config.json --detectOpenHandles --findRelatedTests src/mdx/mdx-sample.tsx",
"react:starter": "env DEBUG='*' webpack --config=./lib/react-starter/webpack.config.js --watch --mode=development",
"version:major": "changelog -M && git add CHANGELOG.md && git commit -m 'updated CHANGELOG.md' && npm version major",
"version:minor": "changelog -m && git add CHANGELOG.md && git commit -m 'updated CHANGELOG.md' && npm version minor",
Expand Down Expand Up @@ -77,14 +78,22 @@
}
},
"dependencies": {
"@babel/core": "^7.1.2",
"@babel/core": "^7.1.5",
"@babel/generator": "^7.1.5",
"@babel/node": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-syntax-jsx": "^7.0.0",
"@babel/plugin-transform-react-jsx": "^7.0.0",
"@babel/standalone": "^7.1.0",
"@mapbox/hast-util-table-cell-style": "^0.1.3",
"@mdx-js/loader": "^0.15.7",
"@mdx-js/tag": "^0.15.6",
"body-parser": "^1.18.3",
"cookie-parser": "^1.4.3",
"express": "^4.16.4",
"express-session": "^1.15.6",
"hast-to-hyperscript": "^5.0.0",
"hast-util-sanitize": "^1.2.0",
"html-whitespace-sensitive-tag-names": "^1.0.0",
"hyperscript": "^2.0.2",
"mdast-util-to-hast": "^3.0.2",
Expand All @@ -98,13 +107,14 @@
"rehype-parse": "^5.0.0",
"rehype-react": "^3.0.3",
"rehype-stringify": "^4.0.0",
"remark": "^9.0.0",
"remark": "^10.0.0",
"remark-html": "^8.0.0",
"remark-parse": "^5.0.0",
"remark-parse": "^6.0.0",
"remark-preset-lint-recommended": "^3.0.2",
"remark-react": "^4.0.3",
"remark-rehype": "^3.0.1",
"remark-slug": "^5.1.0",
"remark-stringify": "^5.0.0",
"remark-stringify": "^6.0.1",
"styled-components": "^3.4.10",
"to-vfile": "^5.0.2",
"unified": "^7.0.0",
Expand Down
16 changes: 16 additions & 0 deletions src/babel-generator/sample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// npx ts-node ./src/babel-generator/sample.tsx
const { parse } = require('@babel/parser');
const generate = require('@babel/generator').default;

const code = 'class Example {}';
const ast = parse(code);

const output = generate(
ast,
{
/* options */
},
code,
);

console.log(output); // { code: 'class Example {}', map: null, rawMappings: null }
33 changes: 33 additions & 0 deletions src/mdx/__tests__/mdx-sample.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as ReactDOM from 'react-dom/server';
import { converter, mdxToHtml } from '../mdx-sample';

const templateText = `
# Hello World
body message
## h2 title
highlight
`;

const resultTest = '<div><h1>Hello World</h1><p>body message</p><h2>h2 title</h2><p>highlight</p></div>';

// tslint:disable:max-line-length
const expectValue = `
<MDXTag name="wrapper" components={components}><MDXTag name="h1" components={components}>{\`Hello World\`}</MDXTag>
<MDXTag name="p" components={components}>{\`body message\`}</MDXTag>
<MDXTag name="h2" components={components}>{\`h2 title\`}</MDXTag>
<MDXTag name="p" components={components}>{\`highlight\`}</MDXTag></MDXTag>`;

test('hello', async () => {
const result = await converter(templateText);
expect(result).toBe(expectValue);
});

test('hello2', async () => {
const component = await mdxToHtml(templateText);
const renderResult = ReactDOM.renderToStaticMarkup(component);
expect(renderResult).toEqual(resultTest);
});
8 changes: 8 additions & 0 deletions src/mdx/__tests__/sample.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as ReactDOM from 'react-dom/server';
import { makeComponent } from '../sample';

test('renderToStaticMarkup2', () => {
const component = makeComponent('h1', 'hoge', {});
const result = ReactDOM.renderToStaticMarkup(component);
expect(result).toEqual('<h2 style="color:tomato">hoge</h2>');
});
42 changes: 42 additions & 0 deletions src/mdx/mdx-sample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// @ts-ignore
import * as objectRestSpread from '@babel/plugin-proposal-object-rest-spread';
// @ts-ignore
import * as transformJSX from '@babel/plugin-transform-react-jsx';
// @ts-ignore
import * as babelStandAlone from '@babel/standalone';
import * as mdx from '@mdx-js/mdx';
import { MDXTag } from '@mdx-js/tag';
import * as React from 'react';

process.on('unhandledRejection', console.dir);

const parse2 = (raw: string): string | null =>
babelStandAlone.transform(raw, {
plugins: [transformJSX, objectRestSpread],
}).code;

export const converter = async (content: string) => {
return await mdx.sync(content, {
skipExport: true,
});
};

export const mdxToHtml = async (content: string) => {
const tmp1 = await converter(content);
const code = parse2(tmp1);
const scope = {};
const components = {};
const props = {};

const fullScope = {
MDXTag,
components,
props,
...scope,
};
const keys = Object.keys(fullScope);
const values = keys.map(key => fullScope[key]);
const fn = new Function('React', ...keys, `return ${code}`);
const resultComponent = fn(React, ...values);
return resultComponent;
};
17 changes: 17 additions & 0 deletions src/mdx/sample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { MDXTag } from '@mdx-js/tag';
import * as React from 'react';

const H2 = (props: JSX.IntrinsicElements['h2']) => <h2 style={{ color: 'tomato' }} {...props} />;

export const makeComponent = <T extends keyof JSX.IntrinsicElements>(tag: T, body: string, props?: JSX.IntrinsicElements[T]) => {
return (
<MDXTag
name={tag}
props={props}
components={{
h1: H2,
}}
children={body}
/>
);
};
4 changes: 1 addition & 3 deletions src/react-markdown/markdown.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import * as React from 'react';
// @ts-ignore
import * as remark from 'remark';
// @ts-ignore
import * as remarkReact from 'remark-react';
Expand Down Expand Up @@ -39,11 +38,10 @@ export class Markdown extends React.Component<MarkdownProps, {}> {
const opts = {
remarkReactComponents, // 上書きする
};
// @ts-ignore
const element = remark()
.use(remarkSlug)
.use(remarkReact, opts)
.processSync(this.props.text).contents;
.processSync(this.props.text || '').contents;

return element;
}
Expand Down
2 changes: 1 addition & 1 deletion src/react-starter/oneshot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export class App extends React.Component<{}, { text: string }> {
}

public render() {
// @ts-ignore
const markUp = {
// @ts-ignore
__html: remark()
.use(reactRenderer, {
sanitize: false,
Expand Down
21 changes: 21 additions & 0 deletions src/remark-react-latest/__tests__/main.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react';
import * as ReactDOMServer from 'react-dom/server';
import * as renderer from 'react-test-renderer';
import { convert, TestApp } from '../sample';

test('pluginを対象とした単体テスト', () => {
const component = convert('# Hello world');
expect(component).toEqual('<h1>Hello world</h1>\n');
});

test('Reactに組み込んだ場合のテスト', () => {
const component = renderer.create(<TestApp body="# h1を書き換える" />);
const componentJSON = component.toJSON()!;
const result = componentJSON.props.dangerouslySetInnerHTML.__html;
expect(result).toEqual('<h1>h1を書き換える</h1>\n');
});

test('renderToStaticMarkup', () => {
const result = ReactDOMServer.renderToStaticMarkup(<TestApp body="# h1を書き換える" />);
expect(result).toEqual('<div><h1>h1を書き換える</h1>\n</div>');
});
98 changes: 98 additions & 0 deletions src/remark-react-latest/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
const toHAST = require('mdast-util-to-hast');
const toSanitize = require('hast-util-sanitize');
const toH = require('hast-to-hyperscript');
const tableCellStyle = require('@mapbox/hast-util-table-cell-style');
import * as React from 'react';

const own = {}.hasOwnProperty;

const TABLE_ELEMENTS = ['table', 'thead', 'tbody', 'tfoot', 'tr'];

export interface Options {
prefix?: string;
processor?: any;
sanitize?: boolean;
createElement: typeof React.createElement;
toHast?: typeof toHAST;
remarkReactComponents?: { [key: string]: <T>(props: T) => React.ReactElement<T> };
}

/**
* Attach a react compiler.
*
* @param {Unified} processor - Instance.
* @param {Object?} [options]
* @param {Object?} [options.sanitize]
* - Sanitation schema.
* @param {Object?} [options.remarkReactComponents]
* - Components.
* @param {string?} [options.prefix]
* - Key prefix.
* @param {Function?} [options.createElement]
* - `h()`.
*/
export function remarkReact({
createElement = React.createElement,
sanitize,
toHast = {},
remarkReactComponents = {},
prefix = '',
}: Options): any {
const clean = sanitize !== false;
const scheme = sanitize ? sanitize : null;
const toHastOptions = toHast;

/**
* Wrapper around `createElement` to pass
* components in.
*
* @param {string} name - Element name.
* @param {Object} props - Attributes.
* @return {ReactElement} - React element.
*/
// @ts-ignore a
function h(name: string, props: object, children: React.ReactNode[]) {
const component = own.call(remarkReactComponents, name) ? remarkReactComponents[name] : name;

/*
* Currently, a warning is triggered by react for
* *any* white-space in tables. So we remove the
* pretty lines for now:
* https://github.com/facebook/react/pull/7081
*/
if (children && typeof component === 'string' && TABLE_ELEMENTS.indexOf(component) !== -1) {
children = children.filter(child => {
return child !== '\n';
});
}

return createElement(component, props, children);
}

/**
* Compile MDAST to React.
*
* @param {Node} node - MDAST node.
* @return {ReactElement} - React element.
*/
function compile(node: any) {
console.log(node);
let hast = {
type: 'element',
tagName: 'div',
properties: {},
children: toHAST(node, toHastOptions).children,
};

if (clean) {
hast = toSanitize(hast, scheme);
}

hast = tableCellStyle(hast);

return toH(React.createElement, hast, prefix);
}

// @ts-ignore
this.Compiler = compile;
}
Loading

0 comments on commit b857968

Please sign in to comment.