Skip to content

Commit d70070d

Browse files
committed
feat: support for imported bases
1 parent 94e9f9a commit d70070d

8 files changed

+87
-3
lines changed

src/ComponentRef.js

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* @copyright 2016-present, Reactdown Team
3+
* @flow
4+
*/
5+
6+
import * as types from 'babel-types';
7+
8+
// TODO: More robust regexpes required!
9+
const PARSE_REF_RE = /^([a-zA-Z0-9_\-\/]+)(\.([a-zA-Z0-9_]+))?$/;
10+
const PARSE_NAMED_REF_RE = /^([a-zA-Z0-9_]+)=([a-zA-Z0-9_\-\/]+)(\.([a-zA-Z0-9_]+))?$/;
11+
12+
export type ComponentRef = {
13+
source: string;
14+
name: string;
15+
};
16+
17+
export function parse(ref: string): ?ComponentRef {
18+
let match = PARSE_REF_RE.exec(ref);
19+
if (!match) {
20+
return null;
21+
}
22+
let [_everything, source, _nothing, name = 'default'] = match;
23+
return {source, name};
24+
}
25+
26+
export function parseNamed(ref: string): ?{id: string; ref: ComponentRef} {
27+
let match = PARSE_NAMED_REF_RE.exec(ref);
28+
if (!match) {
29+
return null;
30+
}
31+
let [_everything, id, source, _nothing, name = 'default'] = match;
32+
return {id, ref: {source, name}};
33+
}
34+
35+
export function importDeclaration(identifier, ref: ComponentRef | string) {
36+
if (typeof ref === 'string') {
37+
ref = parse(ref);
38+
}
39+
let specifier;
40+
if (ref.name === 'default') {
41+
specifier = types.importDefaultSpecifier(identifier);
42+
} else {
43+
specifier = types.importSpecifier(identifier, types.identifier(ref.name));
44+
}
45+
return types.importDeclaration([specifier], types.stringLiteral(ref.source));
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:local(.Label) {
2+
color: red
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from "react";
2+
import styles from "css";
3+
import { Label as Label__Base } from "lib";
4+
export function Label(props) {
5+
return React.createElement(Label__Base, { ...props, className: styles.Label
6+
});
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Label {
2+
base: lib.Label;
3+
color: red;
4+
}
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:local(.Label) {
2+
color: red
3+
}
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from "react";
2+
import styles from "css";
3+
import Label__Base from "somelib/Label";
4+
export function Label(props) {
5+
return React.createElement(Label__Base, { ...props, className: styles.Label
6+
});
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Label {
2+
base: somelib/Label;
3+
color: red;
4+
}

src/index.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import * as postcss from 'postcss';
88
import * as LoaderUtils from 'loader-utils';
99
import generate from 'babel-generator';
1010
import transformVariants, {isVariant} from './transformVariants';
11+
import HTMLTagList from './HTMLTagList';
12+
import * as ComponentRef from './ComponentRef';
1113

1214
const LOADER = require.resolve('../webpack');
1315

@@ -53,14 +55,22 @@ function renderToCSS(source: string, _config: RenderConfig): string {
5355
function renderToJS(source: string, config: RenderConfig): string {
5456
let root = postcss.parse(source);
5557
let statements = [];
56-
let component = 'div';
58+
let component = types.stringLiteral('div');
5759
root.walkRules(node => {
5860
if (isVariant(node)) {
5961
return;
6062
}
6163
node.walkDecls(decl => {
6264
if (decl.prop === 'base') {
63-
component = decl.value;
65+
if (HTMLTagList[decl.value]) {
66+
component = types.stringLiteral(decl.value);
67+
} else {
68+
let componentRef = ComponentRef.parse(decl.value);
69+
component = types.identifier(node.selector + '__Base');
70+
statements.unshift(
71+
ComponentRef.importDeclaration(component, decl.value)
72+
);
73+
}
6474
}
6575
});
6676
statements.push(exportComponent(node.selector, component, node.selector));
@@ -92,7 +102,7 @@ function exportComponent(name: string, component: string, className: string) {
92102
types.memberExpression(
93103
types.identifier('React'),
94104
types.identifier('createElement')),
95-
[types.stringLiteral(component), propsNode]
105+
[component, propsNode]
96106
);
97107
let componentNode = types.functionDeclaration(
98108
types.identifier(name),

0 commit comments

Comments
 (0)