Skip to content

Commit c624d07

Browse files
aaronfrostVillanuevand
authored andcommitted
refactor(docs): Add extra information about plugins
Extra grammar changes.
1 parent 0261152 commit c624d07

2 files changed

Lines changed: 195 additions & 24 deletions

File tree

docs/plugins.md

Lines changed: 191 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,94 @@
1-
# Plugins
1+
# <a name="plugins"></a> Plugins
22

3-
Scully uses a plugin system to allow users to define new ways for Scully to build your app. There are two main types of
4-
plugins:
3+
Scully uses a plugin system to allow users to define new ways for Scully to pre-render your app. There are three main
4+
types of plugins:
55

6-
1. [Route Plugins](#route-plugins)
7-
2. [Data Transform Plugins](#transform-plugins)
6+
1. [Router Plugins](#router-plugin)
7+
2. [Render Plugins](#render-plugin)
8+
3. [File Handler Plugins](#file-plugin)
89

910
See our [Recommended Plugins](recommended-plugins.md) page to find a list of available plugins.
1011

11-
## <a name="route-plugins"></a> Route Plugins
12+
---
1213

13-
Scully needs __Route Plugins__ to discover data needed to pre-render your app's views. Any route that has a route
14-
parameter in it will require you to configure a plugin that teaches Scully how to get the data needed for those route
15-
parameters.
14+
## <a name="router-plugin"></a> Router Plugins
1615

17-
Let's look at an example. Suppose your app has a route `{path: 'user/:userId', component: UserComponent}`. In order for
18-
Scully to pre-render your app, it needs to know the complete list of User IDs that will be used in that route parameter
19-
`:userId`. If your app had 5 users with the IDs 1, 2, 3, 4, and 5, then Scully would need to render the following routes:
16+
### <a name="router-plugin-what-is"></a> What is a Router Plugin?
17+
18+
Scully needs __router plugins__ to discover data needed to pre-render your app's views. Any route that has a route
19+
parameter in it will require you to configure a __router plugin__ that teaches Scully how to get the data needed for
20+
those route parameters.
21+
22+
Suppose your app has a route `{path: 'user/:userId', component: UserComponent}`. In order for Scully to pre-render your
23+
app, it needs to know the complete list of User IDs that will be used in that route parameter `:userId`. If your app
24+
had 5 users with the IDs 1, 2, 3, 4, and 5, then Scully would need to render the following routes:
2025
```
21-
/user/10
22-
/user/11
23-
/user/12
24-
/user/13
25-
/user/14
26+
/user/1
27+
/user/2
28+
/user/3
29+
/user/4
30+
/user/5
2631
```
2732

28-
To provide this list of User IDs to Scully, you'll use a __Route Plugins__.
33+
A __router plugin__ is used to convert the raw route config into a list of routes that scully can then crawl/render.
34+
35+
### <a name="router-plugin-interface"></a> Router Plugin Interface
36+
37+
A __router plugin__ is a function that returns a `Promise<HandledRoute[]>`. Let's look at the interface of the route
38+
plugin as well as the `HandledRoute`.
39+
40+
```typescript
41+
interface HandledRoute {
42+
route: string;
43+
}
44+
45+
function exampleRouterPlugin(route: string, config: any) : Promise<HandledRoute[]> {
46+
// must return a promise here
47+
}
48+
```
49+
50+
The `HandledRoute[]` gets added into the `scully-routes.json` that is generated when you run `npm run scully`.
51+
52+
### <a name="router-plugin-how-to"></a> How To Make A Router Plugin
53+
In our previous example of an app with the route `/user/:userId` where we have five distinct userIds, here is a __router
54+
plugin__ that would turn the raw route into five distinct HandledRoutes.
55+
56+
```typescript
57+
function userIdPlugin(route: string, config = {}): Promise<HandledRoute[]> {
58+
return Promise.resolve(
59+
[
60+
{ route: '/user/1' },
61+
{ route: '/user/2' },
62+
{ route: '/user/3' },
63+
{ route: '/user/4' },
64+
{ route: '/user/5' },
65+
]
66+
);
67+
}
68+
// DON'T FORGET THIS STEP
69+
registerPlugin('router', 'userIds', userIdPlugin);
70+
```
71+
72+
Once we have built a plugin, we can configure our `scully.config.js` to use our plugin.
73+
74+
### <a name="router-plugin-configure"></a> How To Configure A Router Plugin
75+
76+
The following configuration uses our `userIds` router plugin to get the `HandledRoute[]` for our app:
77+
78+
```javascript
79+
// scully.config.js
80+
exports.config = {
81+
// Add the following to your file
82+
routes: {
83+
"/user/:userId": {
84+
"type": "userIds",
85+
}
86+
}
87+
};
88+
```
2989

3090
The following is an example that uses the [jsonplaceholder](https://jsonplaceholder.typicode.com/) to fetch a list of
31-
User IDs for my app.
91+
User IDs for my app. It uses the `json` plugin.
3292

3393
```javascript
3494
// scully.config.js
@@ -53,10 +113,120 @@ second is `property`. The JSON plugin will pluck the provided property name fro
53113
means that the array returned by the jsonplaceholder api will each have an `id` property. So instead of returning a list
54114
users, it will return a list of userIds.
55115

116+
### <a name="router-plugin-configure"></a> Router Plugin Examples
117+
For those looking to build router plugins for their app, here are links to the built-in __router plugins__ in Scully:
118+
- [JSON Plugin](../scully/routerPlugins/jsonRoutePlugin.ts)
119+
- [Content Folder Plugin](../scully/routerPlugins/contentFolderPlugin.ts)
120+
121+
[Back to top](#plugins)
122+
123+
---
124+
125+
## <a name="render-plugin"></a> Render Plugins
56126

57-
## <a name="transform-plugins"></a> Data Transform Plugins
127+
### <a name="render-plugin-what-is"></a> What is a Render Plugin?
128+
129+
A __render plugin__ is used to transform the HTML that your app rendered. After your Angular app renders the page,
130+
that rendered content/HTML is passed to a __render plugin__ where it can be further modified. An example of why you
131+
would want to use a render plugin: to transform a page that contains markdown into a page that contains the rendered
132+
markdown.
133+
134+
### <a name="render-plugin-interface"></a> Render Plugin Interface
135+
136+
A __render plugin__ is a function that returns a `Promise<String>`. The string in the promise must be the transformed
137+
HTML. Here is what the interface looks like:
138+
```typescript
139+
function exampleContentPlugin(HTML: string, route: HandledRoute) : Promise<string> {
140+
// must return a promise here
141+
}
142+
```
143+
144+
### <a name="render-plugin-how-to"></a> How To Make A Render Plugin
145+
The following is a sample __render plugin__ that adds a title to the head of a page if it doesn't find one.
146+
147+
```ecmascript 6
148+
function defaultTitlePlugin(html, route) {
149+
// If no title in the document
150+
if(html.indexOf('<title') < 0) {
151+
const splitter = '</head>';
152+
const [begin, end] = html.split(splitter);
153+
const defaultTitle = `<title>The Truth Is Out There!</title>`;
154+
return Promise.resolve(`${begin}${defaultTitle}${splitter}${end}`);
155+
}
156+
return Promise.resolve(html);
157+
}
158+
// DON'T FORGET THIS STEP
159+
registerPlugin('render', 'defaultTitle', defaultTitlePlugin);
160+
```
161+
162+
In this example, the HTML that the Angular app rendered is transformed to include a title (if one wasn't found). This
163+
is the primary function of a render plugin.
164+
165+
Here is another example that would replace any instances of `:)` with a smiley emoji:
166+
167+
```ecmascript 6
168+
function smileEmojiPlugin(html, route) {
169+
return Promise.resolve(html.replace(/\:\)/g, '😊'));
170+
}
171+
// This registers your plugin as
172+
registerPlugin('render', 'smiles', smileEmojiPlugin);
173+
```
174+
175+
176+
### <a name="render-plugin-configure"></a> Render Plugin Examples
177+
Here are links to the built-in __render plugins__ in Scully:
178+
- [Route Content Renderer Plugin](../scully/renderPlugins/routeContentRenderer.ts)
179+
- [Content Folder Plugin](../scully/)
180+
181+
[Back to top](#plugins)
182+
183+
---
184+
185+
## <a name="file-plugin"></a> File Handler Plugins
186+
187+
188+
### <a name="file-plugin-what-is"></a> What is a File Handler Plugin?
189+
190+
A __file handler plugin__ is used by the `contentFolder` plugin during the `render` process. As the `contentFolder`
191+
plugin processes the folders for markdown files or whatever they contain, it ends that process by seeing if a
192+
`fileHandler` plugin exists for that file extenion type.
193+
194+
Scully comes with two built-in `fileHandler` plugins. The [markdown plugin](../scully/fileHanderPlugins/markdown.ts) and
195+
the [asciidoc plugin](../scully/fileHanderPlugins/asciidoc.ts). These two plugins are there to handle and process the
196+
content of those types of files as they are read from the file system.
197+
198+
Suppose you wanted to support `.docx` files, or `.csv` files, or anything else. You would want to add a file handler
199+
for those types of files. The `contentFolder` plugin will take care of reading those files from the filesystem, but
200+
what if you wanted to transform them somehow AFTER the `contentFolder` plugin reads them. You would need a `fileHandler`
201+
plugin for this.
202+
203+
### <a name="file-plugin-interface"></a> File Handler Plugin Interface
204+
205+
A __file handler plugin__ is a function that returns a `Promise<string>`. Here is what the interface looks like:
206+
```typescript
207+
function exampleFileHandlerPlugin(rawContent: string) : Promise<string> {
208+
// must return a promise here
209+
}
210+
```
211+
212+
### <a name="file-plugin-how-to"></a> How To Make A File Handler Plugin
213+
214+
The following is a sample __file handler plugin__ that handles CSV by wrapping it in a code block. You could of course,
215+
do something much more elaborate like create a table or a grid for this data. Example:
216+
217+
```ecmascript 6
218+
function csvFilePlugin(raw) {
219+
return Promise.resolve(`<pre><code>${code}</code></pre>`);
220+
}
221+
// This registers your plugin
222+
registerPlugin('fileHandler', 'csv', { handler: csvFilePlugin});
223+
```
58224

59-
Describe data transform plugins
225+
### <a name="file-plugin-configure"></a> File Handler Plugin Examples
226+
Here are links to the built-in __render plugins__ in Scully:
227+
- [asciidoc Plugin](../scully/fileHanderPlugins/asciidoc.ts)
228+
- [markdown Plugin](../scully/fileHanderPlugins/markdown.ts)
60229

230+
[Back to top](#plugins)
61231

62232
[Full Documentation ➡️](scully.md)

docs/scully.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
## What is Scully?
44

55
**Scully** is freaking awesome. Why? Because it can create static sites using Angular.
6-
So basically **Scully** is a SSG (static site generator) for Angular.
6+
In other words, **Scully** is a SSG (static site generator) for Angular.
77

8-
### How does it do it?
8+
### How does it work?
99

10-
The magic happens thanks to its Node.js CLI application. It allows you to use schematics for a simple work flow.
10+
Under the hood, Scully analyzes your project and generates a static version of your website. Scully provides you with
11+
a few node commands and several Angular schematics to make this all __AS EASY AS POSSIBLE!__
1112

1213
Scully works on Windows, Linux and macOS.
1314

0 commit comments

Comments
 (0)