@playpilot/tpi 6.5.0 → 6.5.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/link-injections.js +11 -10
- package/eslint.config.js +22 -0
- package/package.json +2 -2
- package/src/lib/api/api.ts +1 -0
- package/src/lib/api/externalPages.ts +1 -0
- package/src/lib/clipboard.ts +4 -4
- package/src/lib/modal.ts +15 -15
- package/src/lib/popover.ts +3 -3
- package/src/lib/routes.ts +2 -2
- package/src/lib/tracking.ts +1 -0
- package/src/lib/trailer.ts +5 -5
- package/src/main.ts +1 -0
- package/src/routes/components/Button.svelte +0 -1
- package/src/routes/components/Editorial/DragHandle.svelte +0 -1
- package/src/routes/components/Editorial/EditorItem.svelte +0 -1
- package/src/routes/components/Editorial/ManualInjection.svelte +0 -1
- package/src/routes/components/Editorial/ResizeHandle.svelte +0 -1
- package/src/routes/components/Editorial/Search/TitleSearch.svelte +0 -1
- package/src/routes/components/Editorial/Session.svelte +0 -1
- package/src/routes/components/Editorial/Switch.svelte +0 -1
- package/src/routes/components/Explore/Filter/Dropdown.svelte +0 -1
- package/src/routes/components/Explore/Filter/FilterItem.svelte +3 -4
- package/src/routes/components/Explore/Filter/Range.svelte +0 -2
- package/src/routes/components/Explore/Filter/Search.svelte +0 -1
- package/src/routes/components/Explore/Filter/TogglesWithSearch.svelte +0 -1
- package/src/routes/components/GridTitle.svelte +0 -1
- package/src/routes/components/ListTitle.svelte +0 -1
- package/src/routes/components/Playlinks/AfterArticlePlaylinks.svelte +0 -1
- package/src/routes/components/Playlinks/PlaylinkIcon.svelte +0 -1
- package/src/routes/components/Playlinks/PlaylinkLabel.svelte +0 -1
- package/src/routes/components/PostersScrollReveal.svelte +3 -2
- package/src/routes/components/SkeletonText.svelte +1 -1
- package/src/routes/components/UserJourney.svelte +0 -2
- package/src/tests/lib/api/externalPages.test.js +10 -1
- package/src/tests/lib/trailer.test.js +1 -4
package/eslint.config.js
CHANGED
|
@@ -81,4 +81,26 @@ export default [
|
|
|
81
81
|
],
|
|
82
82
|
},
|
|
83
83
|
},
|
|
84
|
+
{
|
|
85
|
+
ignores: [],
|
|
86
|
+
|
|
87
|
+
plugins: {
|
|
88
|
+
prettier,
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
rules: {
|
|
92
|
+
'svelte/require-each-key': 'off',
|
|
93
|
+
'svelte/no-navigation-without-resolve': 'off',
|
|
94
|
+
'no-unused-vars': 'off',
|
|
95
|
+
'@typescript-eslint/no-unused-vars': [
|
|
96
|
+
'error',
|
|
97
|
+
{
|
|
98
|
+
vars: 'all',
|
|
99
|
+
args: 'after-used',
|
|
100
|
+
ignoreRestSiblings: true,
|
|
101
|
+
argsIgnorePattern: '^_',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
84
106
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playpilot/tpi",
|
|
3
|
-
"version": "6.5.
|
|
3
|
+
"version": "6.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@typescript-eslint/parser": "^8.32.1",
|
|
25
25
|
"eslint": "^9.27.0",
|
|
26
26
|
"eslint-config-prettier": "^9.1.0",
|
|
27
|
-
"eslint-plugin-svelte": "^
|
|
27
|
+
"eslint-plugin-svelte": "^3.15.0",
|
|
28
28
|
"globals": "^15.0.0",
|
|
29
29
|
"happy-dom": "^16.5.3",
|
|
30
30
|
"prettier": "^3.3.2",
|
package/src/lib/api/api.ts
CHANGED
|
@@ -21,6 +21,7 @@ export async function api<T>(path: string, { headers = {}, method = 'GET', body
|
|
|
21
21
|
const response = await fetch(apiBaseUrl + path, {
|
|
22
22
|
method,
|
|
23
23
|
headers: new Headers({ ...baseHeaders, ...headers }),
|
|
24
|
+
// eslint-disable-next-line no-undef
|
|
24
25
|
body: body ? JSON.stringify(body as BodyInit) : null,
|
|
25
26
|
})
|
|
26
27
|
|
|
@@ -129,6 +129,7 @@ export async function runAiBasedOnResponse(pageText: string, response: LinkInjec
|
|
|
129
129
|
const isCurrentTimeEqualToResponseTime = currentModifiedTime && responseModifiedTime === currentModifiedTime
|
|
130
130
|
|
|
131
131
|
if (response.ai_last_run && isCurrentTimeEqualToResponseTime) return response
|
|
132
|
+
if (new Date(currentModifiedTime || 0) <= new Date(responseModifiedTime || 0)) return response
|
|
132
133
|
|
|
133
134
|
return await fetchLinkInjections(pageText, { params: { run_ai: true } })
|
|
134
135
|
}
|
package/src/lib/clipboard.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
export function copyToClipboard(text: string): void {
|
|
2
|
-
const textarea = document.createElement(
|
|
2
|
+
const textarea = document.createElement('textarea')
|
|
3
3
|
|
|
4
4
|
textarea.value = text
|
|
5
|
-
textarea.style.position =
|
|
6
|
-
textarea.style.left =
|
|
5
|
+
textarea.style.position = 'fixed'
|
|
6
|
+
textarea.style.left = '-9999px'
|
|
7
7
|
|
|
8
8
|
document.body.appendChild(textarea)
|
|
9
9
|
|
|
10
10
|
textarea.select()
|
|
11
11
|
|
|
12
|
-
document.execCommand(
|
|
12
|
+
document.execCommand('copy')
|
|
13
13
|
document.body.removeChild(textarea)
|
|
14
14
|
}
|
package/src/lib/modal.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { mount, unmount } from
|
|
2
|
-
import { isHoldingSpecialKey } from
|
|
3
|
-
import type { LinkInjection } from
|
|
4
|
-
import type { TitleData } from
|
|
5
|
-
import type { ParticipantData } from
|
|
6
|
-
import { mobileBreakpoint } from
|
|
7
|
-
import TitleModal from
|
|
8
|
-
import ParticipantModal from
|
|
9
|
-
import ExploreModal from
|
|
10
|
-
import { getPlayPilotWrapperElement, keyDataAttribute, keySelector } from
|
|
11
|
-
import { playFallbackViewTransition } from
|
|
12
|
-
import { destroyLinkPopover } from
|
|
13
|
-
import { prefersReducedMotion } from
|
|
1
|
+
import { mount, unmount } from 'svelte'
|
|
2
|
+
import { isHoldingSpecialKey } from './event'
|
|
3
|
+
import type { LinkInjection } from './types/injection'
|
|
4
|
+
import type { TitleData } from './types/title'
|
|
5
|
+
import type { ParticipantData } from './types/participant'
|
|
6
|
+
import { mobileBreakpoint } from './constants'
|
|
7
|
+
import TitleModal from '../routes/components/TitleModal.svelte'
|
|
8
|
+
import ParticipantModal from '../routes/components/ParticipantModal.svelte'
|
|
9
|
+
import ExploreModal from '../routes/components/Explore/ExploreModal.svelte'
|
|
10
|
+
import { getPlayPilotWrapperElement, keyDataAttribute, keySelector } from './injection'
|
|
11
|
+
import { playFallbackViewTransition } from './viewTransition'
|
|
12
|
+
import { destroyLinkPopover } from './popover'
|
|
13
|
+
import { prefersReducedMotion } from 'svelte/motion'
|
|
14
14
|
|
|
15
15
|
type ModalType = 'title' | 'participant' | 'explore'
|
|
16
16
|
|
|
@@ -49,13 +49,13 @@ export function openModal(
|
|
|
49
49
|
addModalToList({ type, injection, data, scrollPosition, component })
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
function getModalComponentByType({ type = 'title', target, data, props = {} }: { type: ModalType, target: Element, data: TitleData | ParticipantData | null, props?: Record<string, any> }) {
|
|
52
|
+
function getModalComponentByType({ type = 'title', target, data, props = {} }: { type: ModalType, target: Element, data: TitleData | ParticipantData | null, props?: Record<string, any> }): ReturnType<typeof mount> {
|
|
53
53
|
if (type === 'participant') return mount(ParticipantModal, { target, props: { participant: data as ParticipantData, ...props } })
|
|
54
54
|
if (type === 'explore') return mount(ExploreModal, { target, props: { ...props } })
|
|
55
55
|
return mount(TitleModal, { target, props: { title: data as TitleData, ...props } })
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function addModalToList({ type = 'title', injection = null, data, scrollPosition = 0, component }: Modal) {
|
|
58
|
+
function addModalToList({ type = 'title', injection = null, data, scrollPosition = 0, component }: Modal): void {
|
|
59
59
|
modals.push({ type, injection, data, scrollPosition, component })
|
|
60
60
|
}
|
|
61
61
|
|
package/src/lib/popover.ts
CHANGED
|
@@ -27,7 +27,7 @@ export function openPopoverForInjectedLink(event: MouseEvent, injection: LinkInj
|
|
|
27
27
|
}, 100)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export async function destroyLinkPopover(outro: boolean = true) {
|
|
30
|
+
export async function destroyLinkPopover(outro: boolean = true): Promise<void> {
|
|
31
31
|
if (activePopoverInsertedComponent) {
|
|
32
32
|
const promise = unmount(activePopoverInsertedComponent, { outro })
|
|
33
33
|
|
|
@@ -59,10 +59,10 @@ export function destroyLinkPopoverOnMouseleave(event: MouseEvent): void {
|
|
|
59
59
|
destroyLinkPopover()
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
export function clearCurrentlyHoveredInjection() {
|
|
62
|
+
export function clearCurrentlyHoveredInjection(): void {
|
|
63
63
|
currentlyHoveredInjection = null
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export function isPopoverActive() {
|
|
66
|
+
export function isPopoverActive(): boolean {
|
|
67
67
|
return !!activePopoverInsertedComponent
|
|
68
68
|
}
|
package/src/lib/routes.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { playPilotBaseUrl } from
|
|
2
|
-
import type { TitleData } from
|
|
1
|
+
import { playPilotBaseUrl } from './constants'
|
|
2
|
+
import type { TitleData } from './types/title'
|
|
3
3
|
|
|
4
4
|
export function titleUrl(title: TitleData): string {
|
|
5
5
|
return `${playPilotBaseUrl}/${title.type}/${title.slug}/`
|
package/src/lib/tracking.ts
CHANGED
|
@@ -36,6 +36,7 @@ export async function track(event: string, title: TitleData | null = null, paylo
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
// eslint-disable-next-line no-undef
|
|
39
40
|
payload.version = __SCRIPT_VERSION__
|
|
40
41
|
payload.url = getFullUrlPath()
|
|
41
42
|
payload.organization_sid = window.PlayPilotLinkInjections?.organization_sid || 'undefined'
|
package/src/lib/trailer.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { mount, unmount } from
|
|
2
|
-
import { getPlayPilotWrapperElement } from
|
|
3
|
-
import type { TitleData } from
|
|
4
|
-
import YouTubeEmbedOverlay from
|
|
1
|
+
import { mount, unmount } from 'svelte'
|
|
2
|
+
import { getPlayPilotWrapperElement } from './injection'
|
|
3
|
+
import type { TitleData } from './types/title'
|
|
4
|
+
import YouTubeEmbedOverlay from '../routes/components/YouTubeEmbedOverlay.svelte'
|
|
5
5
|
|
|
6
6
|
let currentTrailerComponent: object | null = {}
|
|
7
7
|
|
|
8
|
-
export function openTrailerOverlay(title: TitleData) {
|
|
8
|
+
export function openTrailerOverlay(title: TitleData): void {
|
|
9
9
|
const target = getPlayPilotWrapperElement()
|
|
10
10
|
const props = { onclose: closeTrailerOverlay, embeddable_url: title.embeddable_url || '' }
|
|
11
11
|
|
package/src/main.ts
CHANGED
|
@@ -42,6 +42,7 @@ window.PlayPilotLinkInjections = {
|
|
|
42
42
|
this.editorial_token = options.editorial_token
|
|
43
43
|
this.selector = options.selector
|
|
44
44
|
this.after_article_selector = options.after_article_selector
|
|
45
|
+
// eslint-disable-next-line no-undef
|
|
45
46
|
this.after_article_insert_position = options.after_article_insert_position as InsertPosition
|
|
46
47
|
this.language = options.language
|
|
47
48
|
this.region = options.region
|
|
@@ -7,8 +7,7 @@
|
|
|
7
7
|
import Range from './Range.svelte'
|
|
8
8
|
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
9
9
|
import { track } from '$lib/tracking'
|
|
10
|
-
import {
|
|
11
|
-
import { t } from '$lib/localization';
|
|
10
|
+
import { t } from '$lib/localization'
|
|
12
11
|
|
|
13
12
|
type Item = { label: string, value: string }
|
|
14
13
|
|
|
@@ -31,7 +30,7 @@
|
|
|
31
30
|
data = null,
|
|
32
31
|
fetchData = null,
|
|
33
32
|
range = null,
|
|
34
|
-
valueAppend = ''
|
|
33
|
+
valueAppend = '',
|
|
35
34
|
}: Props = $props()
|
|
36
35
|
|
|
37
36
|
const active = $derived.by(() => {
|
|
@@ -97,7 +96,7 @@
|
|
|
97
96
|
{@const selected = filter[param]?.value as string[] | undefined}
|
|
98
97
|
<TogglesWithSearch options={data} {selected} onchange={(selected) => setFilter(selected, 'array')} />
|
|
99
98
|
{:else if range}
|
|
100
|
-
{@const value =
|
|
99
|
+
{@const value = filter[param]?.value as unknown as [number, number]}
|
|
101
100
|
<Range {range} {value} label={label} {valueAppend} onchange={(value) => setFilter(value, 'range')} />
|
|
102
101
|
{/if}
|
|
103
102
|
</div>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { mobileBreakpoint } from '$lib/constants'
|
|
3
3
|
import { onDestroy } from 'svelte'
|
|
4
|
+
import { SvelteSet } from 'svelte/reactivity'
|
|
4
5
|
|
|
5
6
|
const linksWithPosters = Array.from(document.querySelectorAll<HTMLElement>('[data-playpilot-poster-url]'))
|
|
6
|
-
const linksWithCurrentlyVisiblePosters = new
|
|
7
|
+
const linksWithCurrentlyVisiblePosters = new SvelteSet<HTMLElement>()
|
|
7
8
|
const targetThreshold = 0.7
|
|
8
9
|
const posterSelector = '[data-playpilot-poster]'
|
|
9
10
|
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
setScrollTimeout()
|
|
22
23
|
|
|
23
24
|
const windowHeight = window.innerHeight
|
|
24
|
-
const linksWithinTargetViewport = new
|
|
25
|
+
const linksWithinTargetViewport = new SvelteSet<HTMLElement>()
|
|
25
26
|
const targetFromBottom = windowHeight * targetThreshold
|
|
26
27
|
const targetFromTop = windowHeight - targetFromBottom
|
|
27
28
|
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { isEditorialModeEnabled } from '$lib/api/auth'
|
|
3
|
-
import { SplitTest } from '$lib/enums/SplitTest'
|
|
4
3
|
import { TrackingEvent } from '$lib/enums/TrackingEvent'
|
|
5
4
|
import { keyDataAttribute, keySelector } from '$lib/injection'
|
|
6
|
-
import { getSplitTestVariantName } from '$lib/splitTest'
|
|
7
5
|
import { track } from '$lib/tracking'
|
|
8
6
|
import { onMount } from 'svelte'
|
|
9
7
|
|
|
@@ -290,7 +290,7 @@ describe('$lib/api/externalPages', () => {
|
|
|
290
290
|
expect(result).toEqual(response)
|
|
291
291
|
})
|
|
292
292
|
|
|
293
|
-
it('Should call api if ai_enabled is true and content_modified_time does not match document time, but no pageText is given', async () => {
|
|
293
|
+
it('Should not call api if ai_enabled is true and content_modified_time does not match document time, but no pageText is given', async () => {
|
|
294
294
|
document.body.innerHTML = '<meta content="2025-04-20T00:00:00Z" property="article:modified_time">'
|
|
295
295
|
const response = { ai_enabled: true, content_modified_time: '2025-01-01T00:00:00Z' }
|
|
296
296
|
|
|
@@ -308,6 +308,15 @@ describe('$lib/api/externalPages', () => {
|
|
|
308
308
|
expect(api).not.toHaveBeenCalledTimes(1)
|
|
309
309
|
})
|
|
310
310
|
|
|
311
|
+
it('Should not call api if ai_enabled is true but response content_modified_time is before document time', async () => {
|
|
312
|
+
document.body.innerHTML = '<meta content="2020-04-20T00:00:00Z" property="article:modified_time">'
|
|
313
|
+
const response = { ai_enabled: true, content_modified_time: '2025-01-01T00:00:00Z' }
|
|
314
|
+
|
|
315
|
+
// @ts-ignore
|
|
316
|
+
await runAiBasedOnResponse('Some text', response)
|
|
317
|
+
expect(api).not.toHaveBeenCalled()
|
|
318
|
+
})
|
|
319
|
+
|
|
311
320
|
it('Should call api if ai_enabled is true and ai_last_run is null, regardless of content_modified_time', async () => {
|
|
312
321
|
const response = { ai_enabled: true, ai_last_run: null }
|
|
313
322
|
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
2
|
-
import {
|
|
3
|
-
import { linkInjections, title } from '$lib/fakeData'
|
|
2
|
+
import { title } from '$lib/fakeData'
|
|
4
3
|
import { mount, unmount } from 'svelte'
|
|
5
|
-
import ParticipantModal from '../../routes/components/ParticipantModal.svelte'
|
|
6
|
-
import TitleModal from '../../routes/components/TitleModal.svelte'
|
|
7
4
|
import { closeTrailerOverlay, openTrailerOverlay } from '$lib/trailer'
|
|
8
5
|
|
|
9
6
|
vi.mock('svelte', () => ({
|