Skip to content

Commit

Permalink
add support for namespace exports (#156)
Browse files Browse the repository at this point in the history
  • Loading branch information
jantimon authored Sep 9, 2024
1 parent bfef0ce commit 581c645
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
export const siteMaxWidth = 10;
export const siteMaxWidth = 10;

export const colors = {
primary: 'var(--color-primary)',
secondary: 'var(--color-secondary)',
};
13 changes: 10 additions & 3 deletions packages/cross-file-tests/__tests__/fixtures/constant/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { styled } from "next-yak";
import { siteMaxWidth } from "./constants";
export const Button = styled.button`
import { styled, css } from "next-yak";
import { colors, siteMaxWidth } from "./constants";
export const Button = styled.button<{$variant: 'primary' | 'secondary'}>`
color: red;
height: ${siteMaxWidth}px;
color: ${colors.primary};
background-color: ${colors.secondary};
${({$variant}) => $variant === "secondary" && css`
color: ${colors.secondary};
background-color: ${colors.primary};
`}
`;
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
export var siteMaxWidth = 10;
export var siteMaxWidth = 10;
export var colors = {
primary: 'var(--color-primary)',
secondary: 'var(--color-secondary)'
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { styled } from "next-yak/internal";
import { styled, css } from "next-yak/internal";
import __styleYak from "./index.yak.module.css!=!./index?./index.yak.module.css";
import { siteMaxWidth } from "./constants";
import { colors, siteMaxWidth } from "./constants";
export var Button = /*YAK Extracted CSS:
.Button {
color: red;
height: --yak-css-import: url("./constants:siteMaxWidth",mixin)px;
color: --yak-css-import: url("./constants:colors:primary",mixin);
background-color: --yak-css-import: url("./constants:colors:secondary",mixin);
}
*/ /*#__PURE__*/ styled.button(__styleYak.Button);
.Button__ {
color: --yak-css-import: url("./constants:colors:secondary",mixin);
background-color: --yak-css-import: url("./constants:colors:primary",mixin);
}
*/ /*#__PURE__*/ styled.button(__styleYak.Button, function(param) {
var $variant = param.$variant;
return $variant === "secondary" && /*#__PURE__*/ css(__styleYak.Button__);
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
.Button {
color: red;
height: 10px;
color: var(--color-primary);
background-color: var(--color-secondary);
}
.Button__ {
color: var(--color-secondary);
background-color: var(--color-primary);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const primary = 'var(--color-primary)';
export const secondary = 'var(--color-secondary)';

// namespace export same file
export * as colors from './constants';
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { styled } from "next-yak";
import { colors } from "./constants";
export const Button = styled.button`
color: ${colors.primary};
background-color: ${colors.secondary};
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export var primary = 'var(--color-primary)';
export var secondary = 'var(--color-secondary)';
// namespace export same file
import * as _colors from './constants';
export { _colors as colors };
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { styled } from "next-yak/internal";
import __styleYak from "./index.yak.module.css!=!./index?./index.yak.module.css";
import { colors } from "./constants";
export var Button = /*YAK Extracted CSS:
.Button {
color: --yak-css-import: url("./constants:colors:primary",mixin);
background-color: --yak-css-import: url("./constants:colors:secondary",mixin);
}
*/ /*#__PURE__*/ styled.button(__styleYak.Button);
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.Button {
color: var(--color-primary);
background-color: var(--color-secondary);
}
53 changes: 49 additions & 4 deletions packages/next-yak/loaders/lib/resolveCrossFileSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getCssModuleLocalIdent } from "next/dist/build/webpack/config/blocks/cs

const yakCssImportRegex =
// Make mixin and selector non optional once we dropped support for the babel plugin
/--yak-css-import\:\s*url\("([^"]+)",?(|mixin|selector)\);?/g;
/--yak-css-import\:\s*url\("([^"]+)",?(|mixin|selector)\)(;?)/g;

const compilationCache = new WeakMap<
Compilation,
Expand Down Expand Up @@ -40,7 +40,7 @@ export async function resolveCrossFileConstant(
): Promise<string> {
// Search for --yak-css-import: url("path/to/module") in the css
const matches = [...css.matchAll(yakCssImportRegex)].map((match) => {
const [fullMatch, encodedArguments, importKind] = match;
const [fullMatch, encodedArguments, importKind, semicolon] = match;
const [moduleSpecifier, ...specifier] = encodedArguments
.split(":")
.map((entry) => decodeURIComponent(entry));
Expand All @@ -49,6 +49,7 @@ export async function resolveCrossFileConstant(
moduleSpecifier,
specifier,
importKind,
semicolon,
position: match.index!,
size: fullMatch.length,
};
Expand Down Expand Up @@ -87,7 +88,7 @@ export async function resolveCrossFileConstant(
// Replace the imports with the resolved values
let result = css;
for (let i = matches.length - 1; i >= 0; i--) {
const { position, size, importKind, specifier } = matches[i];
const { position, size, importKind, specifier, semicolon } = matches[i];
const resolved = resolvedValues[i];

if (importKind === "selector") {
Expand All @@ -111,7 +112,17 @@ export async function resolveCrossFileConstant(
resolved.name,
{},
)})`
: resolved.value;
: resolved.value +
// resolved.value can be of two different types:
// - mixin:
// ${mixinName};
// - constant:
// color: ${value};
// For mixins the semicolon is already included in the value
// but for constants it has to be added manually
(["}", ";"].includes(String(resolved.value).trimEnd().slice(-1))
? ""
: semicolon);

result =
result.slice(0, position) +
Expand Down Expand Up @@ -296,6 +307,23 @@ async function parseExports(
});
}
},
ExportDeclaration({ node }) {
if ("specifiers" in node && node.source) {
const { specifiers, source } = node;
specifiers.forEach((specifier) => {
// export * as color from "./colors";
if (
specifier.type === "ExportNamespaceSpecifier" &&
specifier.exported.type === "Identifier"
) {
exports[specifier.exported.name] = {
type: "star-export",
from: [source.value],
};
}
});
}
},
ExportAllDeclaration({ node }) {
if (Object.keys(exports).length === 0) {
exports["*"] ||= {
Expand Down Expand Up @@ -437,6 +465,7 @@ async function resolveModuleSpecifierRecursively(
}
}
// Follow reexport
// e.g. export { colors as primaryColors } from "./colors";
if (exportValue.type === "re-export") {
const importedModule = await parseModule(
loader,
Expand All @@ -448,6 +477,20 @@ async function resolveModuleSpecifierRecursively(
...specifier.slice(1),
]);
}
// Namespace export
// e.g. export * as colors from "./colors";
else if (exportValue.type === "star-export") {
const importedModule = await parseModule(
loader,
exportValue.from[0],
path.dirname(module.filePath),
);
return resolveModuleSpecifierRecursively(
loader,
importedModule,
specifier.slice(1),
);
}

if (exportValue.type === "styled-component") {
return {
Expand Down Expand Up @@ -481,6 +524,8 @@ async function resolveModuleSpecifierRecursively(
// mixins in .yak files are wrapped inside an object with a __yak key
if (depth === specifier.length && "__yak" in current) {
return { type: "mixin", value: current["__yak"] };
} else if (depth === specifier.length && "value" in current) {
return { type: "constant", value: current["value"] };
} else {
current = current[specifier[depth]];
}
Expand Down
2 changes: 1 addition & 1 deletion packages/next-yak/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "next-yak",
"version": "0.3.0",
"version": "0.3.1",
"type": "module",
"types": "./dist/",
"license": "MIT",
Expand Down

0 comments on commit 581c645

Please sign in to comment.