@financial-times/dotcom-server-navigation 7.2.7 → 7.3.1
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/dist/node/actions.d.ts +2 -0
- package/dist/node/decorateMenuData.d.ts +1 -0
- package/dist/node/editions.d.ts +3 -0
- package/dist/node/index.d.ts +3 -0
- package/dist/node/navigation.d.ts +19 -0
- package/dist/node/selectMenuDataForEdition.d.ts +2 -0
- package/dist/tsconfig.tsbuildinfo +2060 -0
- package/package.json +7 -5
- package/src/actions.ts +0 -9
- package/src/decorateMenuData.ts +0 -53
- package/src/editions.ts +0 -27
- package/src/index.ts +0 -3
- package/src/navigation.ts +0 -104
- package/src/selectMenuDataForEdition.ts +0 -26
package/package.json
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/dotcom-server-navigation",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/node/index.js",
|
|
6
6
|
"types": "src/index.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
|
-
"tsc": "../../node_modules/.bin/tsc --incremental",
|
|
10
9
|
"clean": "npm run clean:dist && npm run clean:node_modules",
|
|
11
10
|
"clean:dist": "rm -rf dist",
|
|
12
11
|
"clean:node_modules": "rm -rf node_modules",
|
|
12
|
+
"build:node": "tsc",
|
|
13
13
|
"build": "npm run build:node",
|
|
14
|
-
"build:node": "npm run tsc -- --module commonjs --outDir ./dist/node",
|
|
15
14
|
"dev": "npm run build:node -- --watch",
|
|
16
15
|
"preinstall": "[ \"$INIT_CWD\" != \"$PWD\" ] || npm_config_yes=true npx check-engine"
|
|
17
16
|
},
|
|
@@ -19,7 +18,7 @@
|
|
|
19
18
|
"author": "",
|
|
20
19
|
"license": "MIT",
|
|
21
20
|
"dependencies": {
|
|
22
|
-
"@financial-times/dotcom-types-navigation": "
|
|
21
|
+
"@financial-times/dotcom-types-navigation": "file:../dotcom-types-navigation",
|
|
23
22
|
"@types/deep-freeze": "^0.1.1",
|
|
24
23
|
"deep-freeze": "0.0.1",
|
|
25
24
|
"ft-poller": "^7.2.1",
|
|
@@ -35,6 +34,9 @@
|
|
|
35
34
|
"node": ">= 14.0.0",
|
|
36
35
|
"npm": "7.x || 8.x"
|
|
37
36
|
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist/"
|
|
39
|
+
],
|
|
38
40
|
"repository": {
|
|
39
41
|
"type": "git",
|
|
40
42
|
"repository": "https://github.com/Financial-Times/dotcom-page-kit.git",
|
|
@@ -44,4 +46,4 @@
|
|
|
44
46
|
"volta": {
|
|
45
47
|
"extends": "../../package.json"
|
|
46
48
|
}
|
|
47
|
-
}
|
|
49
|
+
}
|
package/src/actions.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { TNavAction } from '@financial-times/dotcom-types-navigation'
|
|
2
|
-
|
|
3
|
-
export function getSubscribeAction(): TNavAction {
|
|
4
|
-
return {
|
|
5
|
-
id: 'subscribe',
|
|
6
|
-
name: 'Subscribe for full access',
|
|
7
|
-
url: '/products?segmentId=4526c036-7527-ab37-9a29-0b0403fa0b5f'
|
|
8
|
-
}
|
|
9
|
-
}
|
package/src/decorateMenuData.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { TNavMenuItem } from '@financial-times/dotcom-types-navigation'
|
|
2
|
-
|
|
3
|
-
const isSelected = (url: string, currentPath: string): boolean => {
|
|
4
|
-
return url === currentPath
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
const isMenuItem = (item: any): boolean => {
|
|
8
|
-
return item.hasOwnProperty('label') && item.hasOwnProperty('url')
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const decorateURL = (url: string, currentPath: string): string => {
|
|
12
|
-
if (url && url.includes('${currentPath}')) {
|
|
13
|
-
// Don't replace the URL placeholder with a barrier or error URL so that
|
|
14
|
-
// a user logging in is not redirected to a barrier or error!
|
|
15
|
-
const shouldReplace = !/\/(products|barriers|errors)/.test(currentPath)
|
|
16
|
-
const redirectPath = shouldReplace ? currentPath : '%2F'
|
|
17
|
-
return url.replace('${currentPath}', redirectPath)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return url
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const decorateMenuItem = (item: TNavMenuItem, currentPath: string): void => {
|
|
24
|
-
item.url = decorateURL(item.url, currentPath)
|
|
25
|
-
item.selected = isSelected(item.url, currentPath)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// This is a recursive clone function that will decorate objects it recognises as links
|
|
29
|
-
function cloneMenu(value: any, currentPath: string): any {
|
|
30
|
-
if (Array.isArray(value)) {
|
|
31
|
-
return value.map((item) => cloneMenu(item, currentPath))
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (Object(value) === value) {
|
|
35
|
-
const cloned = {}
|
|
36
|
-
|
|
37
|
-
for (const key of Object.keys(value)) {
|
|
38
|
-
cloned[key] = cloneMenu(value[key], currentPath)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (isMenuItem(cloned)) {
|
|
42
|
-
decorateMenuItem(cloned as TNavMenuItem, currentPath)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return cloned
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return value
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function decorateMenuData<Type>(menuData: Type, currentUrl: string): Type {
|
|
52
|
-
return cloneMenu(menuData, currentUrl)
|
|
53
|
-
}
|
package/src/editions.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { TNavEdition, TNavEditions } from '@financial-times/dotcom-types-navigation'
|
|
2
|
-
|
|
3
|
-
const availableEditions: TNavEdition[] = [
|
|
4
|
-
{
|
|
5
|
-
id: 'uk',
|
|
6
|
-
name: 'UK',
|
|
7
|
-
url: '/'
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
id: 'international',
|
|
11
|
-
name: 'International',
|
|
12
|
-
url: '/'
|
|
13
|
-
}
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
const editionIDs = availableEditions.map((edition) => edition.id)
|
|
17
|
-
|
|
18
|
-
export function isEdition(editionID: string): boolean {
|
|
19
|
-
return editionIDs.includes(editionID)
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function getEditions(currentEdition: string): TNavEditions {
|
|
23
|
-
return {
|
|
24
|
-
current: availableEditions.find((edition) => edition.id === currentEdition),
|
|
25
|
-
others: availableEditions.filter((edition) => edition.id !== currentEdition)
|
|
26
|
-
}
|
|
27
|
-
}
|
package/src/index.ts
DELETED
package/src/navigation.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import Poller from 'ft-poller'
|
|
2
|
-
import httpError from 'http-errors'
|
|
3
|
-
import deepFreeze from 'deep-freeze'
|
|
4
|
-
import fetch from 'node-fetch'
|
|
5
|
-
import {
|
|
6
|
-
TNavMenus,
|
|
7
|
-
TNavMenusForEdition,
|
|
8
|
-
TNavSubNavigation,
|
|
9
|
-
TNavEditions,
|
|
10
|
-
TNavAction
|
|
11
|
-
} from '@financial-times/dotcom-types-navigation'
|
|
12
|
-
import { selectMenuDataForEdition } from './selectMenuDataForEdition'
|
|
13
|
-
import { decorateMenuData } from './decorateMenuData'
|
|
14
|
-
import { getEditions, isEdition } from './editions'
|
|
15
|
-
import { getSubscribeAction } from './actions'
|
|
16
|
-
|
|
17
|
-
// Makes the navigation data completely immutable,
|
|
18
|
-
// To modify the data, clone the parts you need to change then modify in your app
|
|
19
|
-
const parseData = (data: any) => {
|
|
20
|
-
return deepFreeze(data)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const removeLeadingForwardSlash = (pagePath: string) => {
|
|
24
|
-
return pagePath.charAt(0) === '/' ? pagePath.substring(1) : pagePath
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type TNavOptions = {
|
|
28
|
-
menuUrl?: string
|
|
29
|
-
subNavigationUrl?: string
|
|
30
|
-
interval?: number
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const defaults: TNavOptions = {
|
|
34
|
-
menuUrl: 'http://next-navigation.ft.com/v2/menus',
|
|
35
|
-
subNavigationUrl: 'http://next-navigation.ft.com/v2/hierarchy',
|
|
36
|
-
interval: 15 * 60 * 1000 // poll every 15 minutes
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export class Navigation {
|
|
40
|
-
public options: TNavOptions
|
|
41
|
-
public poller: Poller
|
|
42
|
-
public initialPromise: Promise<void>
|
|
43
|
-
private menuData: TNavMenus
|
|
44
|
-
|
|
45
|
-
constructor(options: TNavOptions = {}) {
|
|
46
|
-
this.options = { ...defaults, ...options }
|
|
47
|
-
|
|
48
|
-
this.poller = new Poller({
|
|
49
|
-
url: this.options.menuUrl,
|
|
50
|
-
refreshInterval: this.options.interval,
|
|
51
|
-
parseData
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
this.initialPromise = this.poller.start({ initialRequest: true })
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async getMenusData(): Promise<TNavMenus> {
|
|
58
|
-
// initialPromise does not return data but must resolve before `getData` can be called
|
|
59
|
-
await this.initialPromise
|
|
60
|
-
|
|
61
|
-
this.menuData = this.poller.getData()
|
|
62
|
-
|
|
63
|
-
return this.menuData
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async getMenusFor(currentPath: string, currentEdition: string = 'uk'): Promise<TNavMenusForEdition> {
|
|
68
|
-
const menusData = await this.getMenusData()
|
|
69
|
-
const menusForEdition = selectMenuDataForEdition(menusData, currentEdition)
|
|
70
|
-
|
|
71
|
-
return decorateMenuData(menusForEdition, currentPath)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async getSubNavigationFor(path: string): Promise<TNavSubNavigation> {
|
|
75
|
-
const currentPage = removeLeadingForwardSlash(path)
|
|
76
|
-
const subNavigation = `${this.options.subNavigationUrl}/${currentPage}`
|
|
77
|
-
const response = await fetch(subNavigation)
|
|
78
|
-
|
|
79
|
-
if (response.ok) {
|
|
80
|
-
const data = await response.json()
|
|
81
|
-
|
|
82
|
-
const currentItem = { ...data.item, selected: true }
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
breadcrumb: data.ancestors.concat(currentItem),
|
|
86
|
-
subsections: data.children
|
|
87
|
-
}
|
|
88
|
-
} else {
|
|
89
|
-
throw httpError(response.status, `Sub-navigation for ${currentPage} could not be found.`)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
getEditionsFor(currentEdition: string = 'uk'): TNavEditions {
|
|
94
|
-
if (isEdition(currentEdition)) {
|
|
95
|
-
return getEditions(currentEdition)
|
|
96
|
-
} else {
|
|
97
|
-
throw Error(`The provided edition "${currentEdition}" is not a valid edition`)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
getSubscribeAction(): TNavAction {
|
|
102
|
-
return getSubscribeAction()
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { TNavMenuKeys, TNavMenus, TNavMenusForEdition } from '@financial-times/dotcom-types-navigation'
|
|
2
|
-
|
|
3
|
-
const sharedMenuKeys: TNavMenuKeys[] = [
|
|
4
|
-
'account',
|
|
5
|
-
'anon',
|
|
6
|
-
'footer',
|
|
7
|
-
'navbar-simple',
|
|
8
|
-
'navbar-right',
|
|
9
|
-
'navbar-right-anon',
|
|
10
|
-
'user'
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
export function selectMenuDataForEdition(menuData: TNavMenus, currentEdition: string): TNavMenusForEdition {
|
|
14
|
-
const output = {
|
|
15
|
-
navbar: menuData[`navbar-${currentEdition}`],
|
|
16
|
-
drawer: menuData[`drawer-${currentEdition}`]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
for (const key of sharedMenuKeys) {
|
|
20
|
-
if (menuData[key]) {
|
|
21
|
-
output[key] = menuData[key]
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return output as TNavMenusForEdition
|
|
26
|
-
}
|