@stylable/core
Version:
CSS for Components
84 lines (76 loc) • 2.37 kB
text/typescript
import path from 'path';
import type * as postcss from 'postcss';
import { processDeclarationFunctions } from './process-declaration-functions';
function isExternal(url: string) {
return url === '' || url.startsWith('data:') || isUrl(url);
}
function isUrl(maybeUrl: string) {
maybeUrl = maybeUrl.trim();
if (maybeUrl.includes(' ')) {
return false;
}
try {
new URL(maybeUrl);
return true;
} catch {
return false;
}
}
export function isAsset(url: string) {
return !isExternal(url);
}
export function isRelativeNativeCss(fullPath: string) {
return (
fullPath.endsWith('.css') &&
!fullPath.endsWith('.st.css') &&
!fullPath.includes(path.sep + 'node_modules' + path.sep) &&
!isUrl(fullPath)
);
}
export function makeAbsolute(
host: {
join: (...paths: string[]) => string;
isAbsolute: (path: string) => boolean;
},
resourcePath: string,
rootContext: string,
moduleContext: string
) {
const isAbs = host.isAbsolute(resourcePath);
let abs: string;
if (isExternal(resourcePath) || resourcePath.startsWith('~')) {
abs = resourcePath;
} else if (isAbs && resourcePath.startsWith('/')) {
abs = host.join(rootContext, resourcePath);
} else if (isAbs) {
abs = resourcePath;
} else {
abs = host.join(moduleContext, resourcePath);
}
return abs;
}
export function fixRelativeUrls(ast: postcss.Root, originPath: string, targetPath: string) {
ast.walkDecls((decl) => {
processDeclarationFunctions(
decl,
(node) => {
if (node.type === 'url') {
if (!node.url || !isAsset(node.url) || !node.url.startsWith('.')) {
return;
}
const url = path
.join(
path.relative(path.dirname(targetPath), path.dirname(originPath)),
node.url
)
.replace(/\\/gm, '/');
node.url = assureRelativeUrlPrefix(url);
}
},
true
);
});
}
export function assureRelativeUrlPrefix(url: string) {
return !url.startsWith('./') && !url.startsWith('../') ? './' + url : url;
}