Repository: vinaygopinath/ng2-meta Branch: master Commit: 736326579151 Files: 14 Total size: 19.5 KB Directory structure: gitextract_uuysa5xh/ ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.MD ├── package.json ├── src/ │ ├── index.ts │ ├── meta.guard.ts │ ├── meta.module.ts │ ├── meta.service.ts │ └── models/ │ ├── meta-config.ts │ └── meta-constants.ts ├── tsconfig.json └── tslint.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* # Runtime data pids *.pid *.seed # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage # nyc test coverage .nyc_output # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules jspm_packages # Optional npm cache directory .npm # Optional REPL history .node_repl_history # Generated # !karma.conf.js !karma-test-shim.js *.js *.map *.d.ts typings dist dist.tgz ================================================ FILE: .npmignore ================================================ # Node node_modules npm-debug.log ================================================ FILE: CHANGELOG.md ================================================ #Changelog ## [v5.0.0](https://github.com/vinaygopinath/ng2-meta/releases/tag/v5.0.0) **Breaking change**: ng2-meta depends on Angular 6+ and rxjs 6+. Ensure that your site works with Angular 6 before you upgrade to this version. ## [v4.0.0](https://github.com/vinaygopinath/ng2-meta/releases/tag/v4.0.0) **Breaking change**: All routes must contain `canActivate: [MetaGuard]` in their route configuration to notify `ng2-meta` when the route is about to change. * More consistent meta tag updates: Meta tags are now set *before* the route is activated. Fixes [#7](https://github.com/vinaygopinath/ng2-meta/issues/7) ## [v3.0.1](https://github.com/vinaygopinath/ng2-meta/releases/tag/v3.0.1) * [WIP] [Server-side rendering] Remove dependency on window.document * Set `property` attribute for opengraph tags (and `name` attribute for all others) ## [v3.0.0](https://github.com/vinaygopinath/ng2-meta/releases/tag/v3.0.0) * Angular 5.x compatibility + AOT support ## [v2.0.3](https://github.com/vinaygopinath/ng2-meta/releases/tag/v2.0.3) * postInstall script fix ([@bergben](https://github.com/bergben)) + support for child routes ([@Chocobozzz](https://github.com/Chocobozzz)) ## [v2.0.2](https://github.com/vinaygopinath/ng2-meta/releases/tag/v2.0.2) ##### Bugfixes * [#13](https://github.com/vinaygopinath/ng2-meta/issues/13) Attempt 2 at fixing the "duplicate identifier" error while installing ng2-meta. Thanks [@Chocobozzz](https://github.com/Chocobozzz) ## [v2.0.1](https://github.com/vinaygopinath/ng2-meta/releases/tag/v2.0.1) ##### Bugfixes * [#13](https://github.com/vinaygopinath/ng2-meta/issues/13) Fix "duplicate identifier" error while installing ng2-meta. Thanks [@Bioto](https://github.com/Bioto) ## [v2.0.0](https://github.com/vinaygopinath/ng2-meta/releases/tag/v2.0.0) * [#11](https://github.com/vinaygopinath/ng2-meta/issues/11) Support for angular 2.0.0 and router 3.0.0. Thanks to [@bergben](https://github.com/bergben) once again, and the folks in the thread for their input. Note: This version has **breaking changes** (needed to support angular final). If, for some reason, you would like to continue using RC4, please use v1.0.0. ## [v1.0.0](https://github.com/vinaygopinath/ng2-meta/releases/tag/v1.0.0) ##### Bugfixes * [#1](https://github.com/vinaygopinath/ng2-meta/issues/1) Fixed "No provider for meta.config" issue resulting from a missing @Optional annotation. Thanks to [@bergben](https://github.com/bergben) ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Vinay Gopinath Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.MD ================================================ # ng2-meta [](https://gitter.im/ng2-meta/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) Update HTML meta tags for title, description and others automatically based on the route in your Angular app. ng2-meta v5.0.0+ requires **Angular 6**. On **Angular 5** or lower, use ng2-meta v4.0.0 (`npm install ng2-meta@4.0.0`) For the AngularJS (1.x) module, check out [ngMeta](https://github.com/vinaygopinath/ngMeta) ## Getting started ### Install To install this library, run: ```bash $ npm install ng2-meta --save ``` ### Modify routes Add meta tags and `MetaGuard` to routes. By default, `title` and `description` values are duplicated for `og:title` and `og:description`, so there's no need to add them separately.
import { MetaGuard } from 'ng2-meta';
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
canActivate: [MetaGuard],
data: {
meta: {
title: 'Home page',
description: 'Description of the home page'
}
}
},
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [MetaGuard],
data: {
meta: {
title: 'Dashboard',
description: 'Description of the dashboard page',
'og:image': 'http://example.com/dashboard-image.png'
}
}
}
];
### Import MetaModule
...
import { MetaModule } from 'ng2-meta';
@NgModule({
declarations: [
AppComponent,
...
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
RouterModule.forRoot(routes),
MetaModule.forRoot()
],
bootstrap: [AppComponent]
})
### Update AppComponent
import { MetaService } from 'ng2-meta';
@Component({
...
})
export class AppComponent {
constructor(private metaService: MetaService) {}
}
You're all set! ng2-meta will update the meta tags whenever the route changes.
## Options
### Set defaults
Set default values for tags. These values are used when routes without `meta: {}` information are encountered.
```typescript
import { MetaConfig, MetaService } from 'ng2-meta';
const metaConfig: MetaConfig = {
//Append a title suffix such as a site name to all titles
//Defaults to false
useTitleSuffix: true,
defaults: {
title: 'Default title for pages without meta in their route',
titleSuffix: ' | Site Name',
'og:image': 'http://example.com/default-image.png',
'any other': 'arbitrary tag can be used'
}
};
@NgModule({
declarations: [
AppComponent,
...
],
imports: [
...,
MetaModule.forRoot(metaConfig)
],
bootstrap: [AppComponent]
})
```
### Change meta tags programmatically
```typescript
import { Component, OnInit } from '@angular/core';
class ProductComponent implements OnInit {
...
constructor(private metaService: MetaService) {}
ngOnInit() {
this.product = //HTTP GET for product in catalogue
this.metaService.setTitle('Product page for '+this.product.name);
this.metaService.setTag('og:image',this.product.imageURL);
}
}
```
### Define fallback meta content in HTML
While Google executes Javascript and extracts meta tags set by ng2-meta, many bots (like Facebook and Twitter) do not execute Javascript. Consider defining fallback meta tags in your HTML for such bots. The fallback content is overridden by ng2-meta in Javascript-enabled environments.
```html
```
## Contribute
If you wish to contribute to this repo, please check out the [open issues](https://github.com/vinaygopinath/ng2-meta/issues).
If you notice a bug that has not already been reported or would like to make a feature request, please create a [new issue](https://github.com/vinaygopinath/ng2-meta/issues/new). This helps to start a discussion with the community and avoid duplication of effort before you make any changes.
## Licence
MIT © [Vinay Gopinath](http://vinaygopinath.me)
================================================
FILE: package.json
================================================
{
"name": "ng2-meta",
"description": "Dynamic meta tags and SEO in Angular2",
"version": "5.0.0",
"scripts": {
"lint": "tslint src/**/*.ts -p tsconfig.json",
"build": "ng-packagr -p package.json"
},
"ngPackage": {
"lib": {
"entryFile": "src/index.ts"
}
},
"repository": {
"type": "git",
"url": "https://github.com/vinaygopinath/ng2-meta"
},
"author": {
"name": "Vinay Gopinath",
"email": "vinay@vinaygopinath.me",
"url": "https://www.vinaygopinath.me"
},
"keywords": [
"angular",
"angular2",
"seo",
"meta tags",
"open graph"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/vinaygopinath/ng2-meta/issues"
},
"peerDependencies": {
"@angular/common": "^6.0.0",
"@angular/compiler": "^6.0.0",
"@angular/compiler-cli": "^6.0.0",
"@angular/core": "^6.0.0",
"@angular/platform-browser": "^6.0.0",
"@angular/router": "^6.0.0",
"core-js": "^2.5.7",
"zone.js": "^0.8.26",
"rxjs": "^6.0"
},
"devDependencies": {
"@angular/compiler": "^6.0.0",
"@angular/compiler-cli": "^6.0.0",
"@types/node": "^6.0.46",
"codelyzer": "^4.4.2",
"ng-packagr": "^3.0.3",
"tsickle": "^0.32",
"tslint": "^5.10.0",
"typescript": ">=2.7.2"
},
"engines": {
"node": ">= 6.9.0",
"npm": ">= 3.0.0"
}
}
================================================
FILE: src/index.ts
================================================
export { MetaConfig } from './models/meta-config';
export { MetaService } from './meta.service';
export { MetaModule } from './meta.module';
export { MetaGuard } from './meta.guard';
================================================
FILE: src/meta.guard.ts
================================================
import { Inject, Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot, Router } from '@angular/router';
import { MetaService } from './meta.service';
import { MetaConfig } from './models/meta-config';
import { META_CONFIG_TOKEN, META_GUARD_IDENTIFIER } from './models/meta-constants';
@Injectable()
export class MetaGuard implements CanActivate {
public static IDENTIFIER = META_GUARD_IDENTIFIER;
public constructor(
private router: Router,
private metaService: MetaService,
@Inject(META_CONFIG_TOKEN) private metaConfig: MetaConfig
) {
}
public canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
this._processRouteMetaTags(route.data && route.data.meta);
return true;
}
private _processRouteMetaTags(meta: any = {}) {
if (meta.disableUpdate) {
return;
}
this.metaService.setTitle(meta.title, meta.titleSuffix);
Object.keys(meta).forEach(key => {
if (key === 'title' || key === 'titleSuffix') {
return;
}
this.metaService.setTag(key, meta[key]);
});
Object.keys(this.metaConfig.defaults).forEach(key => {
if (key in meta || key === 'title' || key === 'titleSuffix') {
return;
}
this.metaService.setTag(key, this.metaConfig.defaults[key]);
});
}
}
================================================
FILE: src/meta.module.ts
================================================
import { NgModule, ModuleWithProviders } from '@angular/core';
import { Optional, SkipSelf } from '@angular/core';
import { RouterModule } from '@angular/router';
import { MetaService } from './meta.service';
import { DEFAULT_META_CONFIG, MetaConfig } from './models/meta-config';
import { META_CONFIG_TOKEN } from './models/meta-constants';
import { MetaGuard } from './meta.guard';
@NgModule({
imports: [
RouterModule
]
})
export class MetaModule {
public static forRoot(metaConfig: MetaConfig = DEFAULT_META_CONFIG): ModuleWithProviders {
return {
ngModule: MetaModule,
providers: [
{ provide: META_CONFIG_TOKEN, useValue: metaConfig },
MetaGuard,
MetaService
]
};
}
public constructor(@Optional() @SkipSelf() parentModule: MetaModule) {
if (parentModule) {
throw new Error(
'MetaModule is already loaded. Import it in the AppModule only');
}
}
}
================================================
FILE: src/meta.service.ts
================================================
import { Inject, Injectable } from '@angular/core';
import { Title, Meta } from '@angular/platform-browser';
import { Router, ActivatedRoute, Route } from '@angular/router';
import { MetaConfig } from './models/meta-config';
import { META_CONFIG_TOKEN, META_GUARD_IDENTIFIER } from './models/meta-constants';
const isDefined = (val: any) => typeof val !== 'undefined';
@Injectable()
export class MetaService {
public constructor(
private router: Router,
private meta: Meta,
private titleService: Title,
private activatedRoute: ActivatedRoute,
@Inject(META_CONFIG_TOKEN) private metaConfig: MetaConfig
) {
this._warnMissingGuard();
}
public setTitle(title?: string, titleSuffix?: string): MetaService {
let titleContent = isDefined(title) ? title : (this.metaConfig.defaults['title'] || '');
if (this.metaConfig.useTitleSuffix) {
titleContent += isDefined(titleSuffix) ? titleSuffix : (this.metaConfig.defaults['titleSuffix'] || '');
}
this._updateMetaTag('title', titleContent);
this._updateMetaTag('og:title', titleContent);
this.titleService.setTitle(titleContent);
return this;
}
public setTag(tag: string, value: string): MetaService {
if (tag === 'title' || tag === 'titleSuffix') {
throw new Error(`Attempt to set ${tag} through 'setTag': 'title' and 'titleSuffix' are reserved tag names.
Please use 'MetaService.setTitle' instead`);
}
let content = isDefined(value) ? value : (this.metaConfig.defaults[tag] || '');
this._updateMetaTag(tag, content);
if (tag === 'description') {
this._updateMetaTag('og:description', content);
}
return this;
}
private _updateMetaTag(tag: string, value: string) {
let prop = 'name';
if (tag.startsWith(`og:`)) {
prop = 'property';
}
this.meta.updateTag({
[prop]: tag,
content: value
});
}
private _warnMissingGuard() {
if (isDefined(this.metaConfig.warnMissingGuard) && !this.metaConfig.warnMissingGuard) {
return;
}
const hasDefaultMeta = !!Object.keys(this.metaConfig.defaults).length;
const hasMetaGuardInArr = (it: any) => (it && it.IDENTIFIER === META_GUARD_IDENTIFIER);
let hasShownWarnings = false;
this.router.config.forEach((route: Route) => {
const hasRouteMeta = route.data && route.data.meta;
const showWarning = !isDefined(route.redirectTo)
&& (hasDefaultMeta || hasRouteMeta)
&& !(route.canActivate || []).some(hasMetaGuardInArr);
if (showWarning) {
console.warn(`Route with path "${route.path}" has ${hasRouteMeta ? '' : 'default '}meta tags, but does not use MetaGuard. \
Please add MetaGuard to the canActivate array in your route configuration`);
hasShownWarnings = true;
}
});
if (hasShownWarnings) {
console.warn(`To disable these warnings, set metaConfig.warnMissingGuard: false \
in your ng2-meta MetaConfig passed to MetaModule.forRoot()`);
}
}
}
================================================
FILE: src/models/meta-config.ts
================================================
export const DEFAULT_META_CONFIG: MetaConfig = {
useTitleSuffix: false,
warnMissingGuard: true,
defaults: {}
};
/**
* Additional site-wide configuration of meta tags.
*
* Use this to enable adding a title suffix to the title of each route,
* or to set default meta tags to be used when no equivalent meta tag
* exists in the meta configuration of the route.
*
*
* Default
* ```
* {
* useTitleSuffix: false,
* defaults: {}
* }
* ```
*/
export interface MetaConfig {
/**
* Flag to append an optional title suffix to the title.
* Default value: false
*/
useTitleSuffix?: boolean;
/**
* Flag to show a warning for each route that is missing MetaGuard in its `canActivate` array when
* * the route contains `data: { meta: {} }`
*
* OR
*
* * the site-wide MetaConfig contains default meta tags
*
* Default value: true
*/
warnMissingGuard?: boolean;
/**
* A dictionary of default meta tags and their values
*/
defaults?: {
/**
* The default title, used when a route does not have its own titleSuffix.
*/
title?: string;
/**
* The default titleSuffix, used when useTitleSuffix is set to true
* and a route does not have its own titleSuffix.
*/
titleSuffix?: string;
} & { [key: string]: string | undefined; };
}
================================================
FILE: src/models/meta-constants.ts
================================================
import { InjectionToken } from '@angular/core';
import { MetaConfig } from './meta-config';
export const META_CONFIG_TOKEN = new InjectionToken