Skip to content

Commit

Permalink
A ton of documentation on plugins and other improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-dean committed Jan 7, 2017
1 parent f462221 commit 355f564
Show file tree
Hide file tree
Showing 22 changed files with 330 additions and 181 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ node_modules
npm-debug.log

# local dev
*.map
tmp
temp
vendor
Expand Down
6 changes: 3 additions & 3 deletions content/features-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ You can also bundle pseudo-selectors with your mixins using this method. Here's
**[Learn More About Parent Selectors](/features/#parent-selectors-feature)**


## Nested Directives and Bubbling
## Nested At-Rules and Bubbling

Directives such as `@media` or `@supports` can be nested in the same way as selectors. The directive is placed on top and relative order against other elements inside the same ruleset remains unchanged. This is called bubbling.
At-rules such as `@media` or `@supports` can be nested in the same way as selectors. The at-rule is placed on top and relative order against other elements inside the same ruleset remains unchanged. This is called bubbling.

```less
.component {
Expand Down Expand Up @@ -326,4 +326,4 @@ Importing works pretty much as expected. You can import a `.less` file, and all
@import "typo.css";
```

**[Learn More About Imports](/features/#import-directives-feature)**
**[Learn More About Imports](/features/#imports-feature)**
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The following options can be used to override this behavior.
Syntax: `@import (keyword) "filename";`

The following import directives have been implemented:
The following import options have been implemented:

* `reference`: use a Less file but do not output it
* `inline`: include the source file in the output but do not process it
Expand All @@ -49,13 +49,13 @@ The following import directives have been implemented:
Example: `@import (optional, reference) "foo.less";`

### reference
> Use `@import (reference)` to import external files, but without adding the imported styles to the compiled output unless referenced.
Use `@import (reference)` to import external files, but without adding the imported styles to the compiled output unless referenced.

Released [v1.5.0]({{ less.master.url }}CHANGELOG.md)

Example: `@import (reference) "foo.less";`

Imagine that `reference` marks every directive and selector with a _reference flag_ in the imported file, imports as normal, but when the CSS is generated, "reference" selectors (as well as any media queries containing only reference selectors) are not output. `reference` styles will not show up in your generated CSS unless the reference styles are used as [mixins](#mixins-feature) or [extended](#extend-feature).
Imagine that `reference` marks every at-rule and selector with a _reference flag_ in the imported file, imports as normal, but when the CSS is generated, "reference" selectors (as well as any media queries containing only reference selectors) are not output. `reference` styles will not show up in your generated CSS unless the reference styles are used as [mixins](#mixins-feature) or [extended](#extend-feature).

Additionally, **`reference`** produces different results depending on which method was used (mixin or extend):

Expand All @@ -74,7 +74,8 @@ And you will pull in only `.navbar` related styles from Bootstrap.


### inline
> Use `@import (inline)` to include external files, but not process them.

Use `@import (inline)` to include external files, but not process them.

Released [v1.5.0]({{ less.master.url }}CHANGELOG.md)

Expand All @@ -86,7 +87,8 @@ So you can use this to include the file in the output so that all CSS will be in


### less
> Use `@import (less)` to treat imported files as Less, regardless of file extension.

Use `@import (less)` to treat imported files as Less, regardless of file extension.

Released [v1.4.0]({{ less.master.url }}CHANGELOG.md)

Expand All @@ -97,7 +99,8 @@ Example:
```

### css
> Use `@import (css)` to treat imported files as regular CSS, regardless of file extension. This means the import statement will be left as it is.

Use `@import (css)` to treat imported files as regular CSS, regardless of file extension. This means the import statement will be left as it is.

Released [v1.4.0]({{ less.master.url }}CHANGELOG.md)

Expand All @@ -113,7 +116,8 @@ outputs
```

### once
> The default behavior of `@import` statements. It means the file is imported only once and subsequent import statements for that file will be ignored.

The default behavior of `@import` statements. It means the file is imported only once and subsequent import statements for that file will be ignored.

Released [v1.4.0]({{ less.master.url }}CHANGELOG.md)

Expand All @@ -128,7 +132,8 @@ Example:


### multiple
> Use `@import (multiple)` to allow importing of multiple files with the same name. This is the opposite behavior to once.

Use `@import (multiple)` to allow importing of multiple files with the same name. This is the opposite behavior to once.

Released [v1.4.0]({{ less.master.url }}CHANGELOG.md)

Expand All @@ -155,6 +160,7 @@ Outputs
```

### optional
> Use `@import (optional)` to allow importing of a file only when it exists. Without the `optional` keyword Less throws a FileError and stops compiling when importing a file that can not be found.

Use `@import (optional)` to allow importing of a file only when it exists. Without the `optional` keyword Less throws a FileError and stops compiling when importing a file that can not be found.

Released [v2.3.0]({{ less.master.url }}CHANGELOG.md)
185 changes: 185 additions & 0 deletions content/features/plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
Released [v2.5.0]({{ less.master.url }}CHANGELOG.md)

> Import JavaScript plugins to add Less.js functions and features
## Writing your first plugin

Using a `@plugin` at-rule is similar to using an `@import` for your `.less` files.
```less
@plugin "my-plugin"; // automatically appends .js if no extension
```

What can you do with a plugin? A lot, but let's start with the basics. Let's say you write this:

```js
// my-plugin.js

functions.add('pi', function() {
return Math.PI;
});
```
Congratulations! You've written a Less plugin!

If you were to use this in your stylesheet:
```less
@plugin "my-plugin";
.show-me-pi {
value: pi();
}
```
You would get:
```less
.show-me-pi {
value: 3.141592653589793;
}
```
However, you would need to return a proper Less node if you wanted to, say, multiply that against other values or do other Less operations. Otherwise the output in your stylesheet is plain text (which may be fine for your purposes).

Meaning, this is more correct:
```js
functions.add('pi', function() {
return less.Dimension(Math.PI);
});
```
_Note: A dimension is a number with or without a unit, like "10px", which would be `less.Dimension(10, "px")`. For a list of units, see the [Less API](TODO)._

Now you can use your function in operations.
```less
@plugin "my-plugin";
.show-me-pi {
value: pi() * 2;
}
```

You may have noticed that there are available globals for your plugin file, namely a function registry (`functions` object), and the `less` object. These are there for convenience.


## Plugin Scope

Functions added by a `@plugin` at-rule adheres to Less scoping rules. This is great for Less library authors that want to add functionality without introducing naming conflicts.

For instance, say you have 2 plugins from two third-party libraries that both have a function named "foo".
```js
// lib1.js
functions.add('foo', function() {
return "foo";
});

// lib2.js
functions.add('foo', function() {
return "bar";
});
```
That's ok! You can choose which library's function creates which output.
```less
.el-1 {
@plugin "lib1";
value: foo();
}
.el-2 {
@plugin "lib2";
value: foo();
}
```
This will produce:
```less
.el-1 {
value: foo;
}
.el-2 {
value: bar;
}
```

For plugin authors sharing their plugins, that means you can also effectively make private functions by placing them in a particular scope. As in, this will cause an error:
```less
.el {
@plugin "lib1";
}
@value: foo();
```

As of Less 3.0, functions can return any kind of Node type, and can be called at any level.

Meaning, this would throw an error in 2.x, as functions had to be part of the value of a property or variable assignment:
```less
.block {
color: blue;
my-function-rules();
}
```
In 3.x, that's no longer the case, and functions can return At-Rules, Rulesets, any other Less node, strings, and numbers (the latter two are converted to Anonymous nodes).

## Null Functions

There are times when you may want to call a function, but you don't want anything output (such as storing a value for later use). In that case, you just need to return `false` from the function.
```js
var collection = [];

functions.add('store', function(val) {
collection.push(val); // imma store this for later
return false;
});
```
```less
@plugin "collections";
@var: 32;
store(@var);
```
Later you could do something like:
```js
functions.add('retrieve', function(val) {
return less.Value(collection);
});
```
```less
.get-my-values {
@plugin "collections";
values: retrieve();
}
```

## Registering a plugin globally

Plugins can optionally register themselves in the global scope (even if called within a block scope) by exporting an object with a specific signature. All properties of this object are optional, and will only be called if present. It can be returned with a `registerPlugin({...})` call, or you can use the CommonJS `module.exports = {...}` pattern.

_Note: while you can use `module.exports`, other Node.js functionality like `require()` is not provided by Less.js. It's recommended that plugin authors create single-file modules (or single-file builds) of plugins for cross-platform functionality._

The exported object can have any (or none) of these properties.
```js
{
/* Called immediately after the plugin is first imported, only once. */
install: function(less, pluginManager) { },

/* Called for each instance of your @plugin. */
use: function(context) { },

/* Called for each instance of your @plugin, when rules are being evaluated.
* It's just later in the evaluation lifecycle */
eval: function(context) { },

/* Passes an arbitrary string to your plugin e.g. @plugin (args) "file";
* This string is not parsed for you, so it can contain anything */
setOptions: function(argumentString) { },

/* Set a minimum Less compatibility string
* You can also use an array, as in [3, 0] */
minVersion: ['3.0'],

/* Used for lessc plugins only, to explain options in a Terminal */
printUsage: function() { },

}
```
The PluginManager instance for the `install()` function provides methods for adding visitors, file managers, and post-processors.

Here are some example repos showing the different plugin types. <!-- TODO: updated examples -->
- post-processor: https://github.com/less/less-plugin-clean-css
- visitor: https://github.com/less/less-plugin-inline-urls
- file-manager: https://github.com/less/less-plugin-npm-import

## Pre-Loaded Plugins

While a `@plugin` call works well for most scenarios, there are times when you might want to load a plugin before parsing starts.

See: [Pre-Loaded Plugins](/usage/#plugins) in the "Using Less.js" section for how to do that.
62 changes: 19 additions & 43 deletions content/tools/online-less-compilers.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,25 @@
title: Online Less Compilers
---

### [less2css.org](http://less2css.org/)
> Online Integrated Development Environment (IDE) that is hosted in a browser allowing users to edit and compile Less to CSS in real-time.
### [winless.org/online-less-compiler](http://winless.org/online-less-compiler)
> This Online Less Compiler can help you to learn Less. You can go through the examples below or try your own Less code.
### [lesstester.com](http://lesstester.com/)
> Online compiler for Less CSS.
### [dopefly.com/less-converter](http://www.dopefly.com/less-converter/less-converter.html)
> A simple Less CSS file converter using the Less JS project.
### [lessphp.gpeasy.com/demo](http://lessphp.gpeasy.com/demo)
> [less.php](http://lessphp.gpeasy.com/) live demo.
### [leafo.net/lessphp/editor](http://leafo.net/lessphp/editor.html)
> [lessphp](http://leafo.net/lessphp/) live demo.
### [precess](http://precess.co/)
> A real time preprocesser compiler.
### [estFiddle](http://ecomfe.github.io/est/fiddle/)
> Online Less compiler providing live demo for Less and [est](http://ecomfe.github.io/est/). Allowing users to switch among all versions of Less after `1.4.0` with optional est/Autoprefixer functionalities.
### [ILess](http://demo-iless.rhcloud.com/)
> Live demo of [ILess](https://github.com/mishal/iless) PHP compiler
### [BeautifyTools Less Compiler](http://beautifytools.com/less-compiler.php)
> Online Less compiler with optional formatting and minification at [BeautifyTools](http://beautifytools.com)
| | |
|---|---|
| [less2css.org](http://less2css.org/) | Online Integrated Development Environment (IDE) that is hosted in a browser allowing users to edit and compile Less to CSS in real-time. |
| [winless.org/online-less-compiler](http://winless.org/online-less-compiler) | This Online Less Compiler can help you to learn Less. You can go through the examples below or try your own Less code. |
| [lesstester.com](http://lesstester.com/) | Online compiler for Less CSS. |
| [dopefly.com/less-converter](http://www.dopefly.com/less-converter/less-converter.html) | A simple Less CSS file converter using the Less JS project. |
| [lessphp.gpeasy.com/demo](http://lessphp.gpeasy.com/demo) | [less.php](http://lessphp.gpeasy.com/) live demo. |
| [leafo.net/lessphp/editor](http://leafo.net/lessphp/editor.html) | [lessphp](http://leafo.net/lessphp/) live demo. |
| [precess](http://precess.co/) | A real time preprocesser compiler. |
| [estFiddle](http://ecomfe.github.io/est/fiddle/) | Online Less compiler providing live demo for Less and [est](http://ecomfe.github.io/est/). Allowing users to switch among all versions of Less after `1.4.0` with optional est/Autoprefixer functionalities. |
| [ILess](http://demo-iless.rhcloud.com/) | Live demo of [ILess](https://github.com/mishal/iless) PHP compiler |
| [BeautifyTools Less Compiler](http://beautifytools.com/less-compiler.php) | Online Less compiler with optional formatting and minification at [BeautifyTools](http://beautifytools.com) |

## Online Web IDEs/Playgrounds with Less support

### [CSSDeck Labs](http://cssdeck.com/labs)
> CSSDeck Labs is a place where you can quickly create some experiments (or testcases) that involves HTML, CSS, JS code.
### [CodePen](http://codepen.io)
> CodePen is a playground for the front end side of the web.
### [Fiddle Salad](http://fiddlesalad.com/less/)
> An online playground with an instantly ready coding environment.
### [JS Bin](http://jsbin.com)
> JS Bin is a webapp specifically designed to help JavaScript and CSS folk test snippets of code.
### [jsFiddle](http://jsfiddle.net/hb2rsm2x)
> Online Web Editor
| | |
|---|---|
| [CSSDeck Labs](http://cssdeck.com/labs) | CSSDeck Labs is a place where you can quickly create some experiments (or testcases) that involves HTML, CSS, JS code. |
| [CodePen](http://codepen.io) | CodePen is a playground for the front end side of the web. |
| [Fiddle Salad](http://fiddlesalad.com/less/) | An online playground with an instantly ready coding environment. |
| [JS Bin](http://jsbin.com) | JS Bin is a webapp specifically designed to help JavaScript and CSS folk test snippets of code. |
| [jsFiddle](http://jsfiddle.net/hb2rsm2x) | Online Web Editor |
Loading

0 comments on commit 355f564

Please sign in to comment.