@adobe/spacecat-shared-tokowaka-client 1.7.7 → 1.8.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/.releaserc.cjs +6 -2
- package/CHANGELOG.md +13 -0
- package/package.json +3 -1
- package/src/index.js +12 -2
- package/src/mappers/mapper-registry.js +2 -1
- package/src/mappers/semantic-value-visibility-mapper.js +103 -0
- package/src/utils/html-utils.js +22 -0
- package/test/fixtures/semantic-value-visibility/Carahsoft.json +202 -0
- package/test/fixtures/semantic-value-visibility/Koffievoordeel.json +112 -0
- package/test/fixtures/semantic-value-visibility/Krisshop.json +957 -0
- package/test/fixtures/semantic-value-visibility/Veseris.json +555 -0
- package/test/fixtures/semantic-value-visibility/Vuse.json +684 -0
- package/test/index.test.js +110 -55
- package/test/mappers/semantic-value-visibility-mapper.test.js +332 -0
- package/test/utils/htmlToHast.test.js +88 -0
package/.releaserc.cjs
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
extends: "semantic-release-monorepo",
|
|
3
3
|
plugins: [
|
|
4
|
-
"@semantic-release/commit-analyzer",
|
|
5
|
-
|
|
4
|
+
["@semantic-release/commit-analyzer", {
|
|
5
|
+
"preset": "conventionalcommits",
|
|
6
|
+
}],
|
|
7
|
+
["@semantic-release/release-notes-generator", {
|
|
8
|
+
"preset": "conventionalcommits",
|
|
9
|
+
}],
|
|
6
10
|
["@semantic-release/changelog", {
|
|
7
11
|
"changelogFile": "CHANGELOG.md",
|
|
8
12
|
}],
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## [@adobe/spacecat-shared-tokowaka-client-v1.8.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.7.8...@adobe/spacecat-shared-tokowaka-client-v1.8.0) (2026-02-18)
|
|
2
|
+
|
|
3
|
+
### Features
|
|
4
|
+
|
|
5
|
+
* **tokowaka-client:** add semantic-value-visibility mapper ([#1348](https://github.com/adobe/spacecat-shared/issues/1348)) ([373f920](https://github.com/adobe/spacecat-shared/commit/373f920dfa9d5da8f2e15e0533d1347a23f45044))
|
|
6
|
+
|
|
7
|
+
# [@adobe/spacecat-shared-tokowaka-client-v1.7.8](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.7.7...@adobe/spacecat-shared-tokowaka-client-v1.7.8) (2026-02-16)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Bug Fixes
|
|
11
|
+
|
|
12
|
+
* timeout added for edge optimize status ([#1329](https://github.com/adobe/spacecat-shared/issues/1329)) ([93ef065](https://github.com/adobe/spacecat-shared/commit/93ef0653840929e9c76b14d370dbfa6db03cb97e))
|
|
13
|
+
|
|
1
14
|
# [@adobe/spacecat-shared-tokowaka-client-v1.7.7](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-tokowaka-client-v1.7.6...@adobe/spacecat-shared-tokowaka-client-v1.7.7) (2026-02-12)
|
|
2
15
|
|
|
3
16
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/spacecat-shared-tokowaka-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Tokowaka Client for SpaceCat - Edge optimization config management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"@adobe/spacecat-shared-utils": "1.81.1",
|
|
38
38
|
"@aws-sdk/client-cloudfront": "3.940.0",
|
|
39
39
|
"@aws-sdk/client-s3": "3.940.0",
|
|
40
|
+
"hast-util-from-html": "2.0.3",
|
|
40
41
|
"mdast-util-from-markdown": "2.0.2",
|
|
41
42
|
"mdast-util-to-hast": "13.2.1",
|
|
42
43
|
"uuid": "11.0.5"
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"c8": "^10.1.3",
|
|
47
48
|
"chai": "^6.0.1",
|
|
48
49
|
"eslint": "^9.36.0",
|
|
50
|
+
"esmock": "^2.7.3",
|
|
49
51
|
"mocha": "^11.7.2",
|
|
50
52
|
"nock": "^14.0.10",
|
|
51
53
|
"sinon": "^21.0.0",
|
package/src/index.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import crypto from 'crypto';
|
|
14
14
|
import { GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
|
|
15
|
-
import { hasText, isNonEmptyObject } from '@adobe/spacecat-shared-utils';
|
|
15
|
+
import { hasText, isNonEmptyObject, tracingFetch } from '@adobe/spacecat-shared-utils';
|
|
16
16
|
import { v4 as uuidv4 } from 'uuid';
|
|
17
17
|
import MapperRegistry from './mappers/mapper-registry.js';
|
|
18
18
|
import CdnClientRegistry from './cdn/cdn-client-registry.js';
|
|
@@ -1072,17 +1072,20 @@ class TokowakaClient {
|
|
|
1072
1072
|
const maxRetries = 3;
|
|
1073
1073
|
let attempt = 0;
|
|
1074
1074
|
|
|
1075
|
+
const REQUEST_TIMEOUT_MS = 5000;
|
|
1076
|
+
|
|
1075
1077
|
while (attempt <= maxRetries) {
|
|
1076
1078
|
try {
|
|
1077
1079
|
this.log.debug(`Attempt ${attempt + 1}/${maxRetries + 1}: Checking edge optimize status for ${targetUrl}`);
|
|
1078
1080
|
|
|
1079
1081
|
// eslint-disable-next-line no-await-in-loop
|
|
1080
|
-
const response = await
|
|
1082
|
+
const response = await tracingFetch(targetUrl, {
|
|
1081
1083
|
method: 'GET',
|
|
1082
1084
|
headers: {
|
|
1083
1085
|
'User-Agent': 'Tokowaka-AI Tokowaka/1.0 AdobeEdgeOptimize-AI AdobeEdgeOptimize/1.0',
|
|
1084
1086
|
'fastly-debug': '1',
|
|
1085
1087
|
},
|
|
1088
|
+
timeout: REQUEST_TIMEOUT_MS,
|
|
1086
1089
|
});
|
|
1087
1090
|
|
|
1088
1091
|
this.log.debug(`Response status: ${response.status}`);
|
|
@@ -1096,6 +1099,13 @@ class TokowakaClient {
|
|
|
1096
1099
|
edgeOptimizeEnabled,
|
|
1097
1100
|
};
|
|
1098
1101
|
} catch (error) {
|
|
1102
|
+
const isTimeout = error?.code === 'ETIMEOUT';
|
|
1103
|
+
|
|
1104
|
+
if (isTimeout) {
|
|
1105
|
+
this.log.warn(`Request timed out after ${REQUEST_TIMEOUT_MS}ms for ${targetUrl}, returning edgeOptimizeEnabled: false`);
|
|
1106
|
+
return { edgeOptimizeEnabled: false };
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1099
1109
|
attempt += 1;
|
|
1100
1110
|
|
|
1101
1111
|
if (attempt > maxRetries) {
|
|
@@ -17,6 +17,7 @@ import ReadabilityMapper from './readability-mapper.js';
|
|
|
17
17
|
import TocMapper from './toc-mapper.js';
|
|
18
18
|
import GenericMapper from './generic-mapper.js';
|
|
19
19
|
import PrerenderMapper from './prerender-mapper.js';
|
|
20
|
+
import SemanticValueVisibilityMapper from './semantic-value-visibility-mapper.js';
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Registry for opportunity mappers
|
|
@@ -42,7 +43,7 @@ export default class MapperRegistry {
|
|
|
42
43
|
TocMapper,
|
|
43
44
|
GenericMapper,
|
|
44
45
|
PrerenderMapper,
|
|
45
|
-
|
|
46
|
+
SemanticValueVisibilityMapper,
|
|
46
47
|
];
|
|
47
48
|
|
|
48
49
|
defaultMappers.forEach((MapperClass) => {
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { hasText } from '@adobe/spacecat-shared-utils';
|
|
14
|
+
import { TARGET_USER_AGENTS_CATEGORIES } from '../constants.js';
|
|
15
|
+
import BaseOpportunityMapper from './base-mapper.js';
|
|
16
|
+
import { htmlToHast } from '../utils/html-utils.js';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Mapper for semantic-value-visibility opportunity
|
|
20
|
+
* Handles conversion of image semantic HTML suggestions to Tokowaka patches
|
|
21
|
+
*/
|
|
22
|
+
export default class SemanticValueVisibilityMapper extends BaseOpportunityMapper {
|
|
23
|
+
constructor(log) {
|
|
24
|
+
super(log);
|
|
25
|
+
this.opportunityType = 'semantic-value-visibility';
|
|
26
|
+
this.prerenderRequired = true;
|
|
27
|
+
this.validActions = ['insertAfter', 'insertBefore', 'appendChild'];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
getOpportunityType() {
|
|
31
|
+
return this.opportunityType;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
requiresPrerender() {
|
|
35
|
+
return this.prerenderRequired;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Converts suggestions to Tokowaka patches
|
|
40
|
+
* @param {string} urlPath - URL path for the suggestions
|
|
41
|
+
* @param {Array} suggestions - Array of suggestion entities for the same URL
|
|
42
|
+
* @param {string} opportunityId - Opportunity ID
|
|
43
|
+
* @returns {Array} - Array of Tokowaka patch objects
|
|
44
|
+
*/
|
|
45
|
+
suggestionsToPatches(urlPath, suggestions, opportunityId) {
|
|
46
|
+
const patches = [];
|
|
47
|
+
|
|
48
|
+
suggestions.forEach((suggestion) => {
|
|
49
|
+
const eligibility = this.canDeploy(suggestion);
|
|
50
|
+
if (!eligibility.eligible) {
|
|
51
|
+
this.log.warn(`Semantic-value-visibility suggestion ${suggestion.getId()} cannot be deployed: ${eligibility.reason}`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const data = suggestion.getData();
|
|
56
|
+
const { semanticHtml, transformRules } = data;
|
|
57
|
+
|
|
58
|
+
// Convert HTML to HAST
|
|
59
|
+
const hastValue = htmlToHast(semanticHtml);
|
|
60
|
+
|
|
61
|
+
const patch = {
|
|
62
|
+
...this.createBasePatch(suggestion, opportunityId),
|
|
63
|
+
op: transformRules.action,
|
|
64
|
+
selector: transformRules.selector,
|
|
65
|
+
value: hastValue,
|
|
66
|
+
valueFormat: 'hast',
|
|
67
|
+
target: TARGET_USER_AGENTS_CATEGORIES.AI_BOTS,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
patches.push(patch);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return patches;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Checks if a semantic-value-visibility suggestion can be deployed
|
|
78
|
+
* @param {Object} suggestion - Suggestion object
|
|
79
|
+
* @returns {Object} { eligible: boolean, reason?: string }
|
|
80
|
+
*/
|
|
81
|
+
canDeploy(suggestion) {
|
|
82
|
+
const data = suggestion.getData();
|
|
83
|
+
|
|
84
|
+
// Validate required fields
|
|
85
|
+
if (!hasText(data?.semanticHtml)) {
|
|
86
|
+
return { eligible: false, reason: 'semanticHtml is required' };
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (!data.transformRules) {
|
|
90
|
+
return { eligible: false, reason: 'transformRules is required' };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!hasText(data.transformRules.selector)) {
|
|
94
|
+
return { eligible: false, reason: 'transformRules.selector is required' };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!this.validActions.includes(data.transformRules.action)) {
|
|
98
|
+
return { eligible: false, reason: `transformRules.action must be one of: ${this.validActions.join(', ')}` };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return { eligible: true };
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Adobe. All rights reserved.
|
|
3
|
+
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License. You may obtain a copy
|
|
5
|
+
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
*
|
|
7
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
8
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
9
|
+
* OF ANY KIND, either express or implied. See the License for the specific language
|
|
10
|
+
* governing permissions and limitations under the License.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { fromHtml } from 'hast-util-from-html';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Converts HTML string to HAST (Hypertext Abstract Syntax Tree) format
|
|
17
|
+
* @param {string} html - HTML string
|
|
18
|
+
* @returns {Object} - HAST object
|
|
19
|
+
*/
|
|
20
|
+
export function htmlToHast(html) {
|
|
21
|
+
return fromHtml(html, { fragment: true });
|
|
22
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
{
|
|
2
|
+
"url": "https://carahsoft.com/",
|
|
3
|
+
"opportunityType": "semantic-value-visibility",
|
|
4
|
+
"suggestions": [
|
|
5
|
+
{
|
|
6
|
+
"data": {
|
|
7
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/6617/6522/3539/WEST-2026_Homepage-Banner-Updated.jpg",
|
|
8
|
+
"urlAttribute": "src",
|
|
9
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/6617/6522/3539/WEST-2026_Homepage-Banner-Updated.jpg\">\n <span>carahsoft</span>\n <h2>Carahsoft and Partners at WEST 2026</h2>\n <span>February 10 - 12, 2026 \u2022 San Diego, CA</span>\n <button>Learn More</button>\n</section>",
|
|
10
|
+
"detectedText": [
|
|
11
|
+
"carahsoft ",
|
|
12
|
+
"Carahsoft and Partners",
|
|
13
|
+
"at WEST 2026",
|
|
14
|
+
"February 10",
|
|
15
|
+
"12, 2026",
|
|
16
|
+
"San Diego, CA",
|
|
17
|
+
"Learn More "
|
|
18
|
+
],
|
|
19
|
+
"transformRules": {
|
|
20
|
+
"action": "insertAfter",
|
|
21
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/6617/6522/3539/WEST-2026_Homepage-Banner-Updated.jpg\"]"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"data": {
|
|
27
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/2317/6979/1365/Carahsoft_GovExec_GovExperience_Summit_2026_1140x325.jpg",
|
|
28
|
+
"urlAttribute": "src",
|
|
29
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/2317/6979/1365/Carahsoft_GovExec_GovExperience_Summit_2026_1140x325.jpg\">\n <span>carahsoft</span>\n <span>GovExec</span>\n <h2>GovExperience SUMMIT</h2>\n <p>Advancing Government Service Delivery & CX</p>\n <button>Register Now</button>\n <span>June 2, 2026</span>\n <span>Reston, VA</span>\n</section>",
|
|
30
|
+
"detectedText": [
|
|
31
|
+
"carahsoft",
|
|
32
|
+
"powered by",
|
|
33
|
+
"GovExec",
|
|
34
|
+
"Gov Experience",
|
|
35
|
+
"SUMMIT",
|
|
36
|
+
"Advancing Government",
|
|
37
|
+
"Service Delivery & CX",
|
|
38
|
+
"Register Now",
|
|
39
|
+
"June 2,2026",
|
|
40
|
+
"Reston; VA"
|
|
41
|
+
],
|
|
42
|
+
"transformRules": {
|
|
43
|
+
"action": "insertAfter",
|
|
44
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/2317/6979/1365/Carahsoft_GovExec_GovExperience_Summit_2026_1140x325.jpg\"]"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"data": {
|
|
50
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/1417/7022/0984/OneGov-Graphics-2026-Homepage-Banner.jpg",
|
|
51
|
+
"urlAttribute": "src",
|
|
52
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/1417/7022/0984/OneGov-Graphics-2026-Homepage-Banner.jpg\">\n <span>OneGov Offerings Available Now</span>\n <h2>Cost-Saving Technology Solutions for Government</h2>\n <button>View Special Offers</button>\n <span>carahsoft</span>\n</section>",
|
|
53
|
+
"detectedText": [
|
|
54
|
+
"OneGov",
|
|
55
|
+
"Offerings Available Now",
|
|
56
|
+
"Cost-Saving Technology",
|
|
57
|
+
"Solutions for Government",
|
|
58
|
+
"View Special Offers",
|
|
59
|
+
"carahsoft"
|
|
60
|
+
],
|
|
61
|
+
"transformRules": {
|
|
62
|
+
"action": "insertAfter",
|
|
63
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/1417/7022/0984/OneGov-Graphics-2026-Homepage-Banner.jpg\"]"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"data": {
|
|
69
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/6017/3990/9507/SGT-Home-page-Banner.jpg",
|
|
70
|
+
"urlAttribute": "src",
|
|
71
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/6017/3990/9507/SGT-Home-page-Banner.jpg\">\n <span>carahsoft.</span>\n <h2>Explore all our Self-Guided Tours for Government</h2>\n <button>Tour Our Solutions</button>\n</section>",
|
|
72
|
+
"detectedText": [
|
|
73
|
+
"carahsoft",
|
|
74
|
+
"Explore all our Self-Guided",
|
|
75
|
+
"Tours for Government",
|
|
76
|
+
"Tour Our Solutions"
|
|
77
|
+
],
|
|
78
|
+
"transformRules": {
|
|
79
|
+
"action": "insertAfter",
|
|
80
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/6017/3990/9507/SGT-Home-page-Banner.jpg\"]"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"data": {
|
|
86
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/1517/4076/7653/Buyers-Guide-Hub-Banners_Homepage-Banner.jpg",
|
|
87
|
+
"urlAttribute": "src",
|
|
88
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/1517/4076/7653/Buyers-Guide-Hub-Banners_Homepage-Banner.jpg\">\n <span>carahsoft</span>\n <h2>Explore Carahsoft\u2019s Buyer\u2019s Guides for Government</h2>\n <button>View our Buyer\u2019s Guides</button>\n</section>",
|
|
89
|
+
"detectedText": [
|
|
90
|
+
"carahsoft",
|
|
91
|
+
"40",
|
|
92
|
+
"Explore Carahsoft'$ Buyer's Guides",
|
|
93
|
+
"for Government",
|
|
94
|
+
"View our Buyer's Guides",
|
|
95
|
+
"Govet",
|
|
96
|
+
"OSINT"
|
|
97
|
+
],
|
|
98
|
+
"transformRules": {
|
|
99
|
+
"action": "insertAfter",
|
|
100
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/1517/4076/7653/Buyers-Guide-Hub-Banners_Homepage-Banner.jpg\"]"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"data": {
|
|
106
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/6117/6997/1583/SF-AppExchange-Self-Guided-Tour--home-page.jpg",
|
|
107
|
+
"urlAttribute": "src",
|
|
108
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/6117/6997/1583/SF-AppExchange-Self-Guided-Tour--home-page.jpg\">\n <span>carahsoft</span>\n <h2>Explore Our Salesforce AppExchange Self-Guided Tours</h2>\n <button>Discover Public Sector Solutions</button>\n</section>",
|
|
109
|
+
"detectedText": [
|
|
110
|
+
"carahsoft",
|
|
111
|
+
"Explore Our Salesforce",
|
|
112
|
+
"AppExchange Self-Guided Tours",
|
|
113
|
+
"Discover Public Sector Solutions"
|
|
114
|
+
],
|
|
115
|
+
"transformRules": {
|
|
116
|
+
"action": "insertAfter",
|
|
117
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/6117/6997/1583/SF-AppExchange-Self-Guided-Tour--home-page.jpg\"]"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"data": {
|
|
123
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/1617/6997/1435/Carahsoft-Public-Sector-Partners.jpg",
|
|
124
|
+
"urlAttribute": "src",
|
|
125
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/1617/6997/1435/Carahsoft-Public-Sector-Partners.jpg\">\n <span>carahsoft</span>\n <h2>Explore Our Salesforce Partner Program Self-Guided Tours</h2>\n <button>Discover Public Sector Solutions</button>\n</section>",
|
|
126
|
+
"detectedText": [
|
|
127
|
+
"carahsoft",
|
|
128
|
+
"Explore Our Salesforce",
|
|
129
|
+
"Partner Program Self-Guided Tours",
|
|
130
|
+
"Discover Public Sector Solutions"
|
|
131
|
+
],
|
|
132
|
+
"transformRules": {
|
|
133
|
+
"action": "insertAfter",
|
|
134
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/1617/6997/1435/Carahsoft-Public-Sector-Partners.jpg\"]"
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"data": {
|
|
140
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/6317/4480/9746/NextGovFCW_IIG_Report_April_The_Essential_Elements_of_IT_Modernization_homepage.jpg",
|
|
141
|
+
"urlAttribute": "src",
|
|
142
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/6317/4480/9746/NextGovFCW_IIG_Report_April_The_Essential_Elements_of_IT_Modernization_homepage.jpg\">\n <span>Innovation in Government</span>\n <span>carahsoft</span>\n <h2>The Essential Elements of</h2>\n <span>IN PARTNERSHIP WITH:</span>\n <span>Dell Technologies</span>\n <button>READ THE REPORT HERE</button>\n</section>",
|
|
143
|
+
"detectedText": [
|
|
144
|
+
"Innovation",
|
|
145
|
+
"in Government",
|
|
146
|
+
"carahsoft",
|
|
147
|
+
"The Essential Elements of",
|
|
148
|
+
"IN PARTNERSHIP WITH:",
|
|
149
|
+
"DALTechnologies",
|
|
150
|
+
"READ THE REPORT HERE"
|
|
151
|
+
],
|
|
152
|
+
"transformRules": {
|
|
153
|
+
"action": "insertAfter",
|
|
154
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/6317/4480/9746/NextGovFCW_IIG_Report_April_The_Essential_Elements_of_IT_Modernization_homepage.jpg\"]"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"data": {
|
|
160
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/4217/4481/0167/FCW_Sept_Oct_homepage.jpg",
|
|
161
|
+
"urlAttribute": "src",
|
|
162
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/4217/4481/0167/FCW_Sept_Oct_homepage.jpg\">\n <span>INNOVATION IN GOVERNMENT</span>\n <span>NEXTGOV FCW</span>\n <h2>Delving Deeper into Open-Source Intelligence</h2>\n <button>READ THE REPORT HERE</button>\n</section>",
|
|
163
|
+
"detectedText": [
|
|
164
|
+
"INNOVATION IN GOVERNMENT",
|
|
165
|
+
"NEXTCOVI",
|
|
166
|
+
"FCW",
|
|
167
|
+
"Delving Deeper into",
|
|
168
|
+
"Open-Source Intelligence",
|
|
169
|
+
"READ THE REPORT HERE"
|
|
170
|
+
],
|
|
171
|
+
"transformRules": {
|
|
172
|
+
"action": "insertAfter",
|
|
173
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/4217/4481/0167/FCW_Sept_Oct_homepage.jpg\"]"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"data": {
|
|
179
|
+
"imageUrl": "https://static.carahsoft.com/concrete/files/7017/4481/0098/FCW_AI_homepage.jpg",
|
|
180
|
+
"urlAttribute": "src",
|
|
181
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://static.carahsoft.com/concrete/files/7017/4481/0098/FCW_AI_homepage.jpg\">\n <span>Innovation in Government</span>\n <span>IN PARTNERSHIP WITH: carahsoft</span>\n <h2>COLLABORATING FOR</h2>\n <h2>Responsible AI in National Security</h2>\n <button>READ THE REPORT HERE</button>\n</section>",
|
|
182
|
+
"detectedText": [
|
|
183
|
+
"Innovation",
|
|
184
|
+
"IN PARTNERSHIP WITH: carahsoft",
|
|
185
|
+
"in Government\"",
|
|
186
|
+
"Responsible AI in",
|
|
187
|
+
"National Security",
|
|
188
|
+
"READ THE REPORT HERE"
|
|
189
|
+
],
|
|
190
|
+
"transformRules": {
|
|
191
|
+
"action": "insertAfter",
|
|
192
|
+
"selector": "img[src=\"https://static.carahsoft.com/concrete/files/7017/4481/0098/FCW_AI_homepage.jpg\"]"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"stats": {
|
|
198
|
+
"totalImages": 10,
|
|
199
|
+
"successfulSuggestions": 10,
|
|
200
|
+
"noGuidanceNeeded": 0
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"url": "https://koffievoordeel.nl/",
|
|
3
|
+
"opportunityType": "semantic-value-visibility",
|
|
4
|
+
"suggestions": [
|
|
5
|
+
{
|
|
6
|
+
"data": {
|
|
7
|
+
"imageUrl": "https://www.koffievoordeel.nl/media/wysiwyg/gmi_sample_doos_7-99_kvdnl_kvd_web_hero_desk.jpg?quality=85&fit=bounds",
|
|
8
|
+
"urlAttribute": "src",
|
|
9
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://www.koffievoordeel.nl/media/wysiwyg/gmi_sample_doos_7-99_kvdnl_kvd_web_hero_desk.jpg?quality=85&fit=bounds\">\n <span>Gran Maestro Italiano</span>\n <h2>Probeerpakket</h2>\n <span>Nu slechts 7,99</span>\n</section>",
|
|
10
|
+
"detectedText": [
|
|
11
|
+
"Gran Maestro Italiano",
|
|
12
|
+
"Probeerpakket",
|
|
13
|
+
"Nu slechts",
|
|
14
|
+
"99",
|
|
15
|
+
"GRAN",
|
|
16
|
+
"MAESTRO",
|
|
17
|
+
"tatiano"
|
|
18
|
+
],
|
|
19
|
+
"transformRules": {
|
|
20
|
+
"action": "insertAfter",
|
|
21
|
+
"selector": "img[src=\"https://www.koffievoordeel.nl/media/wysiwyg/gmi_sample_doos_7-99_kvdnl_kvd_web_hero_desk.jpg?quality=85&fit=bounds\"]"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"data": {
|
|
27
|
+
"imageUrl": "https://www.koffievoordeel.nl/media/wysiwyg/D6417_abonnementen_resfresh_web_hero_desk.jpg?quality=85&fit=bounds",
|
|
28
|
+
"urlAttribute": "src",
|
|
29
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://www.koffievoordeel.nl/media/wysiwyg/D6417_abonnementen_resfresh_web_hero_desk.jpg?quality=85&fit=bounds\">\n <h2>Koffie abonnementen</h2>\n <span>Tot 20% extra korting + gratis bezorging</span>\n <span>L\u2019OR</span>\n</section>",
|
|
30
|
+
"detectedText": [
|
|
31
|
+
"Koffie",
|
|
32
|
+
"abonnementen",
|
|
33
|
+
"DORO",
|
|
34
|
+
"ORC",
|
|
35
|
+
"gratis bezorging",
|
|
36
|
+
"illy"
|
|
37
|
+
],
|
|
38
|
+
"transformRules": {
|
|
39
|
+
"action": "insertAfter",
|
|
40
|
+
"selector": "img[src=\"https://www.koffievoordeel.nl/media/wysiwyg/D6417_abonnementen_resfresh_web_hero_desk.jpg?quality=85&fit=bounds\"]"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"data": {
|
|
46
|
+
"imageUrl": "https://www.koffievoordeel.nl/media/wysiwyg/D6360_voordeelpakketen_gmi_web_hero_desk_kvdnl_2.jpg?quality=85&fit=bounds",
|
|
47
|
+
"urlAttribute": "src",
|
|
48
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://www.koffievoordeel.nl/media/wysiwyg/D6360_voordeelpakketen_gmi_web_hero_desk_kvdnl_2.jpg?quality=85&fit=bounds\">\n <h2>Voordeelpakketten:</h2>\n <span>Nu n\u00f3g voordeliger!</span>\n <button>Extra voordeel</button>\n</section>",
|
|
49
|
+
"detectedText": [
|
|
50
|
+
"Voordeelpakketten:",
|
|
51
|
+
"Nu nog voordeliger!",
|
|
52
|
+
"voordeel",
|
|
53
|
+
"tatiano",
|
|
54
|
+
"aliano",
|
|
55
|
+
"00"
|
|
56
|
+
],
|
|
57
|
+
"transformRules": {
|
|
58
|
+
"action": "insertAfter",
|
|
59
|
+
"selector": "img[src=\"https://www.koffievoordeel.nl/media/wysiwyg/D6360_voordeelpakketen_gmi_web_hero_desk_kvdnl_2.jpg?quality=85&fit=bounds\"]"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"data": {
|
|
65
|
+
"imageUrl": "https://www.koffievoordeel.nl/media/wysiwyg/D6927_coffee_finder_winter_web_hero_desk_kvdxx_1.png?quality=85&fit=bounds",
|
|
66
|
+
"urlAttribute": "data-src",
|
|
67
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://www.koffievoordeel.nl/media/wysiwyg/D6927_coffee_finder_winter_web_hero_desk_kvdxx_1.png?quality=85&fit=bounds\">\n <h2>Coffee Finder</h2>\n <p>Voor hetzelfde geld betere koffie?</p>\n <button>Doe de test \u2192</button>\n</section>",
|
|
68
|
+
"detectedText": [
|
|
69
|
+
"Coffee",
|
|
70
|
+
"Finder",
|
|
71
|
+
"Voor hetzelfde geld",
|
|
72
|
+
"betere koffie?",
|
|
73
|
+
"Doe de test"
|
|
74
|
+
],
|
|
75
|
+
"transformRules": {
|
|
76
|
+
"action": "insertAfter",
|
|
77
|
+
"selector": "img[data-src=\"https://www.koffievoordeel.nl/media/wysiwyg/D6927_coffee_finder_winter_web_hero_desk_kvdxx_1.png?quality=85&fit=bounds\"]"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"data": {
|
|
83
|
+
"imageUrl": "https://www.koffievoordeel.nl/media/wysiwyg/kk_Algemeen_EB_KVDNL_kvd_web_hero_desk_7.jpg?quality=85&fit=bounds",
|
|
84
|
+
"urlAttribute": "data-src",
|
|
85
|
+
"semanticHtml": "<section data-llm-context=\"image\" data-llm-shadow=\"image-text\" data-image-id=\"https://www.koffievoordeel.nl/media/wysiwyg/kk_Algemeen_EB_KVDNL_kvd_web_hero_desk_7.jpg?quality=85&fit=bounds\">\n <h2>Deze week: \u20ac10 koffie</h2>\n <span>GRAN MAESTRO</span>\n <span>SLOW ROAST</span>\n <span>cadeaul</span>\n <span>ESPRESSO</span>\n <span>ORIGINALE</span>\n <span>DOKO</span>\n <span>Bean?</span>\n <span>CELESTE</span>\n</section>",
|
|
86
|
+
"detectedText": [
|
|
87
|
+
"Deze week:",
|
|
88
|
+
"\u20ac10 koffie",
|
|
89
|
+
"GRAN",
|
|
90
|
+
"MAESTRO",
|
|
91
|
+
"SLOW",
|
|
92
|
+
"ROAST",
|
|
93
|
+
"cadeaul",
|
|
94
|
+
"ESPRESSO",
|
|
95
|
+
"ORIGINALE",
|
|
96
|
+
"DOKO",
|
|
97
|
+
"Bean?",
|
|
98
|
+
"CELESTE"
|
|
99
|
+
],
|
|
100
|
+
"transformRules": {
|
|
101
|
+
"action": "insertAfter",
|
|
102
|
+
"selector": "img[data-src=\"https://www.koffievoordeel.nl/media/wysiwyg/kk_Algemeen_EB_KVDNL_kvd_web_hero_desk_7.jpg?quality=85&fit=bounds\"]"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"stats": {
|
|
108
|
+
"totalImages": 5,
|
|
109
|
+
"successfulSuggestions": 5,
|
|
110
|
+
"noGuidanceNeeded": 0
|
|
111
|
+
}
|
|
112
|
+
}
|