feat: Flat import of markdown repo
This is a flat (without history) import of (some of) the content from our markdown module. We've imported this without history because the repo contains our blog posts and showcases posts content prior to porting them to strapi. Since this contains many images, it would balloon the size of this repo to import the full history. Instead, please refer to the history of the (archived) markdown repo at: https://github.com/freesewing/markdown
This commit is contained in:
parent
1671a896b5
commit
b34a2ee2ed
6132 changed files with 244167 additions and 0 deletions
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
title: Conditionally loading build-time plugins
|
||||
order: 30
|
||||
---
|
||||
|
||||
You can choose to load your build-time plugin conditionally based on run-time data.
|
||||
|
||||
To do so, you need to create a `condition` method that will determine whether the
|
||||
plugin will be loaded. This method receives the complete settings object and should
|
||||
return `true` if the plugin is to be loaded, and `false` if it should not be loaded.
|
||||
|
||||
```js
|
||||
const condition = settings => {
|
||||
if (settings) {
|
||||
// Remember, settings contains:
|
||||
// settings.options => The user's options
|
||||
// settings.measurements => The measurements
|
||||
return true // Load the plugin
|
||||
}
|
||||
else return false // Do not load the plugin
|
||||
}
|
||||
```
|
||||
You pass your plugin and condition method as a third parameter to the Design constructor
|
||||
with the `plugin` and `condition` keys respectively.
|
||||
|
||||
Let's look at a complete example to illustrate this:
|
||||
|
||||
```js
|
||||
import freesewing from '@freesewing/core'
|
||||
import plugins from '@freesewing/plugin-bundle'
|
||||
import myConditionalPlugin from '@freesewing/plugin-bust'
|
||||
|
||||
const myConditionalPluginCheck = (settings = false) =>
|
||||
settings &&
|
||||
settings.options &&
|
||||
settings.options.draftForHighBust &&
|
||||
settings.measurements.highBust
|
||||
? true
|
||||
: false
|
||||
|
||||
const Pattern = new freesewing.Design(
|
||||
config,
|
||||
plugins,
|
||||
{
|
||||
plugin: myConditionalPlugin,
|
||||
condition: myConditionalPluginCheck
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Our condition method will return `true` only if the following conditions are met:
|
||||
|
||||
- A `settings` object is passed into the method
|
||||
- `settings.options` is _truthy_
|
||||
- `settings.options.draftForHighBust` is _truthy_
|
||||
- `settings.options.measurements.highBust` is _truthy_
|
||||
|
||||
This is a real-world example from our Teagan pattern. A t-shirt pattern that can be
|
||||
drafted to the high bust (rather than the full chest circumference) if the user
|
||||
choses so.
|
||||
|
||||
But that feat is handled auto-magically by `plugin-bust` which is a build-time plugin.
|
||||
So whether to load this plugin or not hinges on the user settings, which is why we
|
||||
load this plugin conditionally.
|
||||
|
25
markdown/dev/guides/plugins/en.md
Normal file
25
markdown/dev/guides/plugins/en.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: Plugin guide
|
||||
order: 400
|
||||
icons:
|
||||
- logo
|
||||
- plugin
|
||||
for: developers
|
||||
about: |
|
||||
This guide shows you everything you need to know to understand plugins in FreeSewing, and create your own.
|
||||
goals:
|
||||
- Know about build-time plugins vs run-time plugins
|
||||
- Understanding plugin structure
|
||||
- Hooks and how to use them
|
||||
- Using hooks without a plugin
|
||||
- Using macros
|
||||
---
|
||||
|
||||
Plugins allow you to extend FreeSewing.
|
||||
|
||||
We have [a list of available plugins](/reference/plugins/), but
|
||||
if you can't find what you're looking for, you can write your own plugin.
|
||||
|
||||
We'll cover the following topics in this guide:
|
||||
|
||||
<ReadMore list />
|
21
markdown/dev/guides/plugins/hooks/en.md
Normal file
21
markdown/dev/guides/plugins/hooks/en.md
Normal file
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
title: Hooks
|
||||
order: 60
|
||||
---
|
||||
|
||||
A **hook** is a lifecycle event. The available hooks are:
|
||||
|
||||
- [preRender](/reference/hooks/prerender/): Called at the start of [`Pattern.render()`](/reference/api/pattern#render)
|
||||
- [postRender](/reference/hooks/postrender/): Called at the end of [`Pattern.render()`](/reference/api/pattern#render)
|
||||
- [insertText](/reference/hooks/inserttext/): Called when inserting text
|
||||
- [preDraft](/reference/hooks/predraft/): Called at the start of [`Pattern.draft()`](/reference/api/pattern#draft)
|
||||
- [postDraft](/reference/hooks/postdraft/): Called at the end of [`Pattern.draft()`](/reference/api/pattern#draft)
|
||||
- [preSample](/reference/hooks/presample/): Called at the start of [`Pattern.sample()`](/reference/api/pattern#sample)
|
||||
- [postSample](/reference/hooks/postsample/): Called at the end of [`Pattern.sample()`](/reference/api/pattern#sample)
|
||||
|
||||
You can register a method for a hook. When the hook is triggered, your method will be
|
||||
called. It will receive two parameters:
|
||||
|
||||
- An object relevant to the hook. See the [hooks API reference](/reference/hooks/) for details.
|
||||
- Data passed when the hook was registered (optional)
|
||||
|
27
markdown/dev/guides/plugins/loading-build-time-plugins/en.md
Normal file
27
markdown/dev/guides/plugins/loading-build-time-plugins/en.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
title: Loading build-time plugins
|
||||
order: 20
|
||||
---
|
||||
|
||||
Build-time plugins are loaded at build time, by passing them to
|
||||
the [`freesewing.Design`](/reference/api/#design) constructor:
|
||||
|
||||
```js
|
||||
import freesewing from "@freesewing/core"
|
||||
import plugins from "@freesewing/plugin-bundle"
|
||||
import config from "../config"
|
||||
|
||||
const Pattern = new freesewing.Design(config, plugins)
|
||||
```
|
||||
|
||||
If you have multiple plugins to load, you can pass them as an array:
|
||||
|
||||
```js
|
||||
import freesewing from "@freesewing/core"
|
||||
import plugins from "@freesewing/plugin-bundle"
|
||||
import gorePlugin from "@freesewing/plugin-gore"
|
||||
import config from "../config"
|
||||
|
||||
const Pattern = new freesewing.Design(config, [plugins, gorePlugin] )
|
||||
```
|
||||
|
26
markdown/dev/guides/plugins/loading-run-time-plugins/en.md
Normal file
26
markdown/dev/guides/plugins/loading-run-time-plugins/en.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
title: Loading run-time plugins
|
||||
order: 40
|
||||
---
|
||||
|
||||
Run-time plugin are loaded at run time, by passing them to the `use` method of
|
||||
an instatiated pattern. That method is chainable, so if you have multiple plugins
|
||||
you can just chain them together:
|
||||
|
||||
```js
|
||||
import Aaron from "@freesewing/aaron";
|
||||
import theme from "@freesewing/plugin-theme";
|
||||
import i18n from "@freesewing/plugin-i18n";
|
||||
|
||||
const myAaron = new Aaron()
|
||||
.use(theme)
|
||||
.use(i18n)
|
||||
```
|
||||
|
||||
<Tip>
|
||||
|
||||
Plugins that use only hooks are typically run-time plugins
|
||||
|
||||
</Tip>
|
||||
|
||||
|
64
markdown/dev/guides/plugins/macros/en.md
Normal file
64
markdown/dev/guides/plugins/macros/en.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
title: Macros
|
||||
order: 90
|
||||
---
|
||||
|
||||
Plugin structure for macros is similar, with a few changes:
|
||||
|
||||
- Rather than the hook name, you provide the macro name (that you choose yourself)
|
||||
- The context (`this`) of a macro method is **always** a [Part](/reference/api/part) object.
|
||||
|
||||
Apart from these, the structure is very similar:
|
||||
|
||||
```js
|
||||
import {name, version} from '../package.json';
|
||||
|
||||
export default {
|
||||
name,
|
||||
version,
|
||||
macros: {
|
||||
box: function(so) {
|
||||
this.points.boxTopLeft = so.anchor;
|
||||
this.points.boxTopRight = so.anchor.shift(0, so.size);
|
||||
this.points.boxBottomRight = this.points.boxTopRight.shift(-90, so.size);
|
||||
this.points.boxBottomLeft = new this.Point(so.anchor.x, this.points.boxBottomRight.y);
|
||||
|
||||
this.paths.box = new this.Path()
|
||||
.move(this.points.boxTopLeft)
|
||||
.line(this.points.boxTopRight)
|
||||
.line(this.points.boxBottomRight)
|
||||
.line(this.points.boxBottomLeft)
|
||||
.close()
|
||||
.attr('class', 'box');
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Did you figure out what this plugin does?
|
||||
It provides a `box` macro that draws a box on our pattern in a given location with a give size.
|
||||
|
||||
We can use it like this:
|
||||
|
||||
```js
|
||||
points.boxAnchor = new Point(100, 100);
|
||||
macro('box', {
|
||||
anchor: points.boxAnchor
|
||||
size: 25
|
||||
});
|
||||
```
|
||||
|
||||
Obviously, you can expect to learn how to call a macro in its documentation,
|
||||
rather than have to comb through its code.
|
||||
|
||||
<Note>
|
||||
|
||||
###### Macros take only 1 argument
|
||||
|
||||
When writing a macro, keep in mind that all information that needs to be passed
|
||||
to a macro needs to be contained in a single argument.
|
||||
|
||||
Typically, you use a single plain object to configure the macro.
|
||||
|
||||
</Note>
|
||||
|
25
markdown/dev/guides/plugins/plugin-structure/en.md
Normal file
25
markdown/dev/guides/plugins/plugin-structure/en.md
Normal file
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
title: Plugin structure
|
||||
order: 50
|
||||
---
|
||||
|
||||
Plugins can do two things:
|
||||
|
||||
- They can use hooks
|
||||
- They can provide macros
|
||||
|
||||
Your plugin should export an object with the following structure:
|
||||
|
||||
```js
|
||||
{
|
||||
name: 'myPlugin',
|
||||
version: '1.0.0',
|
||||
hooks: {},
|
||||
macros: {}
|
||||
};
|
||||
```
|
||||
|
||||
The `name` and `version` attributes are self-explanatory.
|
||||
The [hooks](/guides/plugins/hooks/) and [macros](/guides/plugins/macros/) sections
|
||||
explain the `hooks` and `macros` properties.
|
||||
|
38
markdown/dev/guides/plugins/types-of-plugins/en.md
Normal file
38
markdown/dev/guides/plugins/types-of-plugins/en.md
Normal file
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
title: Types of plugins
|
||||
order: 10
|
||||
---
|
||||
|
||||
Plugins come in two flavours:
|
||||
|
||||
- [Build-time plugins](#build-time-plugins)
|
||||
- [Run-time plugins](#run-time-plugins)
|
||||
|
||||
When writing a plugin, ask yourself whether it's a run-time or a build-time plugin.
|
||||
And if the answer is both, please split them into two plugins.
|
||||
|
||||
## Build-time plugins
|
||||
|
||||
A plugin is a build-time plugin if it is required by the pattern at build-time.
|
||||
In other words, the plugin is a dependency for the pattern, and if it's missing
|
||||
the pattern won't load.
|
||||
|
||||
<Tip>
|
||||
|
||||
Our [plugin bundle](/reference/plugins/bundle/) bundles build-time plugins that are used in many patterns.
|
||||
|
||||
</Tip>
|
||||
|
||||
<Note>Plugins that provide a macro are typically build-time plugins</Note>
|
||||
|
||||
|
||||
## Run-time plugins
|
||||
|
||||
A plugin is a run-time plugin if it can be added after instantiating your pattern.
|
||||
Think of it as a plugin to be used in the front-end.
|
||||
|
||||
Run-time plugins are not a dependecy of the pattern. They just _add something_ to it.
|
||||
|
||||
Our [theme plugin](/reference/plugins/theme/) is a good example of a run-time plugin.
|
||||
If it's missing, your pattern will still work, it just won't look pretty.
|
||||
|
26
markdown/dev/guides/plugins/using-hooks-more-than-once/en.md
Normal file
26
markdown/dev/guides/plugins/using-hooks-more-than-once/en.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
title: Using hooks more than once
|
||||
order: 80
|
||||
---
|
||||
|
||||
What if you want to attach more than one method to a hook?
|
||||
You could spread them over seperate plugins, but there's a better way.
|
||||
|
||||
Rather than assigning a method to your hook, assign an array of methods like this:
|
||||
|
||||
```js
|
||||
import myCoolMethod from './method-a';
|
||||
import myEvenCoolerMethod from './method-b';
|
||||
import {name, version} from '../package.json';
|
||||
|
||||
export default {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: [
|
||||
myCoolMethod,
|
||||
myEvenCoolerMethod
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
20
markdown/dev/guides/plugins/using-hooks-without-plugin/en.md
Normal file
20
markdown/dev/guides/plugins/using-hooks-without-plugin/en.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
title: Using hooks without a plugin
|
||||
order: 85
|
||||
---
|
||||
|
||||
You can attach a method to a hook at run-time without the need for a plugin
|
||||
using the [Pattern.on()](/reference/api/pattern/on) method.
|
||||
|
||||
The method takes the hook name as its first argument, and the hook method as its second.
|
||||
|
||||
Below is an example:
|
||||
|
||||
```js
|
||||
pattern.on('preRender', function(svg) {
|
||||
svg.style += "svg { background: yellow;}";
|
||||
});
|
||||
```
|
||||
|
||||
Congratulations, you've just made your pattern yellow.
|
||||
|
59
markdown/dev/guides/plugins/using-hooks/en.md
Normal file
59
markdown/dev/guides/plugins/using-hooks/en.md
Normal file
|
@ -0,0 +1,59 @@
|
|||
---
|
||||
title: Using hooks
|
||||
order: 70
|
||||
---
|
||||
|
||||
For each hook, your plugin should provide a method that takes the relevant data
|
||||
as its first argument. If data was passed when the hook was loaded, you will receive
|
||||
that as the second object.
|
||||
|
||||
Remember that:
|
||||
|
||||
- The `insertText` hook will receive a locale and string and you should return a string.
|
||||
- All other hooks receive an object. You don't need to return anything, but rather modify the object you receive.
|
||||
|
||||
Let's look at an example:
|
||||
|
||||
```js
|
||||
import myStyle from './style';
|
||||
import myDefs from './defs';
|
||||
import {name, version} from '../package.json';
|
||||
|
||||
export default {
|
||||
name,
|
||||
version,
|
||||
hooks: {
|
||||
preRender: function(svg) {
|
||||
if (svg.attributes.get("freesewing:plugin-"+name) === false) {
|
||||
svg.style += myStyle;
|
||||
svg.defs += myDefs;
|
||||
svg.attributes.add("freesewing:plugin-"+name, version);
|
||||
}
|
||||
},
|
||||
insertText: function(text) {
|
||||
return text.toUpperCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is a complete plugin, ready to be published on NPM. It uses two hooks:
|
||||
|
||||
- `preRender` : We add some style and defs to our SVG
|
||||
- `insertText` : We transfer all text to UPPERCASE
|
||||
|
||||
<Note>
|
||||
|
||||
###### Note that we avoid running our hook twice
|
||||
|
||||
As you can see, the last thing we do in the `preRender` hook is set an attribute on
|
||||
the SVG tag with the name and version of our plugin.
|
||||
|
||||
We check for this attribute when the `preRender` hook runs, thereby avoiding that
|
||||
our styles and defs will be added twice.
|
||||
|
||||
It is good practice to wrap you hook methods in a call like this, because you have
|
||||
no guarantee the user won't render your pattern more than once.
|
||||
|
||||
</Note>
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue