page-analyzer 1.2.0 → 1.2.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/README.md +2 -2
- package/package.json +1 -1
- package/page-extractor.js +3 -3
- package/result-viewer.html +25 -8
- package/scripts/build-result-viewer.js +25 -8
- package/test/smoke.test.js +4 -6
package/README.md
CHANGED
|
@@ -305,7 +305,7 @@ const result = await analyzeUrl('https://example.com', {
|
|
|
305
305
|
bucket: 'my-bucket',
|
|
306
306
|
region: 'ap-northeast-1',
|
|
307
307
|
prefix: 'page-analyzer/snapshots',
|
|
308
|
-
publicBaseUrl: 'https://cdn.example.com
|
|
308
|
+
publicBaseUrl: 'https://cdn.example.com',
|
|
309
309
|
credentials: {
|
|
310
310
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
311
311
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
|
@@ -316,7 +316,7 @@ const result = await analyzeUrl('https://example.com', {
|
|
|
316
316
|
});
|
|
317
317
|
```
|
|
318
318
|
|
|
319
|
-
`extractorConfig.s3.bucket` 和 `extractorConfig.s3.region` 必填。`credentials` 可省略,省略时使用 AWS SDK 默认凭证链。`publicBaseUrl` 可省略,省略时返回 `https://<bucket>.s3.<region>.amazonaws.com/<key>`。
|
|
319
|
+
`extractorConfig.s3.bucket` 和 `extractorConfig.s3.region` 必填。`credentials` 可省略,省略时使用 AWS SDK 默认凭证链。`publicBaseUrl` 可省略,省略时返回 `https://<bucket>.s3.<region>.amazonaws.com/<key>`;配置后返回 `${publicBaseUrl}/<key>`。
|
|
320
320
|
|
|
321
321
|
### parserConfig
|
|
322
322
|
|
package/package.json
CHANGED
package/page-extractor.js
CHANGED
|
@@ -107,9 +107,9 @@ function encodeS3Key(key) {
|
|
|
107
107
|
.join('/');
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
function buildS3Url(s3Config, key
|
|
110
|
+
function buildS3Url(s3Config, key) {
|
|
111
111
|
if (s3Config.publicBaseUrl) {
|
|
112
|
-
return `${s3Config.publicBaseUrl}/${
|
|
112
|
+
return `${s3Config.publicBaseUrl}/${encodeS3Key(key)}`;
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
return `https://${s3Config.bucket}.s3.${s3Config.region}.amazonaws.com/${encodeS3Key(key)}`;
|
|
@@ -196,7 +196,7 @@ export class PageExtractor {
|
|
|
196
196
|
try {
|
|
197
197
|
const command = new PutObjectCommand(commandInput);
|
|
198
198
|
await client.send(command);
|
|
199
|
-
return buildS3Url(s3Config, key
|
|
199
|
+
return buildS3Url(s3Config, key);
|
|
200
200
|
} catch (error) {
|
|
201
201
|
lastError = error;
|
|
202
202
|
if (attempt < s3Config.maxUploadAttempts) {
|
package/result-viewer.html
CHANGED
|
@@ -689,6 +689,19 @@
|
|
|
689
689
|
return text;
|
|
690
690
|
}
|
|
691
691
|
|
|
692
|
+
function safeResourceUrl(value) {
|
|
693
|
+
const url = pathToUrl(value);
|
|
694
|
+
if (!url) return '';
|
|
695
|
+
if (/^(https?:|file:|blob:)/i.test(url)) return url;
|
|
696
|
+
if (/^data:image\/(png|jpe?g|gif|webp);/i.test(url)) return url;
|
|
697
|
+
if (!/^[a-z][a-z0-9+.-]*:/i.test(url)) return url;
|
|
698
|
+
return '';
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function imageSrcAttr(value) {
|
|
702
|
+
return escapeHtml(safeResourceUrl(value));
|
|
703
|
+
}
|
|
704
|
+
|
|
692
705
|
function getShot(block, index) {
|
|
693
706
|
const direct = asArray(block.blockScreenshotPaths)[0] || block.blockScreenshotPath || block.screenshotPath || '';
|
|
694
707
|
if (direct) return { path: direct };
|
|
@@ -792,8 +805,9 @@
|
|
|
792
805
|
}
|
|
793
806
|
els.allBlocks.innerHTML = rows.map(({ block, index }) => {
|
|
794
807
|
const shot = getShot(block, index);
|
|
795
|
-
const
|
|
796
|
-
|
|
808
|
+
const shotUrl = shot?.path ? imageSrcAttr(shot.path) : '';
|
|
809
|
+
const image = shotUrl
|
|
810
|
+
? '<img src="' + shotUrl + '" alt="Screenshot for block ' + index + '">'
|
|
797
811
|
: '<div class="empty-thumb">No selector screenshot</div>';
|
|
798
812
|
return '<article class="mini" data-index="' + index + '">' +
|
|
799
813
|
image +
|
|
@@ -815,8 +829,9 @@
|
|
|
815
829
|
els.selectedTitle.textContent = 'No blocks found';
|
|
816
830
|
els.selectedDescription.textContent = 'Loaded JSON does not contain block analysis rows.';
|
|
817
831
|
els.copySelector.disabled = true;
|
|
818
|
-
|
|
819
|
-
els.fullPageLink.
|
|
832
|
+
const fullPageUrl = safeResourceUrl(data.screenshots?.fullPage || '');
|
|
833
|
+
els.fullPageLink.href = fullPageUrl;
|
|
834
|
+
els.fullPageLink.style.display = fullPageUrl ? 'inline-flex' : 'none';
|
|
820
835
|
els.screenshot.innerHTML = '<div class="missing-shot">Load a Page Analyzer result with analysis.block_analysis.blocks.</div>';
|
|
821
836
|
els.info.innerHTML = '';
|
|
822
837
|
els.raw.textContent = JSON.stringify(data, null, 2);
|
|
@@ -828,12 +843,14 @@
|
|
|
828
843
|
els.selectedTitle.textContent = '#' + selectedIndex + ' ' + (block.blockName || 'Unnamed block');
|
|
829
844
|
els.selectedDescription.textContent = block.blockDescription || 'No description available.';
|
|
830
845
|
els.copySelector.disabled = !block.blockCssPath;
|
|
831
|
-
|
|
832
|
-
els.fullPageLink.
|
|
846
|
+
const fullPageUrl = safeResourceUrl(data.screenshots?.fullPage || '');
|
|
847
|
+
els.fullPageLink.href = fullPageUrl;
|
|
848
|
+
els.fullPageLink.style.display = fullPageUrl ? 'inline-flex' : 'none';
|
|
833
849
|
|
|
834
|
-
|
|
850
|
+
const shotUrl = shot?.path ? imageSrcAttr(shot.path) : '';
|
|
851
|
+
if (shotUrl) {
|
|
835
852
|
els.screenshot.innerHTML =
|
|
836
|
-
'<div class="screenshot-frame"><img src="' +
|
|
853
|
+
'<div class="screenshot-frame"><img src="' + shotUrl + '" alt="Screenshot for selected block"></div>' +
|
|
837
854
|
'<div class="info wide"><label>Screenshot path</label><span>' + escapeHtml(shot.path) + '</span></div>';
|
|
838
855
|
} else {
|
|
839
856
|
els.screenshot.innerHTML =
|
|
@@ -697,6 +697,19 @@ const html = `<!doctype html>
|
|
|
697
697
|
return text;
|
|
698
698
|
}
|
|
699
699
|
|
|
700
|
+
function safeResourceUrl(value) {
|
|
701
|
+
const url = pathToUrl(value);
|
|
702
|
+
if (!url) return '';
|
|
703
|
+
if (/^(https?:|file:|blob:)/i.test(url)) return url;
|
|
704
|
+
if (/^data:image\\/(png|jpe?g|gif|webp);/i.test(url)) return url;
|
|
705
|
+
if (!/^[a-z][a-z0-9+.-]*:/i.test(url)) return url;
|
|
706
|
+
return '';
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function imageSrcAttr(value) {
|
|
710
|
+
return escapeHtml(safeResourceUrl(value));
|
|
711
|
+
}
|
|
712
|
+
|
|
700
713
|
function getShot(block, index) {
|
|
701
714
|
const direct = asArray(block.blockScreenshotPaths)[0] || block.blockScreenshotPath || block.screenshotPath || '';
|
|
702
715
|
if (direct) return { path: direct };
|
|
@@ -800,8 +813,9 @@ const html = `<!doctype html>
|
|
|
800
813
|
}
|
|
801
814
|
els.allBlocks.innerHTML = rows.map(({ block, index }) => {
|
|
802
815
|
const shot = getShot(block, index);
|
|
803
|
-
const
|
|
804
|
-
|
|
816
|
+
const shotUrl = shot?.path ? imageSrcAttr(shot.path) : '';
|
|
817
|
+
const image = shotUrl
|
|
818
|
+
? '<img src="' + shotUrl + '" alt="Screenshot for block ' + index + '">'
|
|
805
819
|
: '<div class="empty-thumb">No selector screenshot</div>';
|
|
806
820
|
return '<article class="mini" data-index="' + index + '">' +
|
|
807
821
|
image +
|
|
@@ -823,8 +837,9 @@ const html = `<!doctype html>
|
|
|
823
837
|
els.selectedTitle.textContent = 'No blocks found';
|
|
824
838
|
els.selectedDescription.textContent = 'Loaded JSON does not contain block analysis rows.';
|
|
825
839
|
els.copySelector.disabled = true;
|
|
826
|
-
|
|
827
|
-
els.fullPageLink.
|
|
840
|
+
const fullPageUrl = safeResourceUrl(data.screenshots?.fullPage || '');
|
|
841
|
+
els.fullPageLink.href = fullPageUrl;
|
|
842
|
+
els.fullPageLink.style.display = fullPageUrl ? 'inline-flex' : 'none';
|
|
828
843
|
els.screenshot.innerHTML = '<div class="missing-shot">Load a Page Analyzer result with analysis.block_analysis.blocks.</div>';
|
|
829
844
|
els.info.innerHTML = '';
|
|
830
845
|
els.raw.textContent = JSON.stringify(data, null, 2);
|
|
@@ -836,12 +851,14 @@ const html = `<!doctype html>
|
|
|
836
851
|
els.selectedTitle.textContent = '#' + selectedIndex + ' ' + (block.blockName || 'Unnamed block');
|
|
837
852
|
els.selectedDescription.textContent = block.blockDescription || 'No description available.';
|
|
838
853
|
els.copySelector.disabled = !block.blockCssPath;
|
|
839
|
-
|
|
840
|
-
els.fullPageLink.
|
|
854
|
+
const fullPageUrl = safeResourceUrl(data.screenshots?.fullPage || '');
|
|
855
|
+
els.fullPageLink.href = fullPageUrl;
|
|
856
|
+
els.fullPageLink.style.display = fullPageUrl ? 'inline-flex' : 'none';
|
|
841
857
|
|
|
842
|
-
|
|
858
|
+
const shotUrl = shot?.path ? imageSrcAttr(shot.path) : '';
|
|
859
|
+
if (shotUrl) {
|
|
843
860
|
els.screenshot.innerHTML =
|
|
844
|
-
'<div class="screenshot-frame"><img src="' +
|
|
861
|
+
'<div class="screenshot-frame"><img src="' + shotUrl + '" alt="Screenshot for selected block"></div>' +
|
|
845
862
|
'<div class="info wide"><label>Screenshot path</label><span>' + escapeHtml(shot.path) + '</span></div>';
|
|
846
863
|
} else {
|
|
847
864
|
els.screenshot.innerHTML =
|
package/test/smoke.test.js
CHANGED
|
@@ -331,7 +331,7 @@ async function analyzeWith(options = {}) {
|
|
|
331
331
|
bucket: 'page-analyzer-test',
|
|
332
332
|
region: 'ap-northeast-1',
|
|
333
333
|
prefix: '/page-analyzer/snapshots/',
|
|
334
|
-
publicBaseUrl: 'https://cdn.example.com/
|
|
334
|
+
publicBaseUrl: 'https://cdn.example.com/',
|
|
335
335
|
client: s3Client
|
|
336
336
|
}
|
|
337
337
|
});
|
|
@@ -357,13 +357,11 @@ async function analyzeWith(options = {}) {
|
|
|
357
357
|
assert.match(fullPageUpload.Key, /^page-analyzer\/snapshots\/example-com-demo-.*-full-page\.png$/);
|
|
358
358
|
assert.match(blockUpload.Key, /^page-analyzer\/snapshots\/example-com-demo-.*-block-000\.png$/);
|
|
359
359
|
|
|
360
|
-
const fullPageFilename = fullPageUpload.Key.split('/').pop();
|
|
361
|
-
const blockFilename = blockUpload.Key.split('/').pop();
|
|
362
360
|
assert.equal(
|
|
363
361
|
screenshots.fullPage,
|
|
364
|
-
`https://cdn.example.com
|
|
362
|
+
`https://cdn.example.com/${fullPageUpload.Key}`
|
|
365
363
|
);
|
|
366
|
-
assert.equal(screenshots.blocks[0].path, `https://cdn.example.com
|
|
364
|
+
assert.equal(screenshots.blocks[0].path, `https://cdn.example.com/${blockUpload.Key}`);
|
|
367
365
|
}
|
|
368
366
|
|
|
369
367
|
{
|
|
@@ -407,7 +405,7 @@ async function analyzeWith(options = {}) {
|
|
|
407
405
|
bucket: 'page-analyzer-test',
|
|
408
406
|
region: 'ap-northeast-1',
|
|
409
407
|
prefix: 'page-analyzer/snapshots',
|
|
410
|
-
publicBaseUrl: 'https://cdn.example.com
|
|
408
|
+
publicBaseUrl: 'https://cdn.example.com',
|
|
411
409
|
client: s3Client
|
|
412
410
|
}
|
|
413
411
|
});
|