Skip to content

Commit

Permalink
Merge pull request #43 from danmademe/warnings_and_structured_data
Browse files Browse the repository at this point in the history
Warnings and structured data
  • Loading branch information
danielcherubini committed Mar 3, 2017
2 parents 92203bc + 3370b40 commit 580c7ed
Show file tree
Hide file tree
Showing 15 changed files with 360 additions and 185 deletions.
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"presets": ["es2015"],
"plugins": [
"add-module-exports"
"add-module-exports",
"transform-flow-strip-types"
]
}
3 changes: 0 additions & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@ root = true
indent_style = space
indent_size = 4
charset = utf-8

[*.md]
trim_trailing_whitespace = false
5 changes: 5 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
"semi": [
"error",
"always"
],
"no-console": [
"error", {
"allow": ["warn", "error"]
}
]
}
}
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ language: node_js
node_js:
- v7
- v6
- v5
- v4
deploy:
skip_cleanup: true
provider: npm
Expand Down
85 changes: 54 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<p align="center"><img width="150"src="http://i.imgur.com/qs9EUdv.png"></p>

<p align="center">
<a href="https://npmjs.org/package/express-vue"><img src="https://badge.fury.io/js/express-vue.svg" alt="Version"></a>
<a href="https://travis-ci.org/danmademe/express-vue"><img src="https://travis-ci.org/danmademe/express-vue.svg?branch=master" alt="Build Status"></a>
<a href="https://david-dm.org/danmademe/express-vue"><img src="https://david-dm.org/danmademe/express-vue.svg?theme=shields.io" alt="Dependency Status"></a>
<a href="https://coveralls.io/r/danmademe/express-vue"><img src="https://coveralls.io/repos/danmademe/express-vue/badge.svg" alt="Coverage Status"></a>
<a href="https://lima.codeclimate.com/github/danmademe/express-vue"><img src="https://lima.codeclimate.com/github/danmademe/express-vue/badges/gpa.svg" /></a>
<a href="https://npmjs.org/package/express-vue"><img src="https://badge.fury.io/js/express-vue.svg" alt="Version"></a>
<a href="https://travis-ci.org/danmademe/express-vue"><img src="https://travis-ci.org/danmademe/express-vue.svg?branch=master" alt="Build Status"></a>
<a href="https://david-dm.org/danmademe/express-vue"><img src="https://david-dm.org/danmademe/express-vue.svg?theme=shields.io" alt="Dependency Status"></a>
<a href="https://coveralls.io/r/danmademe/express-vue"><img src="https://coveralls.io/repos/danmademe/express-vue/badge.svg" alt="Coverage Status"></a>
<a href="https://lima.codeclimate.com/github/danmademe/express-vue"><img src="https://lima.codeclimate.com/github/danmademe/express-vue/badges/gpa.svg" /></a>
</p>


Expand All @@ -25,6 +25,10 @@ The idea is simple use Node+Express for your Controller and Models, and Vue.js f
$ npm install --save express-vue
```

## Requirements

Requires Node V6 or greater

## Examples

A Super Simple example can be found at [danmademe/express-vue-super-simple](https://github.com/danmademe/express-vue-super-simple)
Expand Down Expand Up @@ -60,7 +64,7 @@ router.get('/', (req, res, next) => {
otherData: 'Something Else'
},
vue: {
meta: {
head: {
title: 'Page Title',
head: [
{ property:'og:title', content: 'Page Title'},
Expand Down Expand Up @@ -90,7 +94,7 @@ router.get('/', (req, res, next) => {
otherData: 'Something Else'
},
vue: {
meta: {
head: {
title: 'Page Title',
},
components: ['myheader', 'myfooter']
Expand All @@ -106,11 +110,11 @@ Then in your .vue file you can just use the element directive and it will work o

```vue
<template>
<div>
<myheader></myheader>
<h1>{{otherData}}</h1>
<myfooter></myfooter>
</div>
<div>
<myheader></myheader>
<h1>{{otherData}}</h1>
<myfooter></myfooter>
</div>
</template>
```

Expand Down Expand Up @@ -141,7 +145,7 @@ router.get('/', (req, res, next) => {
otherData: 'Something Else'
},
vue: {
meta: {
head: {
title: 'Page Title',
},
components: ['myheader', 'myfooter'],
Expand All @@ -164,10 +168,10 @@ work here. Just add a `meta` array into your `head` object, with support for bot
(Note we don't support shorthand here, and no support for google+ just yet, that will come soon).

```js
meta: {
head: {
title: 'It will be a pleasure',
// Meta tags
head: [
meta: [
{ name: 'application-name', content: 'Name of my application' },
{ name: 'description', content: 'A description of the page', id: 'desc' } // id to replace intead of create element
// ...
Expand All @@ -193,13 +197,32 @@ meta: {
}
```

## DevTools
## Structured Data

To use the amazing Vue.js DevTools please set the environment variable `VUE_DEV=true`
This also supports Google Structured data
https://developers.google.com/search/docs/guides/intro-structured-data

## Requirements

Requires Node V4 or greater
```js
head: {
title: 'It will be a pleasure',
structuredData: {
"@context": "http://schema.org",
"@type": "Organization",
"url": "http://www.your-company-site.com",
"contactPoint": [{
"@type": "ContactPoint",
"telephone": "+1-401-555-1212",
"contactType": "customer service"
}]
}
}
```


## DevTools

To use the amazing Vue.js DevTools please set the environment variable `VUE_DEV=true`

## Optional

Expand All @@ -213,18 +236,18 @@ Finally you'll need to set the link to your copy of vue.js in the script... (thi

```vue
<template>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script src="assets/scripts/vue.js" charset="utf-8"></script>
</head>
<body>
{{{app}}}
{{{script}}}
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script src="assets/scripts/vue.js" charset="utf-8"></script>
</head>
<body>
{{{app}}}
{{{script}}}
</body>
</html>
</template>
<script>
Expand Down
9 changes: 5 additions & 4 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ gulp.task('test', ['pre-test'], function (cb) {
});
});

gulp.task('watch', function () {
gulp.watch(['lib/**/*.js', 'test/**'], ['test']);
});

gulp.task('coveralls', ['test'], function () {
if (!process.env.CI) {
return;
Expand All @@ -82,3 +78,8 @@ gulp.task('clean', function () {

gulp.task('build', ['nsp', 'babel']);
gulp.task('default', ['static', 'test', 'coveralls']);


gulp.task('watch', function () {
gulp.watch(['lib/**/*.js'], ['build']);
});
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ function expressVue(componentPath, options, callback) {
renderHtmlUtil(components, defaults).then(function(html) {
callback(null, html);
}).catch(function(error) {
console.error(error);
callback(new Error(error));
});
}, function(error) {
console.error(error);
callback(new Error(error));
});
}
Expand Down
33 changes: 20 additions & 13 deletions lib/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ function layoutParser(layoutPath, defaults, type) {
fs.readFile(layoutPath, 'utf-8', function (err, content) {
if (err) {
content = defaults.backupLayout;
// let error = `Could not find the layout, I was expecting it to live here
// ${layoutPath}
// But I couldn't find it there ¯\_(ツ)_/¯
// So I'm using the default layout`;
// console.warn(error)
}

const body = htmlParser(content);
Expand All @@ -91,21 +96,23 @@ function componentParser(templatePath, defaults, type) {
return new Promise(function(resolve, reject) {
fs.readFile(templatePath, 'utf-8', function (err, content) {
if (err) {
reject(new Error(err));
}

const body = htmlParser(content, true);
content = content.replace(htmlRegex, '');
const script = scriptParser(content, defaults, type);
let error = `Could Not Find Component, I was expecting it to live here \n${templatePath} \nBut I couldn't find it there, ¯\\_(ツ)_/¯\n\n`;
console.error(error);
reject(error);
} else {
const body = htmlParser(content, true);
content = content.replace(htmlRegex, '');
const script = scriptParser(content, defaults, type);

let componentScript = script;
componentScript.template = body;
let componentScript = script;
componentScript.template = body;

resolve({
type: type,
name: templatePath.match(/\w*\.vue/g)[0].replace('\.vue', ''),
script: componentScript
});
resolve({
type: type,
name: templatePath.match(/\w*\.vue/g)[0].replace('\.vue', ''),
script: componentScript
});
}
});
});
}
Expand Down
102 changes: 102 additions & 0 deletions lib/utils/head.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// @flow
const metaWarning = 'Deprecation Warning: Please update your meta object. Check github project for more information. \nhttps://github.com/danmademe/express-vue';
//Checks Vue Object to check if a meta object is inside head
//Returns Boolean
function checkMetaInsideHead(vueObject: Object): boolean {
let isMetaInsideHead: boolean = false;
if (vueObject.meta && vueObject.meta.head) {
isMetaInsideHead = false;
} else if(vueObject.head && vueObject.head.meta) {
isMetaInsideHead = true;
}
return isMetaInsideHead;
}

//Support for legacy v3.7.2 and lower
// vue: {
// meta: {
// title: 'Page Title',
// head: [
// { property:'og:title', content: 'Page Title'},
// { name:'twitter:title', content: 'Page Title'},
// ]
// }
// }
function legacyMetaTags(metaTags: string, vueObject: Object): string {
console.warn(metaWarning);
if (vueObject.meta && vueObject.meta.head) {
for (let metaItem of vueObject.meta.head) {
if (metaItem.name) {
metaTags += `<meta name=\"${metaItem.name}\" content=\"${metaItem.content}\" />`;
} else if (metaItem.property) {
metaTags += `<meta property=\"${metaItem.property}\" content=\"${metaItem.content}\" />`;
} else if (metaItem.script) {
const charset = metaItem.charset || 'utf-8';
metaTags += `<script src=\"${metaItem.script}\" charset=\"${charset}\"></script>`;
} else if (metaItem.style) {
const type = metaItem.type || 'text/css';
const rel = metaItem.rel || 'stylesheet';
metaTags += `<link rel=\"${rel}\" type=\"${type}\" href=\"${metaItem.style}\">`;
}
}
}
return metaTags;
}

//For v3.7.3 and greater
// vue: {
// head: {
// title: 'Page Title',
// meta: [
// { property:'og:title', content: 'Page Title'},
// { name:'twitter:title', content: 'Page Title'},
// ]
// }
// }
function createMetaTags(metaTags: string, vueObject: Object): string {
if (vueObject.head && vueObject.head.meta) {
for (let metaItem of vueObject.head.meta) {
if (metaItem.name) {
metaTags += `<meta name=\"${metaItem.name}\" content=\"${metaItem.content}\" />`;
} else if (metaItem.property) {
metaTags += `<meta property=\"${metaItem.property}\" content=\"${metaItem.content}\" />`;
} else if (metaItem.script) {
const charset = metaItem.charset || 'utf-8';
metaTags += `<script src=\"${metaItem.script}\" charset=\"${charset}\"></script>`;
} else if (metaItem.style) {
const type = metaItem.type || 'text/css';
const rel = metaItem.rel || 'stylesheet';
metaTags += `<link rel=\"${rel}\" type=\"${type}\" href=\"${metaItem.style}\">`;
}
}
}
return metaTags;
}

function headUtil(vueObject: Object) {
let metaTags = '';
let title = '';
let structuredData = '';
const hasNewHeadBlock = checkMetaInsideHead(vueObject);

if (vueObject.head && hasNewHeadBlock) {
metaTags = createMetaTags(metaTags, vueObject);
} else if (vueObject.meta && !hasNewHeadBlock) {
metaTags = legacyMetaTags(metaTags, vueObject);
}

if (vueObject.meta && vueObject.meta.title) {
console.warn(metaWarning);
title = `<title>${vueObject.meta.title}</title>`;
} else if (vueObject.head && vueObject.head.title) {
title = `<title>${vueObject.head.title}</title>`;
}

if (vueObject.head && vueObject.head.structuredData) {
structuredData = `<script type="application/ld+json">${JSON.stringify(vueObject.head.structuredData)}</script>`;
}

return title + metaTags + structuredData + '</head>';
}

export default headUtil;
4 changes: 2 additions & 2 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
renderVueMixins
} from './render';
import {scriptToString} from './string';
import metaUtil from './meta';
import headUtil from './head';

export {
renderUtil,
Expand All @@ -15,5 +15,5 @@ export {
renderVueComponents,
renderVueMixins,
scriptToString,
metaUtil
headUtil
};
Loading

0 comments on commit 580c7ed

Please sign in to comment.