-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from Himenon/dev
feat(markdown): MarkdownをReactのComponentに対応させてレンダリングする
- Loading branch information
Showing
21 changed files
with
2,498 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,9 @@ | |
"portfinder", | ||
"resave", | ||
"hoge", | ||
"foo" | ||
"foo", | ||
"rehype", | ||
"hyperscript" | ||
], | ||
"flagWords": [ | ||
"hte" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import * as renderer from 'react-test-renderer'; | ||
import * as OneShot from '../oneshot'; | ||
|
||
describe('hast-to-hyperscript', () => { | ||
test('sample test with hyperscript', () => { | ||
const doc = OneShot.main(); | ||
expect(doc).toBe('<p id="alpha" class="bravo">charlie <strong style="color:red;">delta</strong> echo.</p>'); | ||
}); | ||
|
||
test('sample test with React.createElement', () => { | ||
const doc = OneShot.mainReact(); | ||
expect(doc).toBeUndefined(); | ||
}); | ||
|
||
test('customH', () => { | ||
const result = renderer.create(OneShot.customH('div', {}, null)); | ||
const jsonValue = result.toJSON(); | ||
expect(jsonValue).toEqual({ type: 'div', props: {}, children: null }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,32 @@ | ||
// @ts-ignore | ||
import * as toH from 'hast-to-hyperscript' | ||
import * as h from 'hyperscript' | ||
|
||
const toH = require('hast-to-hyperscript'); | ||
import * as h from 'hyperscript'; | ||
import * as React from 'react'; | ||
const tree = { | ||
type: 'element', | ||
tagName: 'p', | ||
properties: { id: 'alpha', className: ['bravo'] }, | ||
children: [ | ||
{ type: 'text', value: 'charlie ' }, | ||
{ | ||
type: 'element', | ||
tagName: 'strong', | ||
properties: { style: 'color: red' }, | ||
children: [{ type: 'text', value: 'delta' }], | ||
}, | ||
{ type: 'text', value: ' echo.' }, | ||
], | ||
}; | ||
|
||
export const main = () => { | ||
const tree = { | ||
type: 'element', | ||
tagName: 'p', | ||
properties: {id: 'alpha', className: ['bravo']}, | ||
children: [ | ||
{type: 'text', value: 'charlie '}, | ||
{ | ||
type: 'element', | ||
tagName: 'strong', | ||
properties: {style: 'color: red'}, | ||
children: [{type: 'text', value: 'delta'}] | ||
}, | ||
{type: 'text', value: ' echo.'} | ||
] | ||
} | ||
return toH(h, tree).outerHTML; | ||
}; | ||
|
||
const hashTree = { type: 'element', tagName: 'div', properties: {}, children: [] }; | ||
|
||
export const customH = (name: string, props: any, children: any) => { | ||
return React.createElement(name, props, children); | ||
}; | ||
|
||
return toH(h, tree).outerHTML | ||
} | ||
export const mainReact = () => { | ||
return toH(React.createElement, hashTree).outerHTML; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import * as renderer from 'react-test-renderer'; | ||
import { heading } from '../heading1'; | ||
|
||
test('heading', () => { | ||
const makeComponent = heading('div'); | ||
const component = makeComponent({ | ||
title: 'Hello world', | ||
children: null, | ||
}); | ||
const result = renderer.create(component); | ||
const jsonValue = result.toJSON(); | ||
expect(jsonValue).toEqual({ | ||
type: 'div', | ||
props: { title: 'Hello world' }, | ||
children: [{ type: 'a', props: { href: '#hoge', style: { color: 'inherit', textDecoration: 'none' } }, children: null }], | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import * as React from 'react'; | ||
import * as renderer from 'react-test-renderer'; | ||
import { Heading1, Heading1Props } from '../heading1'; | ||
import { defaultProps, Markdown, MarkdownProps } from '../markdown'; | ||
|
||
describe('MarkdownComponent', () => { | ||
test('defaultProps', () => { | ||
const component = defaultProps.scope.Title!({ | ||
title: 'hoge', | ||
}); | ||
const result = renderer.create(component); | ||
const jsonValue = result.toJSON(); | ||
expect(jsonValue).toEqual({ type: 'h1', props: {}, children: ['hoge'] }); | ||
}); | ||
|
||
test('Heading1', () => { | ||
const result = renderer.create(<Heading1 title="sample text" />); | ||
const jsonValue = result.toJSON(); | ||
expect(jsonValue).toEqual({ type: 'h1', props: {}, children: ['sample text'] }); | ||
}); | ||
|
||
test('Rendering Value', () => { | ||
const props: MarkdownProps = { | ||
text: '<h1>Hello Gen</h1>', | ||
h1: {}, | ||
scope: { Title: (props1: Heading1Props) => <Heading1 {...props1} /> }, | ||
}; | ||
const result = renderer.create(<Markdown {...props} />); | ||
const jsonValue = result.toJSON(); | ||
expect(jsonValue).toEqual({ type: 'div', props: {}, children: null }); | ||
}); | ||
|
||
test('Rendering Value no scope', () => { | ||
const props: MarkdownProps = { | ||
text: '<h1>Hello Gen</h1>', | ||
h1: {}, | ||
scope: {}, | ||
}; | ||
const result = renderer.create(<Markdown {...props} />); | ||
const jsonValue = result.toJSON(); | ||
expect(jsonValue).toEqual({ type: 'div', props: {}, children: null }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import * as React from 'react'; | ||
|
||
export interface Heading1Props { | ||
title: string; | ||
children?: React.ReactNode; | ||
} | ||
|
||
export class Heading1 extends React.Component<Heading1Props, {}> { | ||
public render() { | ||
return <h1>{this.props.title}</h1>; | ||
} | ||
} | ||
|
||
export const heading = (Comp: any) => (props: Heading1Props): React.ReactElement<any> => { | ||
return React.createElement( | ||
Comp, | ||
props, | ||
React.createElement( | ||
'a', | ||
{ | ||
href: '#hoge', | ||
style: { | ||
color: 'inherit', | ||
textDecoration: 'none', | ||
}, | ||
}, | ||
props.children, | ||
), | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import * as React from 'react'; | ||
// @ts-ignore | ||
import * as remark from 'remark'; | ||
// @ts-ignore | ||
import * as remarkReact from 'remark-react'; | ||
// @ts-ignore | ||
import * as remarkSlug from 'remark-slug'; | ||
|
||
import { heading, Heading1, Heading1Props } from './heading1'; | ||
|
||
export interface ScopedComponents { | ||
Title?: (props: Heading1Props) => React.ReactElement<Heading1Props>; | ||
} | ||
|
||
export interface MarkdownProps { | ||
text?: string; | ||
h1: { [key: string]: number }; | ||
scope: ScopedComponents; | ||
} | ||
|
||
export interface MappedScope { | ||
h1: React.ReactNode | undefined; | ||
} | ||
|
||
export const defaultProps: MarkdownProps = { | ||
h1: {}, | ||
scope: { | ||
Title: (props: Heading1Props) => <Heading1 {...props} />, | ||
}, | ||
}; | ||
|
||
export class Markdown extends React.Component<MarkdownProps, {}> { | ||
public render() { | ||
const scope = this.props.scope; | ||
|
||
const mappedScope = this.mapScope({ ...scope }); | ||
const remarkReactComponents = this.applyProps(mappedScope); | ||
|
||
const opts = { | ||
remarkReactComponents, // 上書きする | ||
}; | ||
// @ts-ignore | ||
const element = remark() | ||
.use(remarkSlug) | ||
.use(remarkReact, opts) | ||
.processSync(this.props.text).contents; | ||
|
||
return element; | ||
} | ||
|
||
private mapScope = (scope: ScopedComponents): MappedScope => { | ||
const h1 = scope.Title; | ||
return { | ||
h1: h1 ? heading(h1) : undefined, | ||
}; | ||
}; | ||
|
||
private applyProps = (scope: MappedScope) => { | ||
const props = { ...defaultProps }; | ||
Object.keys(props).forEach(key => { | ||
if (!scope[key]) { | ||
return; | ||
} | ||
scope[key].defaultProps = { ...scope[key].defaultProps, ...props[key] }; | ||
}); | ||
return scope; | ||
}; | ||
} |
Oops, something went wrong.