@handbook/babel-plugin
v1.1.0
Published
[![NPM](https://img.shields.io/npm/v/@handbook/babel-plugin.svg)](https://www.npmjs.com/package/@handbook/babel-plugin) [![TEST](https://github.com/rocket-hangar/handbook/workflows/Test/badge.svg)](https://github.com/rocket-hangar/handbook/actions?query=w
Downloads
38
Readme
@handbook/babel-plugin
What does this do?
This is a babel plugin to transform all source()
functions of import { source } from @handbook/source
.
For example,
import { source } from '@handbook/source';
const { module: foo, source: fooSource1 } = source(require('./foo'));
const { module: fooImport, source: fooSource2 } = source(() => import('./foo'));
This babel plugin will transform the source into the below.
import { source } from '@handbook/source';
const { module: foo, source: fooSource1 } = source({
module: require('./foo'),
source: require('!!raw-loader!./foo'),
filename: 'foo.ts',
});
const { module: fooImport, source: fooSource2 } = source({
module: () => import('./foo'),
source: require('!!raw-loader!./foo'),
filename: 'foo.ts',
});
You can use this babel plugin when you need to make a development documentation web site.
__tests__/babel-plugin.test.ts
import { BabelFileResult, transform as babelTransform } from '@babel/core';
import { copyTmpDirectory } from '@ssen/tmp-directory';
import fs from 'fs';
import path from 'path';
import prettier from 'prettier';
import plugin from '../';
function format(code: string): string {
return prettier.format(code, { parser: 'typescript' });
}
describe('@handbook/babel-plugin', () => {
describe('file', () => {
const output: string = `
import { source } from "@handbook/source";
source({
module: "../../c/d/e",
source: require("!!raw-loader!../../c/d/e").default,
filename: "c/d/e.tsx",
});
source({
module: "c/d/e",
source: require("!!raw-loader!c/d/e").default,
filename: "c/d/e.tsx",
});
source({
module: require("../../c/d/e"),
source: require("!!raw-loader!../../c/d/e").default,
filename: "c/d/e.tsx",
});
source({
module: require("c/d/e"),
source: require("!!raw-loader!c/d/e").default,
filename: "c/d/e.tsx",
});
source({
module: () => import("../../c/d/e"),
source: require("!!raw-loader!../../c/d/e").default,
filename: "c/d/e.tsx",
});
source({
module: () => import("c/d/e"),
source: require("!!raw-loader!c/d/e").default,
filename: "c/d/e.tsx",
});
source({
module: "../../c/d/e.tsx",
source: require("!!raw-loader!../../c/d/e.tsx").default,
filename: "c/d/e.tsx",
});
source({
module: "c/d/e.tsx",
source: require("!!raw-loader!c/d/e.tsx").default,
filename: "c/d/e.tsx",
});
source({
module: require("../../c/d/e.tsx"),
source: require("!!raw-loader!../../c/d/e.tsx").default,
filename: "c/d/e.tsx",
});
source({
module: require("c/d/e.tsx"),
source: require("!!raw-loader!c/d/e.tsx").default,
filename: "c/d/e.tsx",
});
`;
test('should succeed to transform in src directory', async () => {
// Arrange
const cwd = await copyTmpDirectory(
path.join(process.cwd(), `test/fixtures/src-project`),
);
const file = 'a/b/c.tsx';
const filename = path.join(cwd, 'src', file);
const source: string = fs.readFileSync(filename, { encoding: 'utf8' });
// Act
const res: BabelFileResult | null = babelTransform(format(source), {
babelrc: false,
cwd,
filename,
plugins: [plugin, require.resolve('@babel/plugin-syntax-jsx')],
});
if (!res || !res.code) {
throw new Error('plugin failed!');
}
// Assert
expect(format(res.code)).toBe(format(output));
});
test('should succeed to transform in root directory', async () => {
// Arrange
const cwd = await copyTmpDirectory(
path.join(process.cwd(), `test/fixtures/root-project`),
);
const file = 'a/b/c.tsx';
const filename = path.join(cwd, file);
const source: string = fs.readFileSync(filename, { encoding: 'utf8' });
// Act
const res: BabelFileResult | null = babelTransform(format(source), {
babelrc: false,
cwd,
filename,
plugins: [plugin, require.resolve('@babel/plugin-syntax-jsx')],
});
if (!res || !res.code) {
throw new Error('plugin failed!');
}
// Assert
expect(format(res.code)).toBe(format(output));
});
});
describe('source', () => {
const filename = 'dir/test.tsx';
function transform(code: string): string {
const res: BabelFileResult | null = babelTransform(format(code), {
babelrc: false,
cwd: process.cwd(),
filename: path.join(process.cwd(), 'src', filename).replace(/\\/g, '/'),
plugins: [plugin, '@babel/plugin-syntax-jsx'],
});
if (!res || !res.code) {
throw new Error('plugin failed!');
}
return res.code;
}
test('should fail to transform', () => {
// Arrange
const source = `
import { source } from '@handbook/source';
import { foo } from './foo';
source(Math.random());
source(foo());
`;
// Assert
expect(format(transform(source))).toBe(format(source));
});
test('should succeed to transform', () => {
// Arrange
process.env.HANDBOOK_TEST_EXT = '.tsx';
const module = './samples/Sample';
const source = `
import { source } from '@handbook/source';
source(require('${module}'));
source(() => import('${module}'));
`;
const moduleFilename = path
.join(path.dirname(filename), module)
.replace(/\\/g, '/');
const output = `
import { source } from '@handbook/source';
source({
module: require('${module}'),
source: require('!!raw-loader!${module}').default,
filename: '${moduleFilename}.tsx',
});
source({
module: () => import('${module}'),
source: require('!!raw-loader!${module}').default,
filename: '${moduleFilename}.tsx',
});
`;
// Assert
expect(format(transform(source))).toBe(format(output));
});
test('should succeed to transform in jsx', () => {
// Arrange
process.env.HANDBOOK_TEST_EXT = '.tsx';
const module1 = './samples/Sample1';
const module2 = './samples/Sample2';
const source = `
import { source } from '@handbook/source';
import { Handbook, Preview, CodeBlock } from '@handbook/components';
function App() {
return (
<div>
<Handbook>
{{
index: {
Title1: source(require('${module1}')),
Title2: source(() => import('${module2}')),
}
}}
</Handbook>
<Preview source={source(require('${module1}'))}/>
<Preview source={source(() => import('${module2}'))}/>
<CodeBlock source={source(require('${module1}'))}/>
<CodeBlock source={source(() => import('${module2}'))}/>
</div>
)
}
`;
const moduleFilename1 = path
.join(path.dirname(filename), module1)
.replace(/\\/g, '/');
const moduleFilename2 = path
.join(path.dirname(filename), module2)
.replace(/\\/g, '/');
const output = `
import { source } from '@handbook/source';
import { Handbook, Preview, CodeBlock } from '@handbook/components';
function App() {
return (
<div>
<Handbook>
{{
index: {
Title1: source({
module: require('${module1}'),
source: require('!!raw-loader!${module1}').default,
filename: '${moduleFilename1}.tsx',
}),
Title2: source({
module: () => import('${module2}'),
source: require('!!raw-loader!${module2}').default,
filename: '${moduleFilename2}.tsx',
}),
}
}}
</Handbook>
<Preview source={source({
module: require('${module1}'),
source: require('!!raw-loader!${module1}').default,
filename: '${moduleFilename1}.tsx',
})}/>
<Preview source={source({
module: () => import('${module2}'),
source: require('!!raw-loader!${module2}').default,
filename: '${moduleFilename2}.tsx',
})}/>
<CodeBlock source={source({
module: require('${module1}'),
source: require('!!raw-loader!${module1}').default,
filename: '${moduleFilename1}.tsx',
})}/>
<CodeBlock source={source({
module: () => import('${module2}'),
source: require('!!raw-loader!${module2}').default,
filename: '${moduleFilename2}.tsx',
})}/>
</div>
)
}
`;
// Assert
expect(format(transform(source))).toBe(format(output));
});
test('should succeed to transform namespace import', () => {
// Arrange
process.env.HANDBOOK_TEST_EXT = '.tsx';
const module = './samples/Sample';
const source = `
import * as ns from '@handbook/source';
ns.source(require('${module}'));
ns.source(() => import('${module}'));
`;
const moduleFilename = path
.join(path.dirname(filename), module)
.replace(/\\/g, '/');
const output = `
import * as ns from '@handbook/source';
ns.source({
module: require('${module}'),
source: require('!!raw-loader!${module}').default,
filename: '${moduleFilename}.tsx',
});
ns.source({
module: () => import('${module}'),
source: require('!!raw-loader!${module}').default,
filename: '${moduleFilename}.tsx',
});
`;
// Assert
expect(format(transform(source))).toBe(format(output));
});
test('should succeed to transform default import', () => {
// Arrange
process.env.HANDBOOK_TEST_EXT = '.tsx';
const module = './samples/Sample';
const source = `
import ns from '@handbook/source';
ns.source(require('${module}'));
ns.source(() => import('${module}'));
`;
const moduleFilename = path
.join(path.dirname(filename), module)
.replace(/\\/g, '/');
const output = `
import ns from '@handbook/source';
ns.source({
module: require('${module}'),
source: require('!!raw-loader!${module}').default,
filename: '${moduleFilename}.tsx',
});
ns.source({
module: () => import('${module}'),
source: require('!!raw-loader!${module}').default,
filename: '${moduleFilename}.tsx',
});
`;
// Assert
expect(format(transform(source))).toBe(format(output));
});
});
});
Install
Install packages.
npm install @handbook/babel-plugin @handbook/source --save-dev
Add plugin to your babel configuration.
// your babel config
module.exports = {
presets: [],
plugins: [
// TODO set transform plugin
require.resolve('@handbook/babel-plugin'),
],
};
See more
@handbook/*
This babel plugin is one of@handbook/*
packages. Go to the project home and see more details.