Compare commits
52 Commits
Author | SHA1 | Date | |
---|---|---|---|
c0d223959d | |||
c40c01b5c8 | |||
57868de491 | |||
ccd68a1257 | |||
c1f82be85f | |||
ca3398c4fd | |||
0884b61099 | |||
db8ea28cee | |||
cb898eeef5 | |||
7a0d767e9d | |||
49ca240237 | |||
c802e8846a | |||
1f7be6b8a0 | |||
a0cbe170c8 | |||
5df46f8b77 | |||
c12e9eaf76 | |||
2aa1839c22 | |||
8e4bdb867c | |||
359e18f5dc | |||
751a325c81 | |||
93d4bc491f | |||
bdf55a19d9 | |||
cd1f68f55e | |||
f2bd7145b3 | |||
6d9789df45 | |||
0be8a6f60d | |||
a3793572e7 | |||
6ace59d1d1 | |||
b6ddf6a87b | |||
b999627ba5 | |||
5e8a91f302 | |||
2fc0613fa6 | |||
2283cdb633 | |||
c0db06fc18 | |||
4557000629 | |||
78997e1e5a | |||
4d5564e8d4 | |||
11d89adc4b | |||
a99fd6374c | |||
ba287cdb76 | |||
5318408037 | |||
16ef41ae20 | |||
7375675d7d | |||
68f9221d33 | |||
269e658967 | |||
9008aca718 | |||
74d73a0d21 | |||
5496c8c482 | |||
c748c5102c | |||
308133fe4f | |||
cb80b4df75 | |||
74ed988da0 |
14
.gitignore
vendored
14
.gitignore
vendored
@ -1,8 +1,20 @@
|
||||
.nogit/
|
||||
node_modules/
|
||||
|
||||
# artifacts
|
||||
coverage/
|
||||
public/
|
||||
pages/
|
||||
|
||||
# installs
|
||||
node_modules/
|
||||
|
||||
# caches
|
||||
.yarn/
|
||||
.cache/
|
||||
.rpt2_cache
|
||||
|
||||
# builds
|
||||
dist/
|
||||
dist_*/
|
||||
|
||||
# custom
|
128
.gitlab-ci.yml
128
.gitlab-ci.yml
@ -1,16 +1,16 @@
|
||||
# gitzone standard
|
||||
image: hosttoday/ht-docker-node:npmci
|
||||
# gitzone ci_default
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- .npmci_cache/
|
||||
key: "$CI_BUILD_STAGE"
|
||||
- .npmci_cache/
|
||||
key: '$CI_BUILD_STAGE'
|
||||
|
||||
stages:
|
||||
- security
|
||||
- test
|
||||
- release
|
||||
- metadata
|
||||
- security
|
||||
- test
|
||||
- release
|
||||
- metadata
|
||||
|
||||
# ====================
|
||||
# security stage
|
||||
@ -18,102 +18,114 @@ stages:
|
||||
mirror:
|
||||
stage: security
|
||||
script:
|
||||
- npmci git mirror
|
||||
- npmci git mirror
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
snyk:
|
||||
auditProductionDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci command npm install -g snyk
|
||||
- npmci command npm install --ignore-scripts
|
||||
- npmci command snyk test
|
||||
- npmci command npm install --production --ignore-scripts
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command npm audit --audit-level=high --only=prod --production
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- docker
|
||||
|
||||
auditDevDependencies:
|
||||
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||
stage: security
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci command npm install --ignore-scripts
|
||||
- npmci command npm config set registry https://registry.npmjs.org
|
||||
- npmci command npm audit --audit-level=high --only=dev
|
||||
tags:
|
||||
- docker
|
||||
allow_failure: true
|
||||
|
||||
# ====================
|
||||
# test stage
|
||||
# ====================
|
||||
|
||||
testLTS:
|
||||
testStable:
|
||||
stage: test
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci node install lts
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
testSTABLE:
|
||||
- docker
|
||||
|
||||
testBuild:
|
||||
stage: test
|
||||
script:
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci npm test
|
||||
- npmci npm prepare
|
||||
- npmci node install stable
|
||||
- npmci npm install
|
||||
- npmci command npm run build
|
||||
coverage: /\d+.?\d+?\%\s*coverage/
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- docker
|
||||
|
||||
release:
|
||||
stage: release
|
||||
script:
|
||||
- npmci node install stable
|
||||
- npmci npm publish
|
||||
- npmci node install stable
|
||||
- npmci npm publish
|
||||
only:
|
||||
- tags
|
||||
- tags
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
# ====================
|
||||
# metadata stage
|
||||
# ====================
|
||||
codequality:
|
||||
stage: metadata
|
||||
image: docker:stable
|
||||
allow_failure: true
|
||||
services:
|
||||
- docker:stable-dind
|
||||
only:
|
||||
- tags
|
||||
script:
|
||||
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
|
||||
- docker run
|
||||
--env SOURCE_CODE="$PWD"
|
||||
--volume "$PWD":/code
|
||||
--volume /var/run/docker.sock:/var/run/docker.sock
|
||||
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
|
||||
artifacts:
|
||||
paths: [codeclimate.json]
|
||||
- npmci command npm install -g tslint typescript
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command "tslint -c tslint.json ./ts/**/*.ts"
|
||||
tags:
|
||||
- docker
|
||||
- priv
|
||||
- lossless
|
||||
- docker
|
||||
- priv
|
||||
|
||||
trigger:
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci trigger
|
||||
- npmci trigger
|
||||
only:
|
||||
- tags
|
||||
- tags
|
||||
tags:
|
||||
- docker
|
||||
- notpriv
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
|
||||
pages:
|
||||
image: hosttoday/ht-docker-node:npmci
|
||||
stage: metadata
|
||||
script:
|
||||
- npmci command npm install -g typedoc typescript
|
||||
- npmci node install lts
|
||||
- npmci command npm install -g @gitzone/tsdoc
|
||||
- npmci npm prepare
|
||||
- npmci npm install
|
||||
- npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/
|
||||
- npmci command tsdoc
|
||||
tags:
|
||||
- lossless
|
||||
- docker
|
||||
- notpriv
|
||||
only:
|
||||
@ -121,5 +133,5 @@ pages:
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- public
|
||||
- public
|
||||
allow_failure: true
|
||||
|
29
.vscode/launch.json
vendored
Normal file
29
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "current file",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"${relativeFile}"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
},
|
||||
{
|
||||
"name": "test.ts",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"args": [
|
||||
"test/test.ts"
|
||||
],
|
||||
"runtimeArgs": ["-r", "@gitzone/tsrun"],
|
||||
"cwd": "${workspaceRoot}",
|
||||
"protocol": "inspector",
|
||||
"internalConsoleOptions": "openOnSessionStart"
|
||||
}
|
||||
]
|
||||
}
|
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": ["/npmextra.json"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"npmci": {
|
||||
"type": "object",
|
||||
"description": "settings for npmci"
|
||||
},
|
||||
"gitzone": {
|
||||
"type": "object",
|
||||
"description": "settings for gitzone",
|
||||
"properties": {
|
||||
"projectType": {
|
||||
"type": "string",
|
||||
"enum": ["website", "element", "service", "npm", "wcc"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
"npmAccessLevel": "public"
|
||||
},
|
||||
"gitzone": {
|
||||
"projectType": "npm",
|
||||
"module": {
|
||||
"githost": "gitlab.com",
|
||||
"gitscope": "pushrocks",
|
||||
|
11035
package-lock.json
generated
11035
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
38
package.json
38
package.json
@ -1,27 +1,45 @@
|
||||
{
|
||||
"name": "@pushrocks/websetup",
|
||||
"version": "1.0.6",
|
||||
"version": "3.0.5",
|
||||
"private": false,
|
||||
"description": "setup basic page properties",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"main": "dist_ts/index.js",
|
||||
"typings": "dist_ts/index.d.ts",
|
||||
"author": "Lossless GmbH",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "(tstest test/)",
|
||||
"build": "(tsbuild)",
|
||||
"format": "(gitzone format)"
|
||||
"build": "(tsbuild --web && tsbundle npm)"
|
||||
},
|
||||
"keywords": [
|
||||
"lossless",
|
||||
"websafe"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@gitzone/tsbuild": "^2.0.22",
|
||||
"@gitzone/tstest": "^1.0.15",
|
||||
"@pushrocks/tapbundle": "^3.0.7",
|
||||
"tslint": "^5.11.0",
|
||||
"@gitzone/tsbuild": "^2.1.25",
|
||||
"@gitzone/tsbundle": "^1.0.78",
|
||||
"@gitzone/tstest": "^1.0.52",
|
||||
"@pushrocks/tapbundle": "^3.2.9",
|
||||
"tslint": "^6.1.3",
|
||||
"tslint-config-prettier": "^1.15.0"
|
||||
},
|
||||
"dependencies": {}
|
||||
"dependencies": {
|
||||
"@pushrocks/smartpromise": "^3.1.3",
|
||||
"@tsclass/tsclass": "^3.0.29"
|
||||
},
|
||||
"files": [
|
||||
"ts/**/*",
|
||||
"ts_web/**/*",
|
||||
"dist/**/*",
|
||||
"dist_*/**/*",
|
||||
"dist_ts/**/*",
|
||||
"dist_ts_web/**/*",
|
||||
"assets/**/*",
|
||||
"cli.js",
|
||||
"npmextra.json",
|
||||
"readme.md"
|
||||
],
|
||||
"browserslist": [
|
||||
"last 1 chrome versions"
|
||||
]
|
||||
}
|
||||
|
31
readme.md
31
readme.md
@ -8,19 +8,32 @@ setup basic page properties
|
||||
* [docs (typedoc)](https://pushrocks.gitlab.io/websetup/)
|
||||
|
||||
## Status for master
|
||||
[](https://gitlab.com/pushrocks/websetup/commits/master)
|
||||
[](https://gitlab.com/pushrocks/websetup/commits/master)
|
||||
[](https://www.npmjs.com/package/@pushrocks/websetup)
|
||||
[](https://snyk.io/test/npm/@pushrocks/websetup)
|
||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
[](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
[](https://prettier.io/)
|
||||
|
||||
Status Category | Status Badge
|
||||
-- | --
|
||||
GitLab Pipelines | [](https://lossless.cloud)
|
||||
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
||||
npm | [](https://lossless.cloud)
|
||||
Snyk | [](https://lossless.cloud)
|
||||
TypeScript Support | [](https://lossless.cloud)
|
||||
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||
Code Style | [](https://lossless.cloud)
|
||||
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
||||
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
||||
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
||||
Platform support | [](https://lossless.cloud) [](https://lossless.cloud)
|
||||
|
||||
## Usage
|
||||
|
||||
Use TypeScript for best in class intellisense.
|
||||
|
||||
## Contribution
|
||||
|
||||
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
|
||||
|
||||
For further information read the linked docs at the top of this readme.
|
||||
|
||||
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)
|
||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
|
||||
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
||||
|
||||
[](https://maintainedby.lossless.com)
|
||||
[](https://maintainedby.lossless.com)
|
||||
|
16
test/test.browser.ts
Normal file
16
test/test.browser.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { expect, tap } from '@pushrocks/tapbundle';
|
||||
import * as websetup from '../ts/index';
|
||||
|
||||
tap.test('first test', async () => {
|
||||
const websetupInstance = new websetup.WebSetup({
|
||||
metaObject: {
|
||||
description: 'A awesome description',
|
||||
title: 'mytitle',
|
||||
canonicalDomain: 'lossless.com',
|
||||
},
|
||||
});
|
||||
await websetupInstance.readyPromise;
|
||||
expect(document.title).to.equal('mytitle');
|
||||
});
|
||||
|
||||
tap.start();
|
@ -1,8 +0,0 @@
|
||||
import { expect, tap } from '@pushrocks/tapbundle';
|
||||
import * as websetup from '../ts/index';
|
||||
|
||||
tap.test('first test', async () => {
|
||||
console.log('Waiting for proper puppeteer support here');
|
||||
});
|
||||
|
||||
tap.start();
|
41
ts/index.ts
41
ts/index.ts
@ -1,37 +1,4 @@
|
||||
import * as plugins from './websetup.plugins';
|
||||
|
||||
import { setupGoogleAnalytics } from './tools/ganalytics';
|
||||
import { setupFullStory } from './tools/fullstory';
|
||||
import { setupServiceWoker } from './serviceworker';
|
||||
import { IMetaObject, setupMetaInformation } from './meta';
|
||||
|
||||
export interface IWebSetupConstructorOptions {
|
||||
googleAnalyticsCode?: string;
|
||||
fsCode?: string;
|
||||
metaObject: IMetaObject;
|
||||
serviceworker?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* the main WebSetup class
|
||||
*/
|
||||
export class WebSetup {
|
||||
constructor(optionsArg: IWebSetupConstructorOptions) {
|
||||
// most important, lets get the meta information in place
|
||||
this.setup(optionsArg);
|
||||
}
|
||||
|
||||
async setup(optionsArg: IWebSetupConstructorOptions) {
|
||||
if (optionsArg.serviceworker) {
|
||||
await setupServiceWoker();
|
||||
}
|
||||
|
||||
if (optionsArg.googleAnalyticsCode) {
|
||||
await setupGoogleAnalytics(optionsArg.googleAnalyticsCode);
|
||||
}
|
||||
|
||||
if (optionsArg.fsCode) {
|
||||
await setupFullStory(optionsArg.fsCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
export * from './websetup.classes.websetup';
|
||||
export * from './websetup.classes.tag.metatag';
|
||||
export * from './websetup.classes.tag.opengraphtag';
|
||||
export * from './websetup.classes.tag.jsonldtag';
|
||||
|
9
ts/interfaces/index.ts
Normal file
9
ts/interfaces/index.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import * as plugins from '../websetup.plugins';
|
||||
|
||||
export interface IMetaObject {
|
||||
title: string;
|
||||
description: string;
|
||||
canonicalDomain?: string;
|
||||
ldCompany?: plugins.tsclass.business.ICompany;
|
||||
ldProduct?: any;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
export interface IMetaObject {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export const setupMetaInformation = async (metaObjectArg: IMetaObject) => {
|
||||
document.title = metaObjectArg.title;
|
||||
addMetaTag('description', metaObjectArg.description);
|
||||
addMetaTag('google', 'notranslate');
|
||||
addMetaTag('revisited-after', '1 days');
|
||||
};
|
||||
|
||||
const addMetaTag = async (linkNameArg: string, contentArg: string) => {
|
||||
const metaElement = document.createElement('meta');
|
||||
metaElement.name = linkNameArg;
|
||||
metaElement.content = contentArg;
|
||||
document.getElementsByTagName('head')[0].appendChild(metaElement);
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
export const setupServiceWoker = async () => {
|
||||
// serviceworker
|
||||
const script = document.createElement('script');
|
||||
script.onload = () => {
|
||||
console.log(
|
||||
'Loaded Serviceworker. The serviceworker helps us with notifications and offline capabilities, so you can also read this site when your device is offline.'
|
||||
);
|
||||
};
|
||||
script.src = 'serviceworker/mainthread.js';
|
||||
document.head.appendChild(script);
|
||||
};
|
@ -1,66 +0,0 @@
|
||||
declare global {
|
||||
// tslint:disable-next-line: interface-name
|
||||
interface Window {
|
||||
_fs_host: any;
|
||||
}
|
||||
}
|
||||
export const setupFullStory = async (fsCodeArg: string) => {
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
window['_fs_debug'] = false;
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
window['_fs_host'] = 'fullstory.com';
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
window['_fs_org'] = fsCodeArg;
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
window['_fs_namespace'] = 'FS';
|
||||
(function(m, n, e, t, l, o, g, y) {
|
||||
if (e in m) {
|
||||
if (m.console && m.console.log) {
|
||||
m.console.log('FullStory namespace conflict. Please set window["_fs_namespace"].');
|
||||
}
|
||||
return;
|
||||
}
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
g = m[e] = function(a, b, s) {
|
||||
g.q ? g.q.push([a, b, s]) : g._api(a, b, s);
|
||||
};
|
||||
g.q = [];
|
||||
o = n.createElement(t);
|
||||
o.async = 1;
|
||||
o.src = 'https://' + window._fs_host + '/s/fs.js';
|
||||
y = n.getElementsByTagName(t)[0];
|
||||
y.parentNode.insertBefore(o, y);
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
g.identify = function(i, v, s) {
|
||||
g(l, { uid: i }, s);
|
||||
if (v) g(l, v, s);
|
||||
};
|
||||
g.setUserVars = function(v, s) {
|
||||
g(l, v, s);
|
||||
};
|
||||
g.event = function(i, v, s) {
|
||||
g('event', { n: i, p: v }, s);
|
||||
};
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
g.shutdown = function() {
|
||||
g('rec', !1);
|
||||
};
|
||||
g.restart = function() {
|
||||
g('rec', !0);
|
||||
};
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
g.consent = function(a) {
|
||||
g('consent', !arguments.length || a);
|
||||
};
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
g.identifyAccount = function(i, v) {
|
||||
o = 'account';
|
||||
v = v || {};
|
||||
v.acctId = i;
|
||||
g(o, v);
|
||||
};
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
g.clearUserCookie = function() {};
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
})(window, document, window['_fs_namespace'], 'script', 'user');
|
||||
};
|
@ -1,31 +0,0 @@
|
||||
declare global {
|
||||
// tslint:disable-next-line: interface-name
|
||||
interface Window {
|
||||
analytics: any;
|
||||
}
|
||||
}
|
||||
|
||||
export const setupGoogleAnalytics = async (gaCode: string) => {
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
(function(i, s, o, g, r, a, m) {
|
||||
// tslint:disable-next-line: no-string-literal
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
// tslint:disable-next-line: ban-comma-operator
|
||||
(i[r] =
|
||||
i[r] ||
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
function() {
|
||||
(i[r].q = i[r].q || []).push(arguments);
|
||||
}),
|
||||
(i[r].l = new Date().getTime());
|
||||
// tslint:disable-next-line: ban-comma-operator
|
||||
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m);
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'analytics');
|
||||
|
||||
window.analytics('create', gaCode, 'auto');
|
||||
window.analytics('send', 'pageview');
|
||||
console.log('Loaded Google Analytics. You may view our privacy policy at https://lossless.gmbh');
|
||||
};
|
75
ts/websetup.classes.tag.jsonldtag.ts
Normal file
75
ts/websetup.classes.tag.jsonldtag.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import * as plugins from './websetup.plugins';
|
||||
import * as interfaces from './interfaces';
|
||||
|
||||
import { Tag } from './websetup.classes.tag';
|
||||
|
||||
export class JsonLdTag extends Tag {
|
||||
public static createCompanyLd(companyDataArg: plugins.tsclass.business.ICompany) {
|
||||
// lets care about linked data
|
||||
const companyLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Corporation',
|
||||
name: companyDataArg.name,
|
||||
alternateName: companyDataArg.name.replace(' GmbH', ''),
|
||||
url: companyDataArg.contact.website,
|
||||
logo: companyDataArg.contact.logoUrl,
|
||||
contactPoint: {
|
||||
'@type': 'ContactPoint',
|
||||
telephone: companyDataArg.contact.phone,
|
||||
contactType: 'customer service',
|
||||
areaServed: 'DE',
|
||||
availableLanguage: ['en', 'German'],
|
||||
},
|
||||
sameAs: [],
|
||||
};
|
||||
|
||||
if (companyDataArg.contact.facebookUrl) {
|
||||
companyLd.sameAs.push(companyDataArg.contact.facebookUrl);
|
||||
}
|
||||
|
||||
if (companyDataArg.contact.twitterUrl) {
|
||||
companyLd.sameAs.push(companyDataArg.contact.twitterUrl);
|
||||
}
|
||||
|
||||
const ldTag = new JsonLdTag(companyLd);
|
||||
return ldTag;
|
||||
}
|
||||
|
||||
public static createNewsArticleLd (newsArticleArg: plugins.tsclass.content.IArticle) {
|
||||
const newsArticleLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "NewsArticle",
|
||||
"mainEntityOfPage": {
|
||||
"@type": "WebPage",
|
||||
"@id": window.location.href
|
||||
},
|
||||
"headline": "Article headline",
|
||||
"image": [
|
||||
newsArticleArg.featuredImageUrl
|
||||
],
|
||||
"datePublished": new Date(newsArticleArg.timestamp).toISOString(),
|
||||
"dateModified": new Date(newsArticleArg.timestamp).toISOString(),
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": `${newsArticleArg.author.firstName} ${newsArticleArg.author.surName}`
|
||||
},
|
||||
"publisher": {
|
||||
"@type": "Organization",
|
||||
"name": newsArticleArg.author.surName, // TODO
|
||||
"logo": {
|
||||
"@type": "ImageObject",
|
||||
"url": newsArticleArg.author.surName // TODO
|
||||
}
|
||||
},
|
||||
"description": newsArticleArg.author.firstName
|
||||
};
|
||||
}
|
||||
|
||||
constructor(ldObjectArg: any) {
|
||||
super();
|
||||
const jsonLdElement = document.createElement('script');
|
||||
jsonLdElement.type = 'application/ld+json';
|
||||
jsonLdElement.text = JSON.stringify(JSON.stringify(ldObjectArg));
|
||||
this.elementRef = jsonLdElement;
|
||||
}
|
||||
}
|
13
ts/websetup.classes.tag.linktag.ts
Normal file
13
ts/websetup.classes.tag.linktag.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { Tag } from './websetup.classes.tag';
|
||||
|
||||
export class LinkTag extends Tag {
|
||||
constructor(relArg: string, hrefArg: string) {
|
||||
super();
|
||||
const linkElement = !!document.querySelector("link[rel='canonical']")
|
||||
? document.querySelector("link[rel='canonical']")
|
||||
: document.createElement('link');
|
||||
linkElement.setAttribute('rel', relArg);
|
||||
linkElement.setAttribute('href', hrefArg);
|
||||
this.elementRef = linkElement;
|
||||
}
|
||||
}
|
11
ts/websetup.classes.tag.metatag.ts
Normal file
11
ts/websetup.classes.tag.metatag.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Tag } from './websetup.classes.tag';
|
||||
|
||||
export class MetaTag extends Tag {
|
||||
constructor(metaNameArg: string, contentArg: string) {
|
||||
super();
|
||||
const metaElement = document.createElement('meta');
|
||||
metaElement.name = metaNameArg;
|
||||
metaElement.content = contentArg;
|
||||
this.elementRef = metaElement;
|
||||
}
|
||||
}
|
11
ts/websetup.classes.tag.opengraphtag.ts
Normal file
11
ts/websetup.classes.tag.opengraphtag.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Tag } from './websetup.classes.tag';
|
||||
|
||||
export class OpengraphTag extends Tag {
|
||||
constructor(propertyNameArg: string, contentArg: string) {
|
||||
super();
|
||||
const openGraphElement = document.createElement('meta');
|
||||
openGraphElement.setAttribute('property', propertyNameArg);
|
||||
openGraphElement.content = contentArg;
|
||||
this.elementRef = openGraphElement;
|
||||
}
|
||||
}
|
21
ts/websetup.classes.tag.ts
Normal file
21
ts/websetup.classes.tag.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import * as plugins from './websetup.plugins';
|
||||
|
||||
export class Tag {
|
||||
public elementRef: Element;
|
||||
|
||||
public tagLevel: 'global' | 'levelbound';
|
||||
|
||||
public appendToDom() {
|
||||
if (!this.elementRef.parentElement && !this.elementRef.parentNode) {
|
||||
document.getElementsByTagName('head')[0].appendChild(this.elementRef);
|
||||
}
|
||||
}
|
||||
|
||||
public removeFromDom() {
|
||||
if (this.elementRef.parentElement) {
|
||||
this.elementRef.parentElement.removeChild(this.elementRef);
|
||||
} else if (this.elementRef.parentNode) {
|
||||
this.elementRef.parentNode.removeChild(this.elementRef);
|
||||
}
|
||||
}
|
||||
}
|
71
ts/websetup.classes.taglevel.ts
Normal file
71
ts/websetup.classes.taglevel.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import { Tag } from './websetup.classes.tag';
|
||||
import { JsonLdTag } from './websetup.classes.tag.jsonldtag';
|
||||
import { OpengraphTag } from './websetup.classes.tag.opengraphtag';
|
||||
import { TagManager } from './websetup.classes.tagmanager';
|
||||
import * as plugins from './websetup.plugins';
|
||||
|
||||
export type TBaseLevelType = 'global' | 'base' | 'subpage';
|
||||
|
||||
export class TagLevel {
|
||||
public tagManagerRef: TagManager;
|
||||
|
||||
public title: string;
|
||||
public type: TBaseLevelType;
|
||||
public tags: Tag[] = [];
|
||||
|
||||
constructor(tagManagerRefArg: TagManager, levelType: TBaseLevelType) {
|
||||
this.tagManagerRef = tagManagerRefArg;
|
||||
}
|
||||
|
||||
public addTag(tagArg: Tag) {
|
||||
this.tags.push(tagArg);
|
||||
}
|
||||
|
||||
public async addCompanyInfo(companyDataArg: plugins.tsclass.business.ICompany) {
|
||||
this.addTag(JsonLdTag.createCompanyLd(companyDataArg));
|
||||
|
||||
// lets care about open graph
|
||||
this.addTag(new OpengraphTag('og:type', 'business.business'));
|
||||
this.addTag(new OpengraphTag('og:title', companyDataArg.name));
|
||||
this.addTag(new OpengraphTag('og:url', companyDataArg.contact.website));
|
||||
this.addTag(new OpengraphTag('og:image', companyDataArg.contact.logoUrl));
|
||||
this.addTag(
|
||||
new OpengraphTag(
|
||||
'business:contact_data:street_address',
|
||||
`${companyDataArg.contact.address.streetName} ${companyDataArg.contact.address.houseNumber}`
|
||||
)
|
||||
);
|
||||
this.addTag(
|
||||
new OpengraphTag('business:contact_data:locality', companyDataArg.contact.address.postalCode)
|
||||
);
|
||||
this.addTag(
|
||||
new OpengraphTag('business:contact_data:region', companyDataArg.contact.address.city)
|
||||
);
|
||||
this.addTag(
|
||||
new OpengraphTag(
|
||||
'business:contact_data:postal_code',
|
||||
companyDataArg.contact.address.postalCode
|
||||
)
|
||||
);
|
||||
this.addTag(
|
||||
new OpengraphTag('business:contact_data:country_name', companyDataArg.contact.address.country)
|
||||
);
|
||||
}
|
||||
|
||||
public addPostInfo() {}
|
||||
|
||||
public async enable() {
|
||||
if (this.title) {
|
||||
document.title = this.title;
|
||||
}
|
||||
for (const tagArg of this.tags) {
|
||||
tagArg.appendToDom();
|
||||
}
|
||||
}
|
||||
|
||||
public async disable() {
|
||||
for (const tagArg of this.tags) {
|
||||
tagArg.removeFromDom();
|
||||
}
|
||||
}
|
||||
}
|
54
ts/websetup.classes.tagmanager.ts
Normal file
54
ts/websetup.classes.tagmanager.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { TagLevel } from './websetup.classes.taglevel';
|
||||
import * as plugins from './websetup.plugins';
|
||||
import * as interfaces from './interfaces';
|
||||
import { MetaTag } from './websetup.classes.tag.metatag';
|
||||
import { JsonLdTag } from './websetup.classes.tag.jsonldtag';
|
||||
import { OpengraphTag } from './websetup.classes.tag.opengraphtag';
|
||||
|
||||
export class TagManager {
|
||||
public globalLevel: TagLevel;
|
||||
|
||||
public baseLevel: TagLevel;
|
||||
|
||||
public activeLevel: TagLevel;
|
||||
|
||||
public async setup(metaObjectArg: interfaces.IMetaObject) {
|
||||
// global tag level
|
||||
this.globalLevel = new TagLevel(this, 'global');
|
||||
this.globalLevel.addTag(new MetaTag('google', 'notranslate'));
|
||||
this.globalLevel.addTag(new MetaTag('revisit-after', '1 days'));
|
||||
|
||||
// base tag level
|
||||
this.baseLevel = new TagLevel(this, 'base');
|
||||
this.baseLevel.title = metaObjectArg.title;
|
||||
this.baseLevel.addTag(new MetaTag('description', metaObjectArg.description));
|
||||
|
||||
if (metaObjectArg.canonicalDomain) {
|
||||
this.baseLevel.addTag(new MetaTag('canonical', metaObjectArg.canonicalDomain));
|
||||
}
|
||||
|
||||
if (metaObjectArg.ldCompany) {
|
||||
this.baseLevel.addCompanyInfo(metaObjectArg.ldCompany);
|
||||
}
|
||||
await this.globalLevel.enable();
|
||||
await this.baseLevel.enable();
|
||||
}
|
||||
|
||||
public setSubPageLevel(metaObjectArg: interfaces.IMetaObject) {
|
||||
const subPageLevel = new TagLevel(this, 'subpage');
|
||||
subPageLevel.title = metaObjectArg.title;
|
||||
subPageLevel.addTag(new MetaTag('description', metaObjectArg.description));
|
||||
this.activeLevel.disable();
|
||||
this.activeLevel = subPageLevel;
|
||||
this.activeLevel.enable();
|
||||
return subPageLevel;
|
||||
}
|
||||
|
||||
public revertToBaseLevel() {
|
||||
if (this.activeLevel !== this.baseLevel) {
|
||||
this.activeLevel.disable();
|
||||
this.activeLevel = this.baseLevel;
|
||||
this.activeLevel.enable();
|
||||
}
|
||||
}
|
||||
}
|
46
ts/websetup.classes.websetup.ts
Normal file
46
ts/websetup.classes.websetup.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import * as plugins from './websetup.plugins';
|
||||
import * as interfaces from './interfaces';
|
||||
import { TagManager } from './websetup.classes.tagmanager';
|
||||
import { TagLevel } from './websetup.classes.taglevel';
|
||||
|
||||
export interface IWebSetupConstructorOptions {
|
||||
metaObject: interfaces.IMetaObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* the main WebSetup class
|
||||
*/
|
||||
export class WebSetup {
|
||||
public tagManager: TagManager = new TagManager();
|
||||
public options: IWebSetupConstructorOptions;
|
||||
private readyDeferred = plugins.smartpromise.defer();
|
||||
public readyPromise = this.readyDeferred.promise;
|
||||
constructor(optionsArg: IWebSetupConstructorOptions) {
|
||||
this.options = optionsArg;
|
||||
this.setup().then(() => {
|
||||
this.readyDeferred.resolve();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* an async setup called by the constructor
|
||||
*/
|
||||
private async setup() {
|
||||
await this.tagManager.setup(this.options.metaObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* reverts the active level and returns to the base level
|
||||
*/
|
||||
public revertToBaseLevel() {
|
||||
this.tagManager.revertToBaseLevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* sets a subpage
|
||||
* @param metaObjectArg
|
||||
*/
|
||||
public setSubLevel(metaObjectArg: interfaces.IMetaObject) {
|
||||
return this.tagManager.setSubPageLevel(metaObjectArg);
|
||||
}
|
||||
}
|
@ -1,2 +1,9 @@
|
||||
const removeme = {};
|
||||
export { removeme };
|
||||
// pushrocks scope
|
||||
import * as smartpromise from '@pushrocks/smartpromise';
|
||||
|
||||
export { smartpromise };
|
||||
|
||||
// tsclass scope
|
||||
import * as tsclass from '@tsclass/tsclass';
|
||||
|
||||
export { tsclass };
|
||||
|
Reference in New Issue
Block a user