Skip to content

Commit

Permalink
Add _meta info with information about insert index
Browse files Browse the repository at this point in the history
  • Loading branch information
reod committed May 29, 2019
1 parent 7abb7fe commit 6148527
Show file tree
Hide file tree
Showing 23 changed files with 260 additions and 94 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
.idea
.vscode
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Changed

## [2.0.0] - 2019-05-29

### Added

- Each item now has a `_meta` property with `insertIndex`. When using build-in rendering it's automagically stripped.

## [1.1.0] - 2018-12-20

### Added

- Rendering set tags to HTML with `render()` method.

## [1.0.0] - 2018-12-05

### Added

- First version.
71 changes: 49 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,103 @@
[![Known Vulnerabilities](https://snyk.io/test/github/reod/koa-head/badge.svg?targetFile=package.json)](https://snyk.io/test/github/reod/koa-head?targetFile=package.json)

# koa-head

A document head manager middleware for koa.

## Installation

`npm i koa-head`

## TL;DR example
**note:** this package can be used as native ES6 module but has fallback to CommonJS `require`.

**note:** this package can be used as native ES6 module but has fallback to CommonJS `require`.

```js
import Koa from 'koa';
import koaHead from 'koa-head';
import Koa from "koa";
import koaHead from "koa-head";

const app = new Koa();

app
.use(koaHead())
.use(async (ctx, next) => {
ctx.documentHead.setTitle('Title for my webpage');
ctx.documentHead.addMetaTag({ name: 'twitter:card', content: 'summary_large_image' });
ctx.documentHead.addLink({ rel: 'canonical', href: 'index.html' });
ctx.documentHead.addStyle('body { background: aliceblue; }');
ctx.documentHead.setTitle("Title for my webpage");
ctx.documentHead.addMetaTag({
name: "twitter:card",
content: "summary_large_image"
});
ctx.documentHead.addLink({ rel: "canonical", href: "index.html" });
ctx.documentHead.addStyle("body { background: aliceblue; }");
ctx.documentHead.addScript("{ fixture: 'test fixture' }");

await next();
})
.use(ctx => {
const documentHead = ctx.documentHead.toHTML();
const userData = { name: 'John Doe' };
const userData = { name: "John Doe" };

await ctx.myAwesomeLayoutEngine('user-view', {
await ctx.myAwesomeLayoutEngine("user-view", {
documentHead,
userData,
})
userData
});
});

app.listen(3333);
```

will make `documentHead` variable to contain:

```html
<title>Title for my webpage</title>
<meta name="twitter:card" content="summary_large_image" />
<link rel="canonical" href="index.html" />
<style type="text/css">body { background: aliceblue; }</style>
<script type="text/javascript">{ fixture: 'test fixture' }</script>
<style type="text/css">
body {
background: aliceblue;
}
</style>
<script type="text/javascript">
{
fixture: "test fixture";
}
</script>
```
so you can use it in a place in your layout.

so you can use it in a place in your layout.

## Available methods

### `.setTitle( string | object )`

Set document title.

### `.addMetaTag( object )`

Add `<meta />` tag.

### `.addLink( object )`

Add `<link />` tag.

### `.addStyle( string | object )`

Add `<style />` tag.

### `.addScript( string | object )`

Add `<script />` tag.

### `.toHtml()`

Render all set content to coresponding HTML tags.

## Middleware factory function config

| Option | Description | Default value |
|---|---|---|
| `ctxNamespace` | Name under which middleware is exposed in `cxt` object and is used by other middlewares i.e. `ctx.documentHead.setTitle('Hello')`. | `'documentHead'` |
| `stateNamespace` | Name under which middleware stores values in `ctx.state` | `'documentHead'` |
| `documentTitleFormatter` | If set, all values passed to `.setTitle()` function will pe parsed by this formatter. | `title => title` |
| `toHtml` | Config for toHtml function. | `{ [default_values] }` |
|`toHtml.tagSeparator` | Separator between tags inside one group. | `\n` |
|`toHtml.groupSeparator` | Separator between group of tags. | `\n\n` |
| Option | Description | Default value |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ---------------------- |
| `ctxNamespace` | Name under which middleware is exposed in `cxt` object and is used by other middlewares i.e. `ctx.documentHead.setTitle('Hello')`. | `'documentHead'` |
| `stateNamespace` | Name under which middleware stores values in `ctx.state` | `'documentHead'` |
| `documentTitleFormatter` | If set, all values passed to `.setTitle()` function will pe parsed by this formatter. | `title => title` |
| `toHtml` | Config for toHtml function. | `{ [default_values] }` |
| `toHtml.tagSeparator` | Separator between tags inside one group. | `\n` |
| `toHtml.groupSeparator` | Separator between group of tags. | `\n\n` |
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "koa-head",
"version": "1.2.0",
"version": "2.0.0",
"description": "A document head manager middleware for koa",
"main": "src/index",
"scripts": {
Expand All @@ -27,4 +27,4 @@
"webpack": "^4.27.0",
"webpack-cli": "^3.1.2"
}
}
}
11 changes: 8 additions & 3 deletions src/add-link/add-link.spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import createAddLink from "./index";
import test from "tape";
import config from "./../config";
import { createCtxWithKoaHead } from "./../../test/test-helpers";
import { createCtxWithKoaHead, createState } from "./../../test/test-helpers";

test("addLink", async t => {
const ctx = await createCtxWithKoaHead();
const addLink = createAddLink(config, ctx);
const expectedLink = { rel: "rel", content: "rel-content" };
const state = createState();
const addLink = createAddLink(config, state, ctx);
const expectedLink = {
rel: "rel",
content: "rel-content",
_meta: { insertIndex: 0 }
};

addLink(expectedLink);

Expand Down
7 changes: 5 additions & 2 deletions src/add-link/index.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export default (config, ctx) => prop => {
ctx.state[config.stateNamespace].links.push(prop);
import { insertProp } from "../prop";

export default (config, state, ctx) => prop => {
const fullProp = insertProp(state, prop);
ctx.state[config.stateNamespace].links.push(fullProp);
};
11 changes: 8 additions & 3 deletions src/add-meta-tag/add-meta-tag.spec.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import createAddMetaTag from "./index";
import test from "tape";
import config from "./../config";
import { createCtxWithKoaHead } from "./../../test/test-helpers";
import { createCtxWithKoaHead, createState } from "./../../test/test-helpers";

test("addMetaTag", async t => {
const ctx = await createCtxWithKoaHead();
const addMetaTag = createAddMetaTag(config, ctx);
const expectedMetaTag = { name: "meta-name", content: "meta-content" };
const state = createState();
const addMetaTag = createAddMetaTag(config, state, ctx);
const expectedMetaTag = {
name: "meta-name",
content: "meta-content",
_meta: { insertIndex: 0 }
};

addMetaTag(expectedMetaTag);

Expand Down
7 changes: 5 additions & 2 deletions src/add-meta-tag/index.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export default (config, ctx) => prop => {
ctx.state[config.stateNamespace].metaTags.push(prop);
import { insertProp } from "../prop";

export default (config, state, ctx) => prop => {
const fullProp = insertProp(state, prop);
ctx.state[config.stateNamespace].metaTags.push(fullProp);
};
14 changes: 9 additions & 5 deletions src/add-script/add-script.spec.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import createAddScript from "./index";
import test from "tape";
import config from "./../config";
import { createCtxWithKoaHead } from "./../../test/test-helpers";
import { createCtxWithKoaHead, createState } from "./../../test/test-helpers";

test("addScript (as string)", async t => {
const ctx = await createCtxWithKoaHead();
const addScript = createAddScript(config, ctx);
const state = createState();
const addScript = createAddScript(config, state, ctx);
const jsText = "console.log('test log')";
const expectedScript = {
type: "text/javascript",
jsText
jsText,
_meta: { insertIndex: 0 }
};

addScript("console.log('test log')");
Expand All @@ -20,13 +22,15 @@ test("addScript (as string)", async t => {

test("addScript (as object)", async t => {
const ctx = await createCtxWithKoaHead();
const addScript = createAddScript(config, ctx);
const state = createState();
const addScript = createAddScript(config, state, ctx);
const jsText = "console.log('test log')";
const fixtureObj = "{ 'fixture': 'test fixture' }";
const expectedScript = {
fixtureObj,
jsText,
type: "text/javascript"
type: "text/javascript",
_meta: { insertIndex: 0 }
};

addScript({ fixtureObj, jsText });
Expand Down
8 changes: 6 additions & 2 deletions src/add-script/index.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
export default (config, ctx) => script => {
import { insertProp } from "../prop";

export default (config, state, ctx) => script => {
const scriptObj =
typeof script === "string" ? { jsText: script } : { ...script };

if (!scriptObj.type) {
scriptObj.type = "text/javascript";
}

ctx.state[config.stateNamespace].scripts.push(scriptObj);
const fullScriptObj = insertProp(state, scriptObj);

ctx.state[config.stateNamespace].scripts.push(fullScriptObj);
};
15 changes: 10 additions & 5 deletions src/add-style/add-style.spec.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import createAddStyle from "./index";
import test from "tape";
import config from "./../config";
import { createCtxWithKoaHead } from "./../../test/test-helpers";
import { createCtxWithKoaHead, createState } from "./../../test/test-helpers";

test("addStyle (as string)", async t => {
const ctx = await createCtxWithKoaHead();
const addStyle = createAddStyle(config, ctx);
const state = createState();
const addStyle = createAddStyle(config, state, ctx);
const cssText = "body { color: red; }";
const expectedStyle = {
type: "text/css",
cssText
cssText,
_meta: { insertIndex: 0 }
};

addStyle("body { color: red; }");
Expand All @@ -20,13 +22,16 @@ test("addStyle (as string)", async t => {

test("addStyle (as object)", async t => {
const ctx = await createCtxWithKoaHead();
const addStyle = createAddStyle(config, ctx);
const state = createState();
const addStyle = createAddStyle(config, state, ctx);
const cssText = "body { color: red; }";
const media = "all and (max-width: 500px)";
const expectedStyle = {
media,
cssText,
type: "text/css"
type: "text/css",

_meta: { insertIndex: 0 }
};

addStyle({ media, cssText });
Expand Down
8 changes: 6 additions & 2 deletions src/add-style/index.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
export default (config, ctx) => style => {
import { insertProp } from "../prop";

export default (config, state, ctx) => style => {
const styleObj =
typeof style === "string" ? { cssText: style } : { ...style };

if (!styleObj.type) {
styleObj.type = "text/css";
}

ctx.state[config.stateNamespace].styles.push(styleObj);
const fullStyleObj = insertProp(state, styleObj);

ctx.state[config.stateNamespace].styles.push(fullStyleObj);
};
Loading

0 comments on commit 6148527

Please sign in to comment.