Skip to content

Commit

Permalink
Merge pull request #13447 from storybookjs/tech/migrate-riot-to-ts
Browse files Browse the repository at this point in the history
Riot: migrate to TS
  • Loading branch information
gaetanmaisse committed Jan 13, 2021
2 parents 2ba5bd6 + 8fe8345 commit a3e4426
Show file tree
Hide file tree
Showing 20 changed files with 163 additions and 148 deletions.
9 changes: 5 additions & 4 deletions app/riot/package.json
Expand Up @@ -53,10 +53,11 @@
"ts-dedent": "^2.0.0"
},
"devDependencies": {
"@babel/plugin-transform-modules-commonjs": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"@babel/preset-flow": "^7.12.1",
"@babel/preset-react": "^7.12.1"
"@types/riot": "^3.6.2",
"riot": "^3.13.2",
"riot-compiler": "^3.6.0",
"riot-hot-reload": "^1.0.0",
"riot-tag-loader": "^2.1.0"
},
"peerDependencies": {
"@babel/core": "*",
Expand Down
File renamed without changes.
Expand Up @@ -2,22 +2,22 @@ import compiler from 'riot-compiler';

export const alreadyCompiledMarker = "var riot = require('riot')";

export function asCompiledCode(text) {
export function asCompiledCode(text: string) {
return compiler
.compile(text, {})
.replace('var riot = require("riot")', '')
.replace('riot.tag2(', 'tag2(');
}

export function compileNow(tag2, text) {
export function compileNow(tag2: unknown, text: string) {
// eslint-disable-next-line no-eval
return tag2 && eval(asCompiledCode(text));
}

export function getRidOfRiotNoise(compiled) {
export function getRidOfRiotNoise(compiled: string) {
return compiled.replace(/riot\.tag2/g, 'tag2').replace(alreadyCompiledMarker, '');
}

export function setConstructor(compiledSourceCode, constructor) {
export function setConstructor(compiledSourceCode: string, constructor: any) {
return compiledSourceCode.replace(/function\(opts\)\s*{\s*}(?=\);$)/, constructor.toString());
}
File renamed without changes.
Expand Up @@ -17,8 +17,9 @@ export const {
} = clientApi;

const framework = 'riot';
export const storiesOf = (...args) => clientApi.storiesOf(...args).addParameters({ framework });
export const configure = (...args) => coreConfigure(framework, ...args);
export const storiesOf = (...args: any) =>
clientApi.storiesOf(...args).addParameters({ framework });
export const configure = (...args: any) => coreConfigure(framework, ...args);

const mount = vendorMount.bind(riot, '#root');
const compileNow = unboundCompileNow.bind(null, tag2);
Expand Down
130 changes: 0 additions & 130 deletions app/riot/src/client/preview/render-riot.test.js

This file was deleted.

111 changes: 111 additions & 0 deletions app/riot/src/client/preview/render-riot.test.ts
@@ -0,0 +1,111 @@
import { document } from 'global';
import { unregister, tag2 } from 'riot';
import { render } from './rendering';
import { asCompiledCode } from './compileStageFunctions';

const rootElement = document.createElement('div');
rootElement.id = 'root';
document.body = document.createElement('body');
document.body.appendChild(rootElement);

beforeEach(() => {
unregister('#root');
rootElement.dataset.is = 'root';
});

describe('render a riot element', () => {
it('should not work with nothing', () => {
expect(render(null)).toBe(false);

expect(rootElement.innerHTML).toEqual('');
});

it('can work with some text', () => {
expect(render({ tags: ['<div><p>some tests</p></div>'] })).toBe(true);

expect(rootElement.innerHTML).toEqual('<div><p>some tests</p></div>');
});

it('can work with raw code', () => {
expect(render("riot.tag2('root', '<div>raw code</div>', '', '', () => {})")).toBe(true);

expect(rootElement.innerHTML).toEqual('<div>raw code</div>');
});

it('can work with compiled code', () => {
expect(render([{}])).toBe(true);
// does only work in true mode, and not in jest mode
});

it('will be possible to compile a template before rendering it', () => {
const compiledTemplate = asCompiledCode('<template><div>raw code</div></template>');

expect(compiledTemplate).toEqual(
"tag2('template', '<div>raw code</div>', '', '', function(opts) {\n});"
);
});

it('works with a json consisting in a tagName and opts', () => {
tag2('hello', '<p>Hello { opts.suffix }</p>', '', '', () => {});

expect(render({ tagName: 'hello', opts: { suffix: 'World' } })).toBe(true);

expect(rootElement.innerHTML).toEqual('<p>Hello World</p>');
});

it('can nest several tags', () => {
expect(
render({
tags: [
'<Tag1><div>Inside tag1:<ul><li><Tag2><yield/></Tag2></li></ul></div></Tag1>',
'<Tag2><div>Inside tag2:<ul><li><Tag3><yield/></Tag3></li></ul></div></Tag2>',
'<Tag3><div>Inside tag3:<ul><li><Tag4><yield/></Tag4></li></ul></div></Tag3>',
'<Tag4><div>Inside tag4:<ul><li><Tag5><yield/></Tag5></li></ul></div></Tag4>',
'<Tag5><div>Inside tag5:<ul><li><yield/></li></ul></div></Tag5>',
],
template: '<Matriochka><div><Tag1>Content</Tag1></div></Matriochka>',
})
).toBe(true);

expect(rootElement.innerHTML).toMatchSnapshot();
});

it('can template some vars', () => {
expect(
render({
tags: [
{
content:
"<SimpleTest><div>simple test ({opts.test || 'without parameter'}). Oh, by the way ({opts.riotValue || '... well, nothing'})</div></SimpleTest>",
boundAs: 'mustBeUniquePlease',
},
],
template:
'<SimpleTest test={ "with a parameter" } value={"value is mapped to riotValue"}></SimpleTest>',
})
).toBe(true);

expect(rootElement.innerHTML).toMatchSnapshot();
});

it('can accept a constructor', () => {
expect(
render({
tags: [
{
content:
"<SimpleTest><div>HACKED : {opts.hacked} ; simple test ({opts.test || 'without parameter'}). Oh, by the way ({opts.riotValue || '... well, nothing'})</div></SimpleTest>",
boundAs: 'mustBeUniquePlease',
},
],
template:
'<SimpleTest hacked={hacked} test={ "with a parameter" } value={"value is mapped to riotValue"}></SimpleTest>',
tagConstructor: function tagConstructor() {
this.hacked = true;
},
})
).toBe(true);

expect(rootElement.innerHTML).toMatchSnapshot();
});
});
Expand Up @@ -9,6 +9,12 @@ export default function renderMain({
name,
showMain = () => {},
showError = () => {},
}: {
storyFn: Function;
kind: string;
name: string;
showMain: () => any;
showError: (input: { title: string; description: string }) => void;
}) {
showMain();
unregister('#root');
Expand Down
@@ -1,5 +1,5 @@
import { mount } from 'riot';

export default function renderCompiledButUnmounted(component) {
export default function renderCompiledButUnmounted(component: any) {
mount('root', component.tagName, component.opts || {});
}
Expand Up @@ -2,7 +2,7 @@ import renderCompiledButUnmounted from './compiledButUnmounted';
import renderStringified from './stringified';
import renderRaw from './raw';

export function render(component) {
export function render(component: any) {
if (typeof component === 'string') {
renderRaw(component);
return true;
Expand Down
Expand Up @@ -2,7 +2,7 @@ import { mount, tag2 as tag } from 'riot';
import compiler from 'riot-compiler';
import { alreadyCompiledMarker, getRidOfRiotNoise } from '../compileStageFunctions';

export default function renderRaw(sourceCode) {
export default function renderRaw(sourceCode: string) {
const tag2 = tag;
// eslint-disable-next-line no-eval
eval(
Expand Down
Expand Up @@ -4,7 +4,7 @@ import compiler from 'riot-compiler';
import { document } from 'global';
import { alreadyCompiledMarker, getRidOfRiotNoise, setConstructor } from '../compileStageFunctions';

function guessRootName(stringified) {
function guessRootName(stringified: string) {
const whiteSpaceLocation = stringified.indexOf(' ', stringified.indexOf('<') + 1);
const firstWhitespace = whiteSpaceLocation === -1 ? stringified.length : whiteSpaceLocation;
const supposedName = stringified.trim().match(/^<[^ >]+\/>$/)
Expand All @@ -17,7 +17,7 @@ function guessRootName(stringified) {
return matchingBuiltInTag === 'HTMLUnknownElement' ? supposedName : 'root';
}

function compileText(code, rootName) {
function compileText(code: string, rootName: string) {
const sourceCodeEndOfHtml =
(Math.min(code.indexOf('<style') + 1, code.indexOf('<script') + 1) || code.length + 1) - 1;
const sourceCodeReformatted =
Expand All @@ -32,6 +32,10 @@ export default function renderStringified({
tags,
template = `<${(tags[0] || []).boundAs || guessRootName(tags[0] || '')}/>`,
tagConstructor,
}: {
tags: any[];
template: string;
tagConstructor: any;
}) {
const tag2 = tag;
tags.forEach((input) => {
Expand Down
File renamed without changes.
@@ -1,4 +1,6 @@
export function webpack(config) {
import { Configuration } from 'webpack';

export function webpack(config: Configuration) {
return {
...config,
module: {
Expand Down
File renamed without changes.
File renamed without changes.
8 changes: 8 additions & 0 deletions app/riot/src/typings.d.ts
@@ -0,0 +1,8 @@
declare module '@storybook/core/*';
declare module 'global';
declare module 'riot-compiler';
declare module 'riot' {
const tag2: Function;
const mount: Function;
const unregister: Function;
}
7 changes: 7 additions & 0 deletions app/riot/tsconfig.json
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"types": ["jest", "webpack-env"]
}
}

0 comments on commit a3e4426

Please sign in to comment.