@venqoo/brand 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +53 -11
- package/dist/credit/copy.d.ts +23 -7
- package/dist/credit/copy.js +37 -11
- package/dist/credit/credit.d.ts +6 -2
- package/dist/credit/credit.js +15 -3
- package/dist/credit/imprint.d.ts +12 -4
- package/dist/credit/imprint.js +20 -6
- package/dist/credit/index.d.ts +5 -3
- package/dist/credit/index.js +2 -1
- package/dist/credit/link.d.ts +27 -2
- package/dist/credit/link.js +40 -3
- package/dist/credit/types.d.ts +21 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,12 +31,15 @@ import { Credit, ImprintCredit } from '@venqoo/brand/credit'
|
|
|
31
31
|
import '@venqoo/brand/credit.css'
|
|
32
32
|
|
|
33
33
|
// footer
|
|
34
|
-
<Credit />
|
|
35
|
-
<Credit variant="pill" theme="dark" />
|
|
34
|
+
<Credit site="baeckerei-muster.de" /> // Made with ♥ by venqoo in Würzburg
|
|
35
|
+
<Credit site="baeckerei-muster.de" variant="pill" theme="dark" />
|
|
36
36
|
|
|
37
37
|
// imprint / legal notice
|
|
38
|
-
<ImprintCredit />
|
|
38
|
+
<ImprintCredit site="baeckerei-muster.de" /> // heading, sentence, address
|
|
39
|
+
<ImprintCredit site="baeckerei-muster.de" lang="de" /> // the same, in German
|
|
40
|
+
<ImprintCredit site="baeckerei-muster.de" subject="app" /> // "This app was designed…"
|
|
39
41
|
<ImprintCredit
|
|
42
|
+
site="baeckerei-muster.de"
|
|
40
43
|
variant="card"
|
|
41
44
|
roles={[
|
|
42
45
|
{ term: 'App', detail: 'iOS & Android' },
|
|
@@ -45,8 +48,10 @@ import '@venqoo/brand/credit.css'
|
|
|
45
48
|
/>
|
|
46
49
|
```
|
|
47
50
|
|
|
48
|
-
Every variant
|
|
49
|
-
|
|
51
|
+
Every variant links to `https://www.venqoo.com` and opens in a new tab. Pass
|
|
52
|
+
`site` on every credit: it tags the link so venqoo can see where a visitor came
|
|
53
|
+
from (see [Attribution and search engines](#attribution-and-search-engines)).
|
|
54
|
+
Footer copy is English only; the imprint credit also comes in German.
|
|
50
55
|
|
|
51
56
|
### `<Credit>` — footer credit
|
|
52
57
|
|
|
@@ -74,19 +79,56 @@ concept / design / development / operations; pass your own, or `[]` to hide it.
|
|
|
74
79
|
`children` replaces the descriptive sentence on `section`, and `headingLevel`
|
|
75
80
|
(2–4) matches the imprint's other headings.
|
|
76
81
|
|
|
82
|
+
`lang` is `'en'` (default) or `'de'`. It sets the heading, sentence, eyebrow,
|
|
83
|
+
country and default roles, and the root's `lang` attribute. Custom `roles` and
|
|
84
|
+
`children` are yours to translate. The default lists are exported as
|
|
85
|
+
`imprintRoles.en` / `imprintRoles.de` (`defaultRoles` is the English one), so a
|
|
86
|
+
project can extend them.
|
|
87
|
+
|
|
88
|
+
`subject` is `'website'` (default) or `'app'` and sets the first sentence's
|
|
89
|
+
subject: "This website was designed and developed by venqoo, a software agency
|
|
90
|
+
in Würzburg, Germany." becomes "This app was…" on an app's legal screen. A
|
|
91
|
+
second sentence says what venqoo GmbH does; `children` replaces both.
|
|
92
|
+
|
|
77
93
|
### Shared props
|
|
78
94
|
|
|
79
|
-
| Prop | Type
|
|
80
|
-
| ----------- |
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
95
|
+
| Prop | Type | Default |
|
|
96
|
+
| ----------- | -------------------------------------- | --------------------------------------------- |
|
|
97
|
+
| `site` | `string` | — (set it: the client site's host) |
|
|
98
|
+
| `rel` | `'nofollow' \| 'follow' \| 'sponsored'` | `'nofollow'` on `Credit`, `'follow'` on `ImprintCredit` |
|
|
99
|
+
| `theme` | `'light' \| 'dark' \| 'auto'` | `'light'` |
|
|
100
|
+
| `href` | `string` | `https://www.venqoo.com` |
|
|
101
|
+
| `newTab` | `boolean` | `true` |
|
|
102
|
+
| `className` | `string` | — |
|
|
85
103
|
|
|
86
104
|
`theme` switches the colour tokens: use `dark` for a dark footer, `auto` on
|
|
87
105
|
sites with a colour-scheme toggle (it follows `prefers-color-scheme`). The
|
|
88
106
|
component cannot see what it sits on, so `light` is the predictable default.
|
|
89
107
|
|
|
108
|
+
### Attribution and search engines
|
|
109
|
+
|
|
110
|
+
The package runs no script and loads nothing; the link is the whole tracker.
|
|
111
|
+
With `site="baeckerei-muster.de"`, a footer credit links to
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
https://www.venqoo.com?utm_source=baeckerei-muster.de&utm_medium=credit&utm_campaign=footer&utm_content=heart
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`utm_source` is the site (normalised to its bare host), `utm_campaign` the
|
|
118
|
+
placement (`footer` or `imprint`) and `utm_content` the variant, so analytics
|
|
119
|
+
on venqoo.com show which site, placement and design a visitor clicked. Without
|
|
120
|
+
`site` the link is untagged; the Referer header then only names the origin, and
|
|
121
|
+
not at all on sites with a strict `Referrer-Policy`. Existing query parameters
|
|
122
|
+
and fragments on a custom `href` are kept. `creditHref()` builds the same URL
|
|
123
|
+
for links you render yourself.
|
|
124
|
+
|
|
125
|
+
`rel` says how search engines should read the link. Google asks for links that
|
|
126
|
+
sit in the template of many sites to be qualified, so the footer credit is
|
|
127
|
+
`nofollow` by default; the imprint credit is one editorial sentence naming the
|
|
128
|
+
maker and stays `follow`. Both can be overridden per project, and `sponsored` is
|
|
129
|
+
for credits that are part of a deal, such as a discount for keeping them. Links
|
|
130
|
+
that open in a new tab always carry `noopener`, never `noreferrer`.
|
|
131
|
+
|
|
90
132
|
### Styling the credit
|
|
91
133
|
|
|
92
134
|
All credit styles live under `.vq-credit` and are driven by CSS custom
|
package/dist/credit/copy.d.ts
CHANGED
|
@@ -9,17 +9,33 @@ export declare const footerCopy: {
|
|
|
9
9
|
readonly pill: 'Made by';
|
|
10
10
|
readonly pillSignal: 'Made with love by';
|
|
11
11
|
};
|
|
12
|
+
/** Languages the imprint credit is written in. */
|
|
13
|
+
export type ImprintLang = 'en' | 'de';
|
|
14
|
+
/** What the imprint credit says venqoo made: a website (default) or an app. */
|
|
15
|
+
export type ImprintSubject = 'website' | 'app';
|
|
12
16
|
export interface ImprintRole {
|
|
13
17
|
/** What venqoo was responsible for, e.g. "Development". */
|
|
14
18
|
term: string;
|
|
15
19
|
/** The specifics, e.g. "Front end & back end". */
|
|
16
20
|
detail: string;
|
|
17
21
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
/**
|
|
22
|
+
interface ImprintCopy {
|
|
23
|
+
heading: string;
|
|
24
|
+
/** "This website" / "This app" — the sentence's subject. */
|
|
25
|
+
subject: Record<ImprintSubject, string>;
|
|
26
|
+
/** Between the subject and the linked name "venqoo". */
|
|
27
|
+
sentenceBefore: string;
|
|
28
|
+
/** After the linked name, including the full stop. */
|
|
29
|
+
sentenceAfter: string;
|
|
30
|
+
/** Second sentence: what venqoo GmbH does. */
|
|
31
|
+
about: string;
|
|
32
|
+
eyebrow: string;
|
|
33
|
+
country: string;
|
|
34
|
+
roles: readonly ImprintRole[];
|
|
35
|
+
}
|
|
36
|
+
export declare const imprintCopy: Record<ImprintLang, ImprintCopy>;
|
|
37
|
+
/** Default role list for the card, per language; override per project with the `roles` prop. */
|
|
38
|
+
export declare const imprintRoles: Record<ImprintLang, readonly ImprintRole[]>;
|
|
39
|
+
/** The English default role list. */
|
|
25
40
|
export declare const defaultRoles: readonly ImprintRole[];
|
|
41
|
+
export {};
|
package/dist/credit/copy.js
CHANGED
|
@@ -11,15 +11,41 @@ export const footerCopy = {
|
|
|
11
11
|
pillSignal: 'Made with love by',
|
|
12
12
|
};
|
|
13
13
|
export const imprintCopy = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
en: {
|
|
15
|
+
heading: 'Concept, design & development',
|
|
16
|
+
subject: { website: 'This website', app: 'This app' },
|
|
17
|
+
sentenceBefore: 'was designed and developed by',
|
|
18
|
+
sentenceAfter: ', a software agency in Würzburg, Germany.',
|
|
19
|
+
about: 'venqoo GmbH builds apps, websites and custom software and advises companies on AI strategy and AI integration.',
|
|
20
|
+
eyebrow: 'Built by',
|
|
21
|
+
country: 'Germany',
|
|
22
|
+
roles: [
|
|
23
|
+
{ term: 'Concept', detail: 'UX & structure' },
|
|
24
|
+
{ term: 'Design', detail: 'Visual concept' },
|
|
25
|
+
{ term: 'Development', detail: 'Front end & back end' },
|
|
26
|
+
{ term: 'Operations', detail: 'Hosting & maintenance' },
|
|
27
|
+
],
|
|
28
|
+
},
|
|
29
|
+
de: {
|
|
30
|
+
heading: 'Konzept, Design & Entwicklung',
|
|
31
|
+
subject: { website: 'Diese Website', app: 'Diese App' },
|
|
32
|
+
sentenceBefore: 'wurde von',
|
|
33
|
+
sentenceAfter: ', einer Software-Agentur aus Würzburg, gestaltet und entwickelt.',
|
|
34
|
+
about: 'Die venqoo GmbH entwickelt Apps, Websites und individuelle Software und berät Unternehmen zu KI-Strategie und KI-Integration.',
|
|
35
|
+
eyebrow: 'Umgesetzt von',
|
|
36
|
+
country: 'Deutschland',
|
|
37
|
+
roles: [
|
|
38
|
+
{ term: 'Konzept', detail: 'UX & Struktur' },
|
|
39
|
+
{ term: 'Design', detail: 'Visuelles Konzept' },
|
|
40
|
+
{ term: 'Entwicklung', detail: 'Frontend & Backend' },
|
|
41
|
+
{ term: 'Betrieb', detail: 'Hosting & Wartung' },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
18
44
|
};
|
|
19
|
-
/** Default role list for the card; override per project with the `roles` prop. */
|
|
20
|
-
export const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
45
|
+
/** Default role list for the card, per language; override per project with the `roles` prop. */
|
|
46
|
+
export const imprintRoles = {
|
|
47
|
+
en: imprintCopy.en.roles,
|
|
48
|
+
de: imprintCopy.de.roles,
|
|
49
|
+
};
|
|
50
|
+
/** The English default role list. */
|
|
51
|
+
export const defaultRoles = imprintRoles.en;
|
package/dist/credit/credit.d.ts
CHANGED
|
@@ -9,5 +9,9 @@ export type CreditVariant = 'heart' | 'mark' | 'pill' | 'pill-signal';
|
|
|
9
9
|
export interface CreditProps extends CreditBaseProps {
|
|
10
10
|
variant?: CreditVariant;
|
|
11
11
|
}
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Footer credit: one link to venqoo in the style of your choice. Pass `site` so
|
|
14
|
+
* visits can be attributed to the client site; the link is `nofollow` unless
|
|
15
|
+
* `rel` says otherwise.
|
|
16
|
+
*/
|
|
17
|
+
export declare function Credit({ variant, theme, className, href, site, rel, newTab, }: CreditProps): import("react").JSX.Element;
|
package/dist/credit/credit.js
CHANGED
|
@@ -4,9 +4,21 @@ import { Heart, UfoMark } from '../marks.js';
|
|
|
4
4
|
import { VENQOO } from '../venqoo.js';
|
|
5
5
|
import { footerCopy as t } from './copy.js';
|
|
6
6
|
import { linkAttrs } from './link.js';
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Footer credit: one link to venqoo in the style of your choice. Pass `site` so
|
|
9
|
+
* visits can be attributed to the client site; the link is `nofollow` unless
|
|
10
|
+
* `rel` says otherwise.
|
|
11
|
+
*/
|
|
12
|
+
export function Credit({ variant = 'heart', theme = 'light', className, href, site, rel, newTab, }) {
|
|
13
|
+
const a = linkAttrs({
|
|
14
|
+
href,
|
|
15
|
+
site,
|
|
16
|
+
rel,
|
|
17
|
+
newTab,
|
|
18
|
+
placement: 'footer',
|
|
19
|
+
variant,
|
|
20
|
+
defaultRel: 'nofollow',
|
|
21
|
+
});
|
|
10
22
|
const name = _jsx("span", { className: "vq-credit__name", children: VENQOO.name });
|
|
11
23
|
let content;
|
|
12
24
|
switch (variant) {
|
package/dist/credit/imprint.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import { type ImprintRole } from './copy.js';
|
|
2
|
+
import { type ImprintLang, type ImprintRole, type ImprintSubject } from './copy.js';
|
|
3
3
|
import type { CreditBaseProps } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* - `section` — heading, sentence and address; inherits the imprint's type (default)
|
|
@@ -10,13 +10,21 @@ export interface ImprintCreditProps extends CreditBaseProps {
|
|
|
10
10
|
variant?: ImprintCreditVariant;
|
|
11
11
|
/** Heading element for `section`; match the imprint's other section headings. */
|
|
12
12
|
headingLevel?: 2 | 3 | 4;
|
|
13
|
+
/** Language of the copy and the address: English (default) or German. */
|
|
14
|
+
lang?: ImprintLang;
|
|
15
|
+
/** What the sentence on `section` says venqoo made: a `website` (default) or an `app`. */
|
|
16
|
+
subject?: ImprintSubject;
|
|
13
17
|
/**
|
|
14
18
|
* What venqoo was responsible for in this project, shown on `card`.
|
|
15
|
-
* Defaults to concept, design, development and operations
|
|
19
|
+
* Defaults to concept, design, development and operations in `lang`; pass `[]` to hide the list.
|
|
16
20
|
*/
|
|
17
21
|
roles?: readonly ImprintRole[];
|
|
18
22
|
/** Replaces the descriptive sentence on `section`. */
|
|
19
23
|
children?: ReactNode;
|
|
20
24
|
}
|
|
21
|
-
/**
|
|
22
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Impressum / legal-notice credit naming venqoo GmbH as the maker of the site or
|
|
27
|
+
* app. Pass `site` so visits can be attributed to the client site. Its links are
|
|
28
|
+
* followed unless `rel` says otherwise: one editorial sentence, not a template.
|
|
29
|
+
*/
|
|
30
|
+
export declare function ImprintCredit({ variant, theme, headingLevel, lang, subject, roles, className, href, site, rel, newTab, children, }: ImprintCreditProps): import("react").JSX.Element;
|
package/dist/credit/imprint.js
CHANGED
|
@@ -2,16 +2,30 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { cx } from '../cx.js';
|
|
3
3
|
import { UfoMark } from '../marks.js';
|
|
4
4
|
import { VENQOO } from '../venqoo.js';
|
|
5
|
-
import {
|
|
5
|
+
import { imprintCopy } from './copy.js';
|
|
6
6
|
import { linkAttrs } from './link.js';
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Impressum / legal-notice credit naming venqoo GmbH as the maker of the site or
|
|
9
|
+
* app. Pass `site` so visits can be attributed to the client site. Its links are
|
|
10
|
+
* followed unless `rel` says otherwise: one editorial sentence, not a template.
|
|
11
|
+
*/
|
|
12
|
+
export function ImprintCredit({ variant = 'section', theme = 'light', headingLevel = 2, lang = 'en', subject = 'website', roles, className, href, site, rel, newTab, children, }) {
|
|
13
|
+
const t = imprintCopy[lang];
|
|
14
|
+
const roleList = roles ?? t.roles;
|
|
15
|
+
const a = linkAttrs({
|
|
16
|
+
href,
|
|
17
|
+
site,
|
|
18
|
+
rel,
|
|
19
|
+
newTab,
|
|
20
|
+
placement: 'imprint',
|
|
21
|
+
variant,
|
|
22
|
+
defaultRel: 'follow',
|
|
23
|
+
});
|
|
10
24
|
const rootClass = cx('vq-credit', `vq-credit--${variant}`, className);
|
|
11
25
|
const Heading = `h${headingLevel}`;
|
|
12
26
|
const siteLink = (_jsx("a", { className: "vq-credit__textlink", ...a, children: VENQOO.displayUrl }));
|
|
13
27
|
if (variant === 'card') {
|
|
14
|
-
return (_jsxs("section", { className: rootClass, "data-theme": theme, lang:
|
|
28
|
+
return (_jsxs("section", { className: rootClass, "data-theme": theme, lang: lang, children: [_jsx("span", { className: "vq-credit__eyebrow", children: t.eyebrow }), _jsxs("a", { className: "vq-credit__link vq-credit__logo", ...a, children: [_jsx(UfoMark, { className: "vq-credit__mark" }), _jsx("span", { className: "vq-credit__wordmark", children: VENQOO.name })] }), roleList.length > 0 && (_jsx("dl", { className: "vq-credit__roles", children: roleList.map((role) => (_jsxs("div", { className: "vq-credit__role-item", children: [_jsx("dt", { children: role.term }), _jsx("dd", { children: role.detail })] }, role.term))) })), _jsxs("address", { className: "vq-credit__address", children: [_jsxs("span", { children: [VENQOO.legalName, " \u00B7 ", VENQOO.street, " \u00B7 ", VENQOO.postalCode, " ", VENQOO.city, " \u00B7 ", t.country] }), siteLink] })] }));
|
|
15
29
|
}
|
|
16
|
-
return (_jsxs("section", { className: rootClass, "data-theme": theme, lang:
|
|
30
|
+
return (_jsxs("section", { className: rootClass, "data-theme": theme, lang: lang, children: [_jsx(Heading, { className: "vq-credit__heading", children: t.heading }), _jsx("p", { className: "vq-credit__body", children: children ?? (_jsxs(_Fragment, { children: [t.subject[subject], " ", t.sentenceBefore, ' ', _jsx("a", { className: "vq-credit__textlink", ...a, children: VENQOO.name }), t.sentenceAfter, " ", t.about] })) }), _jsxs("address", { className: "vq-credit__address", children: [_jsx("span", { className: "vq-credit__address-name", children: VENQOO.legalName }), _jsx("span", { children: VENQOO.street }), _jsxs("span", { children: [VENQOO.postalCode, " ", VENQOO.city] }), _jsx("span", { children: t.country }), _jsx("a", { className: "vq-credit__textlink vq-credit__textlink--quiet vq-credit__address-gap", href: `mailto:${VENQOO.email}`, children: VENQOO.email }), siteLink] })] }));
|
|
17
31
|
}
|
package/dist/credit/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
export type { ImprintRole } from './copy.js';
|
|
2
|
-
export { defaultRoles } from './copy.js';
|
|
1
|
+
export type { ImprintLang, ImprintRole, ImprintSubject } from './copy.js';
|
|
2
|
+
export { defaultRoles, imprintRoles } from './copy.js';
|
|
3
3
|
export type { CreditProps, CreditVariant } from './credit.js';
|
|
4
4
|
export { Credit } from './credit.js';
|
|
5
5
|
export type { ImprintCreditProps, ImprintCreditVariant } from './imprint.js';
|
|
6
6
|
export { ImprintCredit } from './imprint.js';
|
|
7
|
-
export type {
|
|
7
|
+
export type { CreditHrefOptions, CreditPlacement } from './link.js';
|
|
8
|
+
export { creditHref, normalizeSite } from './link.js';
|
|
9
|
+
export type { CreditBaseProps, CreditLinkProps, CreditRel, CreditTheme } from './types.js';
|
package/dist/credit/index.js
CHANGED
package/dist/credit/link.d.ts
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
1
|
import type { AnchorHTMLAttributes } from 'react';
|
|
2
|
-
import type { CreditLinkProps } from './types.js';
|
|
3
|
-
|
|
2
|
+
import type { CreditLinkProps, CreditRel } from './types.js';
|
|
3
|
+
/** Where on the client site the credit sits; becomes `utm_campaign`. */
|
|
4
|
+
export type CreditPlacement = 'footer' | 'imprint';
|
|
5
|
+
export interface CreditHrefOptions {
|
|
6
|
+
/** Base URL; defaults to https://www.venqoo.com. */
|
|
7
|
+
href?: string;
|
|
8
|
+
/** The client site, e.g. "baeckerei-muster.de". Without it the base URL is returned as is. */
|
|
9
|
+
site?: string;
|
|
10
|
+
placement: CreditPlacement;
|
|
11
|
+
/** The component variant, e.g. "heart"; becomes `utm_content`. */
|
|
12
|
+
variant: string;
|
|
13
|
+
}
|
|
14
|
+
/** "https://www.Baeckerei-Muster.de/impressum" → "baeckerei-muster.de" */
|
|
15
|
+
export declare function normalizeSite(site: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* The credit's URL with campaign parameters when a `site` is given, so a visit
|
|
18
|
+
* can be attributed to the client site, the placement and the variant. Existing
|
|
19
|
+
* query parameters and fragments on `href` are kept.
|
|
20
|
+
*/
|
|
21
|
+
export declare function creditHref({ href, site, placement, variant, }: CreditHrefOptions): string;
|
|
22
|
+
export interface CreditLinkOptions extends CreditLinkProps {
|
|
23
|
+
placement: CreditPlacement;
|
|
24
|
+
variant: string;
|
|
25
|
+
/** Qualification used when the `rel` prop is not given. */
|
|
26
|
+
defaultRel: CreditRel;
|
|
27
|
+
}
|
|
28
|
+
export declare function linkAttrs({ href, site, rel, newTab, placement, variant, defaultRel, }: CreditLinkOptions): Pick<AnchorHTMLAttributes<HTMLAnchorElement>, 'href' | 'target' | 'rel'>;
|
package/dist/credit/link.js
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
import { DEFAULT_HREF } from './copy.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return
|
|
2
|
+
/** "https://www.Baeckerei-Muster.de/impressum" → "baeckerei-muster.de" */
|
|
3
|
+
export function normalizeSite(site) {
|
|
4
|
+
return site
|
|
5
|
+
.trim()
|
|
6
|
+
.toLowerCase()
|
|
7
|
+
.replace(/^[a-z][a-z0-9+.-]*:\/\//, '')
|
|
8
|
+
.replace(/^www\./, '')
|
|
9
|
+
.replace(/[/?#].*$/, '');
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The credit's URL with campaign parameters when a `site` is given, so a visit
|
|
13
|
+
* can be attributed to the client site, the placement and the variant. Existing
|
|
14
|
+
* query parameters and fragments on `href` are kept.
|
|
15
|
+
*/
|
|
16
|
+
export function creditHref({ href = DEFAULT_HREF, site, placement, variant, }) {
|
|
17
|
+
const source = site ? normalizeSite(site) : '';
|
|
18
|
+
if (!source)
|
|
19
|
+
return href;
|
|
20
|
+
const params = new URLSearchParams({
|
|
21
|
+
utm_source: source,
|
|
22
|
+
utm_medium: 'credit',
|
|
23
|
+
utm_campaign: placement,
|
|
24
|
+
utm_content: variant,
|
|
25
|
+
});
|
|
26
|
+
const hashAt = href.indexOf('#');
|
|
27
|
+
const base = hashAt === -1 ? href : href.slice(0, hashAt);
|
|
28
|
+
const hash = hashAt === -1 ? '' : href.slice(hashAt);
|
|
29
|
+
const separator = base.includes('?') ? '&' : '?';
|
|
30
|
+
return `${base}${separator}${params}${hash}`;
|
|
31
|
+
}
|
|
32
|
+
export function linkAttrs({ href, site, rel, newTab = true, placement, variant, defaultRel, }) {
|
|
33
|
+
const qualifier = rel ?? defaultRel;
|
|
34
|
+
// No `noreferrer`: besides the campaign parameters, the Referer header is how
|
|
35
|
+
// venqoo sees which client site sent a visitor.
|
|
36
|
+
const rels = [...(newTab ? ['noopener'] : []), ...(qualifier === 'follow' ? [] : [qualifier])];
|
|
37
|
+
return {
|
|
38
|
+
href: creditHref({ href, site, placement, variant }),
|
|
39
|
+
...(newTab ? { target: '_blank' } : {}),
|
|
40
|
+
...(rels.length > 0 ? { rel: rels.join(' ') } : {}),
|
|
41
|
+
};
|
|
5
42
|
}
|
package/dist/credit/types.d.ts
CHANGED
|
@@ -4,9 +4,30 @@
|
|
|
4
4
|
* colour-scheme toggle — the component cannot see what it sits on.
|
|
5
5
|
*/
|
|
6
6
|
export type CreditTheme = 'light' | 'dark' | 'auto';
|
|
7
|
+
/**
|
|
8
|
+
* How the link is qualified for search engines. `nofollow` and `sponsored` tell
|
|
9
|
+
* crawlers not to treat the link as an endorsement of venqoo; `follow` leaves it
|
|
10
|
+
* unqualified. `noopener` is added on top whenever the link opens in a new tab.
|
|
11
|
+
*
|
|
12
|
+
* The footer credit defaults to `nofollow`: it is the same link in the template
|
|
13
|
+
* of many sites, which Google asks to be qualified. The imprint credit defaults
|
|
14
|
+
* to `follow`: a single sentence naming the maker of the site. Use `sponsored`
|
|
15
|
+
* when the credit is part of a deal, e.g. a discount for keeping it.
|
|
16
|
+
*/
|
|
17
|
+
export type CreditRel = 'follow' | 'nofollow' | 'sponsored';
|
|
7
18
|
export interface CreditLinkProps {
|
|
8
19
|
/** Where the credit links to. Defaults to https://www.venqoo.com. */
|
|
9
20
|
href?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The client site the credit sits on, e.g. `"baeckerei-muster.de"`. When set,
|
|
23
|
+
* the link carries campaign parameters (`utm_source` = site, `utm_medium` =
|
|
24
|
+
* credit, `utm_campaign` = footer or imprint, `utm_content` = variant), so
|
|
25
|
+
* venqoo's analytics can tell which site, placement and design a visitor came
|
|
26
|
+
* from. Nothing runs or is tracked on the client site itself.
|
|
27
|
+
*/
|
|
28
|
+
site?: string;
|
|
29
|
+
/** Search-engine qualification of the link; see {@link CreditRel} for the defaults. */
|
|
30
|
+
rel?: CreditRel;
|
|
10
31
|
/** Open the link in a new tab (default) so the visitor stays on the client site. */
|
|
11
32
|
newTab?: boolean;
|
|
12
33
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type { ColorName, ColorScheme } from './colors.js';
|
|
2
2
|
export { colors } from './colors.js';
|
|
3
|
-
export type { CreditBaseProps, CreditLinkProps, CreditProps, CreditTheme, CreditVariant, ImprintCreditProps, ImprintCreditVariant, ImprintRole, } from './credit/index.js';
|
|
4
|
-
export { Credit, defaultRoles, ImprintCredit } from './credit/index.js';
|
|
3
|
+
export type { CreditBaseProps, CreditHrefOptions, CreditLinkProps, CreditPlacement, CreditProps, CreditRel, CreditTheme, CreditVariant, ImprintCreditProps, ImprintCreditVariant, ImprintLang, ImprintRole, ImprintSubject, } from './credit/index.js';
|
|
4
|
+
export { Credit, creditHref, defaultRoles, ImprintCredit, imprintRoles, normalizeSite, } from './credit/index.js';
|
|
5
5
|
export { fonts } from './fonts.js';
|
|
6
6
|
export { Heart, Logo, UfoMark } from './marks.js';
|
|
7
7
|
export { VENQOO } from './venqoo.js';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { colors } from './colors.js';
|
|
2
|
-
export { Credit, defaultRoles, ImprintCredit } from './credit/index.js';
|
|
2
|
+
export { Credit, creditHref, defaultRoles, ImprintCredit, imprintRoles, normalizeSite, } from './credit/index.js';
|
|
3
3
|
export { fonts } from './fonts.js';
|
|
4
4
|
export { Heart, Logo, UfoMark } from './marks.js';
|
|
5
5
|
export { VENQOO } from './venqoo.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venqoo/brand",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "venqoo brand kit: palette, type contract, marks and SVG assets, plus \"Made by venqoo\" credit components for sites and apps built by venqoo.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "venqoo GmbH (https://www.venqoo.com)",
|