Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for <link> elements in svelte components #426

Merged
merged 3 commits into from
Jun 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions docs/svelte.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Svelte

`modular-css-svelte` provides a [svelte preprocessor](https://svelte.technology/guide#preprocessing) that can convert inline `<style>` or external `<link>` tags using `modular-css` and will also staticly replace any css references it can find for maximum speed.

### Options

All options are passed to the underlying `Processor` instance, see [Options](api.md#options).

## Usage

### `svelte.preprocess()`

```js
const filename = "./Component.html";

const { processor, preprocess } = require("modular-css-svelte")({
css : "./dist/bundle.css"
});

const processed = await svelte.preprocess(
fs.readFileSync(filename, "utf8"),
Object.assign({}, preprocess, { filename })
);

const result = processor.output();

fs.writeFileSync("./dist/bundle.css", result.css);
```

### `rollup-plugin-svelte`

#### API

```js
const rollup = require("rollup").rollup;

const { preprocess, plugin } = require("modular-css-svelte/rollup")({
css : "./dist/bundle.css"
});

const bundle = await rollup({
input : "./Component.html",
plugins : [
require("rollup-plugin-svelte")({
preprocess
}),
plugin
]
});

// bundle.write will also write out the CSS to the path specified in the `css` arg
bundle.write({
format : "es",
file : "./dist/bundle.js"
});
```

#### `rollup.config.js`

```js
const { preprocess, plugin } = require("modular-css-svelte/rollup")({
css : "./dist/bundle.css"
});

module.exports = {
input : "./Component.html",
output : {
format : "es",
file : "./dist/bundle.js"
},
plugins : [
require("rollup-plugin-svelte")({
preprocess
}),
plugin
]
};
```
9 changes: 5 additions & 4 deletions packages/svelte/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ modular-css-svelte [![NPM Version](https://img.shields.io/npm/v/modular-css-sve
<a href="https://gitter.im/modular-css/modular-css"><img src="https://img.shields.io/gitter/room/modular-css/modular-css.svg" alt="Gitter" /></a>
</p>

Svelte preprocessor support for [`modular-css`](https://github.com/tivac/modular-css). Process inline `<style>`s inside your Svelte components using the full power of `modular-css` while also providing compile-time optimizations for smaller bundles and even faster runtime performance!
Svelte preprocessor support for [`modular-css`](https://github.com/tivac/modular-css). Process inline `<style>`s or `<link>` references inside your Svelte components using the full power of `modular-css` while also providing compile-time optimizations for smaller bundles and even faster runtime performance!

## Example

Turns this

```html
<div class="{{css.main}}">
<h1 class="{{css.title}}">Title</h1>
<div class="{css.main}">
<h1 class="{css.title}">Title</h1>
</div>

<style>
Expand All @@ -37,6 +37,8 @@ into what is effectively this

while allowing you to use all of the usual `modular-css` goodies.

Alternatively you can use `<link>` tags to reference CSS external to the component.

## Install

`$ npm i modular-css-svelte`
Expand Down Expand Up @@ -115,4 +117,3 @@ module.exports = {
## Options

All options are passed to the underlying `Processor` instance, see [Options](https://github.com/tivac/modular-css/blob/master/docs/api.md#options).

81 changes: 52 additions & 29 deletions packages/svelte/methods.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,62 @@
"use strict";

const path = require("path");

const resolve = require("resolve-from");

const styleRegex = /<style[\S\s]*?>([\S\s]*?)<\/style>/igm;
const linkRegex = /<link\b[^<>]*?\bhref=\s*(?:"([^"]+)"|'([^']+)'|([^>\s]+))[^>]*>/igm;

exports.markup = (processor) => ({ content, filename }) => {
const search = /<style[\S\s]*?>([\S\s]*?)<\/style>/igm;
const matches = search.exec(content);
const link = linkRegex.exec(content);
const style = styleRegex.exec(content);

if(!matches) {
return {
code : content
};
}
if(!link && !style) {
return {
code : content
};
}

const style = matches[1];
if(link && style) {
throw new Error("modular-css-svelte supports <style> OR <link>, but not both");
}

return processor.string(
let css;

if(style) {
css = processor.string(
filename,
style
)
.then((result) => {
const exported = result.files[result.file].exports;

return {
code : content
// Replace simple {css.<key>} values first
.replace(
new RegExp(`{css.(${Object.keys(exported).join("|")})}`, "gm"),
(match, key) => exported[key].join(" ")
)
// Then any remaining bare css.<key> values
.replace(
new RegExp(`(\\b)css.(${Object.keys(exported).join("|")})(\\b)`, "gm"),
(match, prefix, key, suffix) => `${prefix}"${exported[key].join(" ")}"${suffix}`
)
};
});
};
style[1]
);
}

if(link) {
// Remove the <link> element from the component to avoid double-loading
content = content.replace(link[0], "");

let external = resolve(path.dirname(filename), link[1] || link[2] || link[3]);

css = processor.file(external);
}

return css.then((result) => {
const exported = result.files[result.file].exports;

return {
code : content
// Replace simple {css.<key>} values first
.replace(
new RegExp(`{css.(${Object.keys(exported).join("|")})}`, "gm"),
(match, key) => exported[key].join(" ")
)
// Then any remaining bare css.<key> values
.replace(
new RegExp(`(\\b)css.(${Object.keys(exported).join("|")})(\\b)`, "gm"),
(match, prefix, key, suffix) => `${prefix}"${exported[key].join(" ")}"${suffix}`
)
};
});
};

exports.style = () => ({
code : "/* replaced by modular-css */"
Expand Down
Loading