lighthouse 8.0.0-dev.20210709 → 8.0.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/docs/architecture.md +101 -0
- package/docs/authenticated-pages.md +44 -0
- package/docs/bug-labels.md +35 -0
- package/docs/configuration.md +213 -0
- package/docs/emulation.md +32 -0
- package/docs/error-reporting.md +42 -0
- package/docs/hacking-tips.md +55 -0
- package/docs/headless-chrome.md +119 -0
- package/docs/lantern.md +55 -0
- package/docs/new-audits.md +99 -0
- package/docs/performance-budgets.md +187 -0
- package/docs/plugins.md +374 -0
- package/docs/puppeteer.md +95 -0
- package/docs/readme.md +164 -0
- package/docs/recipes/auth/README.md +129 -0
- package/docs/recipes/auth/example-lh-auth.js +81 -0
- package/docs/recipes/auth/package.json +11 -0
- package/docs/recipes/auth/server/public/dashboard-unauthenticated.html +21 -0
- package/docs/recipes/auth/server/public/dashboard.html +25 -0
- package/docs/recipes/auth/server/public/home-unauthenticated.html +27 -0
- package/docs/recipes/auth/server/public/home.html +17 -0
- package/docs/recipes/auth/server/public/unauthenticated.html +22 -0
- package/docs/recipes/auth/server/server.js +85 -0
- package/docs/recipes/custom-audit/custom-config.js +36 -0
- package/docs/recipes/custom-audit/package.json +8 -0
- package/docs/recipes/custom-audit/readme.md +32 -0
- package/docs/recipes/custom-audit/searchable-audit.js +46 -0
- package/docs/recipes/custom-audit/searchable-gatherer.js +32 -0
- package/docs/recipes/custom-gatherer-puppeteer/custom-audit.js +34 -0
- package/{root.js → docs/recipes/custom-gatherer-puppeteer/custom-config.js} +23 -2
- package/docs/recipes/custom-gatherer-puppeteer/custom-gatherer.js +51 -0
- package/docs/recipes/custom-gatherer-puppeteer/package.json +13 -0
- package/docs/recipes/custom-gatherer-puppeteer/readme.md +7 -0
- package/docs/recipes/custom-gatherer-puppeteer/test.sh +9 -0
- package/docs/recipes/gulp/gulpfile.js +79 -0
- package/docs/recipes/gulp/package.json +12 -0
- package/docs/recipes/gulp/public/index.html +22 -0
- package/docs/recipes/gulp/readme.md +6 -0
- package/docs/recipes/integration-test/README.md +14 -0
- package/docs/recipes/integration-test/example-lh-auth.test.js +160 -0
- package/docs/recipes/integration-test/package.json +9 -0
- package/docs/recipes/lighthouse-plugin-example/audits/preload-as.js +46 -0
- package/docs/recipes/lighthouse-plugin-example/package.json +11 -0
- package/docs/recipes/lighthouse-plugin-example/plugin-recipe-screenshot.png +0 -0
- package/docs/recipes/lighthouse-plugin-example/plugin.js +24 -0
- package/docs/recipes/lighthouse-plugin-example/readme.md +53 -0
- package/docs/releasing.md +164 -0
- package/docs/scoring.md +79 -0
- package/docs/throttling.md +150 -0
- package/docs/understanding-results.md +209 -0
- package/docs/v8-perf-faq.md +244 -0
- package/docs/variability.md +150 -0
- package/jest.config.js +0 -3
- package/lighthouse-cli/bin.js +8 -6
- package/lighthouse-core/audits/accessibility/aria-command-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-meter-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-progressbar-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-tooltip-name.js +1 -1
- package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
- package/lighthouse-core/audits/apple-touch-icon.js +0 -1
- package/lighthouse-core/audits/audit.js +3 -3
- package/lighthouse-core/audits/autocomplete.js +2 -2
- package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +14 -29
- package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +2 -3
- package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +2 -3
- package/lighthouse-core/audits/byte-efficiency/modern-image-formats.js +15 -55
- package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +4 -8
- package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +8 -15
- package/lighthouse-core/audits/byte-efficiency/total-byte-weight.js +9 -10
- package/lighthouse-core/audits/byte-efficiency/unminified-css.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -1
- package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +1 -2
- package/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js +2 -2
- package/lighthouse-core/audits/byte-efficiency/uses-optimized-images.js +1 -2
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +24 -46
- package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
- package/lighthouse-core/audits/critical-request-chains.js +0 -1
- package/lighthouse-core/audits/csp-xss.js +1 -1
- package/lighthouse-core/audits/diagnostics.js +0 -1
- package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +0 -1
- package/lighthouse-core/audits/dobetterweb/inspector-issues.js +1 -1
- package/lighthouse-core/audits/dobetterweb/notification-on-start.js +0 -1
- package/lighthouse-core/audits/dobetterweb/uses-http2.js +0 -1
- package/lighthouse-core/audits/final-screenshot.js +4 -8
- package/lighthouse-core/audits/font-display.js +0 -1
- package/lighthouse-core/audits/installable-manifest.js +3 -4
- package/lighthouse-core/audits/largest-contentful-paint-element.js +0 -1
- package/lighthouse-core/audits/long-tasks.js +1 -1
- package/lighthouse-core/audits/maskable-icon.js +0 -1
- package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -4
- package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -4
- package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -4
- package/lighthouse-core/audits/metrics/interactive.js +2 -4
- package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -4
- package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -4
- package/lighthouse-core/audits/metrics/speed-index.js +2 -4
- package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -10
- package/lighthouse-core/audits/metrics.js +2 -4
- package/lighthouse-core/audits/performance-budget.js +0 -1
- package/lighthouse-core/audits/predictive-perf.js +6 -9
- package/lighthouse-core/audits/preload-fonts.js +1 -11
- package/lighthouse-core/audits/preload-lcp-image.js +5 -18
- package/lighthouse-core/audits/redirects.js +8 -10
- package/lighthouse-core/audits/screenshot-thumbnails.js +13 -28
- package/lighthouse-core/audits/seo/canonical.js +1 -2
- package/lighthouse-core/audits/seo/font-size.js +4 -4
- package/lighthouse-core/audits/seo/hreflang.js +2 -3
- package/lighthouse-core/audits/seo/http-status-code.js +16 -21
- package/lighthouse-core/audits/seo/is-crawlable.js +3 -4
- package/lighthouse-core/audits/seo/robots-txt.js +2 -2
- package/lighthouse-core/audits/seo/tap-targets.js +5 -5
- package/lighthouse-core/audits/server-response-time.js +2 -20
- package/lighthouse-core/audits/splash-screen.js +0 -1
- package/lighthouse-core/audits/themed-omnibox.js +0 -1
- package/lighthouse-core/audits/third-party-facades.js +0 -1
- package/lighthouse-core/audits/third-party-summary.js +3 -1
- package/lighthouse-core/audits/timing-budget.js +2 -4
- package/lighthouse-core/audits/uses-rel-preconnect.js +9 -14
- package/lighthouse-core/audits/uses-rel-preload.js +2 -13
- package/lighthouse-core/computed/main-thread-tasks.js +2 -2
- package/lighthouse-core/computed/metrics/cumulative-layout-shift.js +3 -3
- package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +6 -6
- package/lighthouse-core/computed/metrics/first-contentful-paint.js +8 -9
- package/lighthouse-core/computed/metrics/first-meaningful-paint.js +9 -10
- package/lighthouse-core/computed/metrics/interactive.js +24 -25
- package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +6 -6
- package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +6 -6
- package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +6 -6
- package/lighthouse-core/computed/metrics/lantern-metric.js +8 -16
- package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +7 -7
- package/lighthouse-core/computed/metrics/largest-contentful-paint.js +9 -10
- package/lighthouse-core/computed/metrics/max-potential-fid.js +11 -8
- package/lighthouse-core/computed/metrics/metric.js +5 -32
- package/lighthouse-core/computed/metrics/speed-index.js +5 -6
- package/lighthouse-core/computed/metrics/timing-summary.js +45 -55
- package/lighthouse-core/computed/metrics/total-blocking-time.js +29 -36
- package/lighthouse-core/computed/page-dependency-graph.js +14 -14
- package/lighthouse-core/computed/resource-summary.js +7 -3
- package/lighthouse-core/computed/speedline.js +3 -3
- package/lighthouse-core/computed/trace-of-tab.js +86 -15
- package/lighthouse-core/computed/user-timings.js +5 -5
- package/lighthouse-core/config/default-config.js +0 -1
- package/lighthouse-core/fraggle-rock/config/config.js +7 -9
- package/lighthouse-core/fraggle-rock/config/default-config.js +2 -40
- package/lighthouse-core/fraggle-rock/config/filters.js +6 -39
- package/lighthouse-core/fraggle-rock/config/validation.js +4 -4
- package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +19 -54
- package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +10 -21
- package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +2 -2
- package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +2 -2
- package/lighthouse-core/gather/driver/prepare.js +0 -3
- package/lighthouse-core/gather/fetcher.js +2 -0
- package/lighthouse-core/gather/gather-runner.js +14 -2
- package/lighthouse-core/gather/gatherers/image-elements.js +61 -24
- package/lighthouse-core/gather/gatherers/inspector-issues.js +2 -2
- package/lighthouse-core/gather/gatherers/script-elements.js +12 -45
- package/lighthouse-core/gather/gatherers/seo/font-size.js +5 -5
- package/lighthouse-core/gather/gatherers/seo/tap-targets.js +12 -64
- package/lighthouse-core/gather/gatherers/service-worker.js +3 -20
- package/lighthouse-core/gather/gatherers/trace-compat.js +1 -1
- package/lighthouse-core/gather/gatherers/trace-elements.js +3 -15
- package/lighthouse-core/gather/gatherers/trace.js +4 -13
- package/lighthouse-core/gather/gatherers/viewport-dimensions.js +1 -1
- package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +2 -13
- package/lighthouse-core/lib/emulation.js +2 -0
- package/lighthouse-core/lib/i18n/i18n.js +2 -2
- package/lighthouse-core/lib/i18n/locales/ar-XB.json +141 -141
- package/lighthouse-core/lib/i18n/locales/ar.json +143 -143
- package/lighthouse-core/lib/i18n/locales/bg.json +143 -143
- package/lighthouse-core/lib/i18n/locales/ca.json +141 -141
- package/lighthouse-core/lib/i18n/locales/cs.json +141 -141
- package/lighthouse-core/lib/i18n/locales/da.json +141 -141
- package/lighthouse-core/lib/i18n/locales/de.json +142 -142
- package/lighthouse-core/lib/i18n/locales/el.json +141 -141
- package/lighthouse-core/lib/i18n/locales/en-GB.json +141 -141
- package/lighthouse-core/lib/i18n/locales/en-US.ctc.json +6659 -0
- package/lighthouse-core/lib/i18n/locales/en-US.json +144 -150
- package/lighthouse-core/lib/i18n/locales/en-XA.json +141 -141
- package/lighthouse-core/lib/i18n/locales/en-XL.ctc.json +6628 -0
- package/lighthouse-core/lib/i18n/locales/en-XL.json +144 -150
- package/lighthouse-core/lib/i18n/locales/es-419.json +141 -141
- package/lighthouse-core/lib/i18n/locales/es.json +141 -141
- package/lighthouse-core/lib/i18n/locales/fi.json +143 -143
- package/lighthouse-core/lib/i18n/locales/fil.json +142 -142
- package/lighthouse-core/lib/i18n/locales/fr.json +141 -141
- package/lighthouse-core/lib/i18n/locales/he.json +142 -142
- package/lighthouse-core/lib/i18n/locales/hi.json +143 -143
- package/lighthouse-core/lib/i18n/locales/hr.json +141 -141
- package/lighthouse-core/lib/i18n/locales/hu.json +143 -143
- package/lighthouse-core/lib/i18n/locales/id.json +143 -143
- package/lighthouse-core/lib/i18n/locales/it.json +143 -143
- package/lighthouse-core/lib/i18n/locales/ja.json +143 -143
- package/lighthouse-core/lib/i18n/locales/ko.json +143 -143
- package/lighthouse-core/lib/i18n/locales/lt.json +143 -143
- package/lighthouse-core/lib/i18n/locales/lv.json +143 -143
- package/lighthouse-core/lib/i18n/locales/nl.json +141 -141
- package/lighthouse-core/lib/i18n/locales/no.json +141 -141
- package/lighthouse-core/lib/i18n/locales/pl.json +141 -141
- package/lighthouse-core/lib/i18n/locales/pt-PT.json +141 -141
- package/lighthouse-core/lib/i18n/locales/pt.json +141 -141
- package/lighthouse-core/lib/i18n/locales/ro.json +144 -144
- package/lighthouse-core/lib/i18n/locales/ru.json +143 -143
- package/lighthouse-core/lib/i18n/locales/sk.json +142 -142
- package/lighthouse-core/lib/i18n/locales/sl.json +141 -141
- package/lighthouse-core/lib/i18n/locales/sr-Latn.json +143 -143
- package/lighthouse-core/lib/i18n/locales/sr.json +143 -143
- package/lighthouse-core/lib/i18n/locales/sv.json +142 -142
- package/lighthouse-core/lib/i18n/locales/ta.json +141 -141
- package/lighthouse-core/lib/i18n/locales/te.json +143 -143
- package/lighthouse-core/lib/i18n/locales/th.json +143 -143
- package/lighthouse-core/lib/i18n/locales/tr.json +143 -143
- package/lighthouse-core/lib/i18n/locales/uk.json +141 -141
- package/lighthouse-core/lib/i18n/locales/vi.json +143 -143
- package/lighthouse-core/lib/i18n/locales/zh-HK.json +141 -141
- package/lighthouse-core/lib/i18n/locales/zh-TW.json +143 -143
- package/lighthouse-core/lib/i18n/locales/zh.json +143 -143
- package/lighthouse-core/lib/lh-error.js +2 -2
- package/lighthouse-core/lib/minify-trace.js +1 -1
- package/lighthouse-core/lib/network-request.js +1 -17
- package/lighthouse-core/lib/page-functions.js +5 -6
- package/lighthouse-core/lib/rect-helpers.js +3 -3
- package/lighthouse-core/lib/sd-validation/assets/jsonldcontext.json +7137 -0
- package/lighthouse-core/lib/sd-validation/assets/schema-tree.json +9900 -0
- package/{report/report-assets.js → lighthouse-core/lib/sd-validation/helpers/walk-object.js} +20 -12
- package/lighthouse-core/lib/sd-validation/json-expander.js +56 -0
- package/lighthouse-core/lib/sd-validation/json-linter.js +49 -0
- package/lighthouse-core/lib/sd-validation/jsonld-keyword-validator.js +50 -0
- package/lighthouse-core/lib/sd-validation/line-number-from-jsonld-path.js +60 -0
- package/lighthouse-core/lib/sd-validation/schema-validator.js +146 -0
- package/lighthouse-core/lib/sd-validation/scripts/download-jsonldcontext.js +30 -0
- package/lighthouse-core/lib/sd-validation/scripts/generate-schema-tree.js +97 -0
- package/lighthouse-core/lib/sd-validation/sd-validation.js +77 -0
- package/lighthouse-core/lib/tappable-rects.js +1 -1
- package/lighthouse-core/lib/tracehouse/trace-processor.js +42 -116
- package/lighthouse-core/lib/url-shim.js +2 -29
- package/lighthouse-core/report/html/html-report-assets.js +38 -0
- package/{report/README.md → lighthouse-core/report/html/readme.md} +11 -7
- package/{report → lighthouse-core/report/html}/renderer/category-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/crc-details-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/details-renderer.js +1 -1
- package/{report → lighthouse-core/report/html}/renderer/dom.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/element-screenshot-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/i18n.js +1 -1
- package/{report → lighthouse-core/report/html}/renderer/logger.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/performance-category-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/psi.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/pwa-category-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/report-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/report-ui-features.js +3 -3
- package/{report → lighthouse-core/report/html}/renderer/snippet-renderer.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/text-encoding.js +0 -0
- package/{report → lighthouse-core/report/html}/renderer/util.js +4 -7
- package/{report/assets/styles.css → lighthouse-core/report/html/report-styles.css} +0 -0
- package/{report/assets/standalone-template.html → lighthouse-core/report/html/report-template.html} +41 -1
- package/{report/assets → lighthouse-core/report/html}/templates.html +0 -0
- package/{report → lighthouse-core/report}/report-generator.js +1 -1
- package/lighthouse-core/runner.js +1 -1
- package/package.json +12 -13
- package/readme.md +2 -2
- package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -3
- package/third-party/chromium-synchronization/installability-errors-test.js +2 -2
- package/third-party/download-content-shell/download-content-shell.js +1 -2
- package/third-party/snyk/snapshot.json +1 -1
- package/tsconfig.json +1 -0
- package/types/artifacts.d.ts +21 -41
- package/types/audit.d.ts +0 -2
- package/types/config.d.ts +2 -16
- package/types/externs.d.ts +0 -1
- package/types/gatherer.d.ts +13 -13
- package/types/html-renderer.d.ts +14 -14
- package/types/i18n.d.ts +1 -1
- package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +0 -94
- package/lighthouse-core/computed/image-records.js +0 -62
- package/lighthouse-core/computed/metrics/navigation-metric.js +0 -46
- package/lighthouse-core/computed/processed-navigation.js +0 -21
- package/lighthouse-core/computed/processed-trace.js +0 -21
- package/lighthouse-core/gather/gatherers/gather-context.js +0 -25
- package/lighthouse-core/gather/gatherers/host-form-factor.js +0 -31
- package/lighthouse-core/gather/gatherers/host-user-agent.js +0 -29
- package/lighthouse-core/lib/lh-trace-processor.js +0 -46
- package/report/clients/standalone.js +0 -52
- package/report/test/renderer/category-renderer-test.js +0 -488
- package/report/test/renderer/crc-details-renderer-test.js +0 -115
- package/report/test/renderer/details-renderer-test.js +0 -843
- package/report/test/renderer/dom-test.js +0 -157
- package/report/test/renderer/element-screenshot-renderer-test.js +0 -189
- package/report/test/renderer/i18n-test.js +0 -146
- package/report/test/renderer/performance-category-renderer-test.js +0 -332
- package/report/test/renderer/psi-test.js +0 -152
- package/report/test/renderer/pwa-category-renderer-test.js +0 -303
- package/report/test/renderer/report-renderer-test.js +0 -325
- package/report/test/renderer/report-ui-features-test.js +0 -572
- package/report/test/renderer/snippet-renderer-test.js +0 -291
- package/report/test/renderer/text-encoding-test.js +0 -41
- package/report/test/renderer/util-test.js +0 -388
- package/report/test/report-generator-test.js +0 -145
package/{report/report-assets.js → lighthouse-core/lib/sd-validation/helpers/walk-object.js}
RENAMED
|
@@ -5,18 +5,26 @@
|
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Recursively (DFS) traverses an object and calls provided function for each field.
|
|
10
|
+
*
|
|
11
|
+
* @param {*} obj
|
|
12
|
+
* @param {function(string, any, Array<string>, any): void} callback
|
|
13
|
+
* @param {Array<string>} path
|
|
14
|
+
*/
|
|
15
|
+
module.exports = function walkObject(obj, callback, path = []) {
|
|
16
|
+
if (obj === null) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
Object.entries(obj).forEach(([fieldName, fieldValue]) => {
|
|
21
|
+
const newPath = Array.from(path);
|
|
22
|
+
newPath.push(fieldName);
|
|
9
23
|
|
|
10
|
-
|
|
11
|
-
const REPORT_JAVASCRIPT = fs.readFileSync(__dirname + '/../dist/report/standalone.js', 'utf8');
|
|
12
|
-
const REPORT_CSS = fs.readFileSync(__dirname + '/assets/styles.css', 'utf8');
|
|
13
|
-
const REPORT_TEMPLATES = fs.readFileSync(__dirname + '/assets/templates.html', 'utf8');
|
|
24
|
+
callback(fieldName, fieldValue, newPath, obj);
|
|
14
25
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
REPORT_TEMPLATES,
|
|
20
|
-
REPORT_JAVASCRIPT,
|
|
21
|
-
REPORT_CSS,
|
|
26
|
+
if (typeof fieldValue === 'object') {
|
|
27
|
+
walkObject(fieldValue, callback, newPath);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
22
30
|
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2018 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const {URL} = require('../url-shim.js');
|
|
9
|
+
const jsonld = require('jsonld');
|
|
10
|
+
const schemaOrgContext = require('./assets/jsonldcontext.json');
|
|
11
|
+
const SCHEMA_ORG_HOST = 'schema.org';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Custom loader that prevents network calls and allows us to return local version of the
|
|
15
|
+
* schema.org document
|
|
16
|
+
* @param {string} schemaUrl
|
|
17
|
+
* @return {Promise<import('jsonld').RemoteDocument>}
|
|
18
|
+
*/
|
|
19
|
+
async function documentLoader(schemaUrl) {
|
|
20
|
+
let urlObj = null;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
// Give a dummy base URL so relative URLs will be considered valid.
|
|
24
|
+
urlObj = new URL(schemaUrl, 'http://example.com');
|
|
25
|
+
} catch (e) {
|
|
26
|
+
throw new Error('Error parsing URL: ' + schemaUrl);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (urlObj.host === SCHEMA_ORG_HOST && urlObj.pathname === '/') {
|
|
30
|
+
return {
|
|
31
|
+
document: schemaOrgContext,
|
|
32
|
+
};
|
|
33
|
+
} else {
|
|
34
|
+
// We only process schema.org, for other schemas we return an empty object
|
|
35
|
+
return {
|
|
36
|
+
document: {},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Takes JSON-LD object and normalizes it by following the expansion algorithm
|
|
43
|
+
* (https://json-ld.org/spec/latest/json-ld-api/#expansion).
|
|
44
|
+
*
|
|
45
|
+
* @param {any} inputObject
|
|
46
|
+
* @returns {Promise<LH.StructuredData.ExpandedSchemaRepresentation|null>}
|
|
47
|
+
*/
|
|
48
|
+
module.exports = async function expand(inputObject) {
|
|
49
|
+
try {
|
|
50
|
+
return await jsonld.expand(inputObject, {documentLoader});
|
|
51
|
+
} catch (err) {
|
|
52
|
+
// jsonld wraps real errors in a bunch of junk, so see we have an underlying error first
|
|
53
|
+
if (err.details && err.details.cause) throw err.details.cause;
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2018 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const jsonlint = require('jsonlint-mod');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} input
|
|
12
|
+
* @returns {{message: string, lineNumber: number|null}|null}
|
|
13
|
+
*/
|
|
14
|
+
module.exports = function parseJSON(input) {
|
|
15
|
+
try {
|
|
16
|
+
jsonlint.parse(input);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
/** @type {number|null} */
|
|
19
|
+
let line = error.at;
|
|
20
|
+
|
|
21
|
+
// extract line number from message
|
|
22
|
+
if (!line) {
|
|
23
|
+
const regexLineResult = error.message.match(/Parse error on line (\d+)/);
|
|
24
|
+
|
|
25
|
+
if (regexLineResult) {
|
|
26
|
+
line = parseFloat(regexLineResult[1]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
// jsonlint error message points to a specific character, but we just want the message.
|
|
32
|
+
// Example:
|
|
33
|
+
// ---------^
|
|
34
|
+
// Unexpected character {
|
|
35
|
+
let message = /** @type {string} */ (error.message);
|
|
36
|
+
const regexMessageResult = error.message.match(/-+\^\n(.+)$/);
|
|
37
|
+
|
|
38
|
+
if (regexMessageResult) {
|
|
39
|
+
message = regexMessageResult[1];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
message,
|
|
44
|
+
lineNumber: line,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return null;
|
|
49
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2018 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const walkObject = require('./helpers/walk-object.js');
|
|
9
|
+
|
|
10
|
+
// This list comes from the JSON-LD 1.1 editors draft:
|
|
11
|
+
// https://w3c.github.io/json-ld-syntax/#syntax-tokens-and-keywords
|
|
12
|
+
const VALID_KEYWORDS = new Set([
|
|
13
|
+
'@base',
|
|
14
|
+
'@container',
|
|
15
|
+
'@context',
|
|
16
|
+
'@graph',
|
|
17
|
+
'@id',
|
|
18
|
+
'@index',
|
|
19
|
+
'@language',
|
|
20
|
+
'@list',
|
|
21
|
+
'@nest',
|
|
22
|
+
'@none',
|
|
23
|
+
'@prefix',
|
|
24
|
+
'@reverse',
|
|
25
|
+
'@set',
|
|
26
|
+
'@type',
|
|
27
|
+
'@value',
|
|
28
|
+
'@version',
|
|
29
|
+
'@vocab',
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {*} json
|
|
34
|
+
* @return {Array<{path: string, message: string}>}
|
|
35
|
+
*/
|
|
36
|
+
module.exports = function validateJsonLD(json) {
|
|
37
|
+
/** @type {Array<{path: string, message: string}>} */
|
|
38
|
+
const errors = [];
|
|
39
|
+
|
|
40
|
+
walkObject(json, (name, value, path) => {
|
|
41
|
+
if (name.startsWith('@') && !VALID_KEYWORDS.has(name)) {
|
|
42
|
+
errors.push({
|
|
43
|
+
path: path.join('/'),
|
|
44
|
+
message: `Unknown keyword "${name}"`,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return errors;
|
|
50
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2019 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {*} obj - JSON-LD object
|
|
10
|
+
* @param {string} path - slash-separated path in the JSON-LD object (uses relative URIs)
|
|
11
|
+
* @returns {null | number} - line number of the path value in the prettified JSON
|
|
12
|
+
*/
|
|
13
|
+
function getLineNumberFromJsonLDPath(obj, path) {
|
|
14
|
+
// To avoid having an extra dependency on a JSON parser we set a unique key in the
|
|
15
|
+
// object and then use that to identify the correct line
|
|
16
|
+
const searchKey = Math.random().toString();
|
|
17
|
+
obj = JSON.parse(JSON.stringify(obj));
|
|
18
|
+
|
|
19
|
+
setValueAtJsonLDPath(obj, path, searchKey);
|
|
20
|
+
const jsonLines = JSON.stringify(obj, null, 2).split('\n');
|
|
21
|
+
const lineIndex = jsonLines.findIndex(line => line.includes(searchKey));
|
|
22
|
+
|
|
23
|
+
return lineIndex === -1 ? null : lineIndex + 1;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {*} obj
|
|
28
|
+
* @param {string} path
|
|
29
|
+
* @param {*} value
|
|
30
|
+
*/
|
|
31
|
+
function setValueAtJsonLDPath(obj, path, value) {
|
|
32
|
+
const pathParts = path.split('/').filter(p => !!p);
|
|
33
|
+
let currentObj = obj;
|
|
34
|
+
pathParts.forEach((pathPart, i) => {
|
|
35
|
+
if (pathPart === '0' && !Array.isArray(currentObj)) {
|
|
36
|
+
// jsonld expansion turns single values into arrays
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const isLastPart = pathParts.length - 1 === i;
|
|
41
|
+
for (const key of Object.keys(currentObj)) {
|
|
42
|
+
// The actual key in JSON might be an absolute IRI like "http://schema.org/author"
|
|
43
|
+
// but key provided by validator is "author"
|
|
44
|
+
const keyParts = key.split('/');
|
|
45
|
+
const relativeKey = keyParts[keyParts.length - 1];
|
|
46
|
+
if (relativeKey === pathPart) {
|
|
47
|
+
// If we've arrived at the end of the provided path set the value, otherwise
|
|
48
|
+
// continue iterating with the object at the key location
|
|
49
|
+
if (isLastPart) {
|
|
50
|
+
currentObj[key] = value;
|
|
51
|
+
} else {
|
|
52
|
+
currentObj = currentObj[key];
|
|
53
|
+
}
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = getLineNumberFromJsonLDPath;
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2018 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const walkObject = require('./helpers/walk-object.js');
|
|
9
|
+
const schemaStructure = require('./assets/schema-tree.json');
|
|
10
|
+
const TYPE_KEYWORD = '@type';
|
|
11
|
+
const SCHEMA_ORG_URL_REGEX = /https?:\/\/schema\.org\//;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} uri
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
function cleanName(uri) {
|
|
18
|
+
return uri.replace(SCHEMA_ORG_URL_REGEX, '');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} type
|
|
23
|
+
* @returns {Array<string>}
|
|
24
|
+
*/
|
|
25
|
+
function getPropsForType(type) {
|
|
26
|
+
const cleanType = cleanName(type);
|
|
27
|
+
const props = schemaStructure.properties
|
|
28
|
+
.filter(prop => prop.parent.includes(cleanType))
|
|
29
|
+
.map(prop => prop.name);
|
|
30
|
+
const foundType = findType(type);
|
|
31
|
+
if (!foundType) throw new Error(`Unable to get props for missing type "${type}"`);
|
|
32
|
+
const parentTypes = foundType.parent;
|
|
33
|
+
|
|
34
|
+
return parentTypes.reduce((allProps, type) => allProps.concat(getPropsForType(type)), props);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} type
|
|
39
|
+
* @returns {{name: string, parent: Array<string>}|undefined}
|
|
40
|
+
*/
|
|
41
|
+
function findType(type) {
|
|
42
|
+
const cleanType = cleanName(type);
|
|
43
|
+
|
|
44
|
+
return schemaStructure.types.find(typeObj => typeObj.name === cleanType);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Validates keys of given object based on its type(s). Returns an array of error messages.
|
|
49
|
+
*
|
|
50
|
+
* @param {string|Array<string>} typeOrTypes
|
|
51
|
+
* @param {Array<string>} keys
|
|
52
|
+
* @returns {Array<Pick<LH.StructuredData.ValidationError, "message" | "validTypes"> & {key?: string}>}
|
|
53
|
+
*/
|
|
54
|
+
function validateObjectKeys(typeOrTypes, keys) {
|
|
55
|
+
/** @type {Array<string>} */
|
|
56
|
+
let types = [];
|
|
57
|
+
|
|
58
|
+
if (typeof typeOrTypes === 'string') {
|
|
59
|
+
types = [typeOrTypes];
|
|
60
|
+
} else if (Array.isArray(typeOrTypes)) {
|
|
61
|
+
types = typeOrTypes;
|
|
62
|
+
const invalidIndex = typeOrTypes.findIndex(s => typeof s !== 'string');
|
|
63
|
+
if (invalidIndex >= 0) {
|
|
64
|
+
return [{message: `Unknown value type at index ${invalidIndex}`}];
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
return [{message: 'Unknown value type'}];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const unknownTypes = types.filter(t => !findType(t));
|
|
71
|
+
|
|
72
|
+
if (unknownTypes.length) {
|
|
73
|
+
return unknownTypes
|
|
74
|
+
.filter(type => SCHEMA_ORG_URL_REGEX.test(type))
|
|
75
|
+
.map(type => ({
|
|
76
|
+
message: `Unrecognized schema.org type: ${type}`,
|
|
77
|
+
key: '@type',
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** @type {Set<string>} */
|
|
82
|
+
const allKnownProps = new Set();
|
|
83
|
+
|
|
84
|
+
types.forEach(type => {
|
|
85
|
+
const knownProps = getPropsForType(type);
|
|
86
|
+
|
|
87
|
+
knownProps.forEach(key => allKnownProps.add(key));
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const cleanKeys = keys
|
|
91
|
+
// Skip JSON-LD keywords (including invalid ones as they were already flagged in the json-ld validator)
|
|
92
|
+
.filter(key => key.indexOf('@') !== 0)
|
|
93
|
+
.map(key => cleanName(key));
|
|
94
|
+
|
|
95
|
+
return cleanKeys
|
|
96
|
+
// remove Schema.org input/output constraints http://schema.org/docs/actions.html#part-4
|
|
97
|
+
.map(key => key.replace(/-(input|output)$/, ''))
|
|
98
|
+
.filter(key => !allKnownProps.has(key))
|
|
99
|
+
.map(key => ({
|
|
100
|
+
message: `Unexpected property "${key}"`,
|
|
101
|
+
key,
|
|
102
|
+
validTypes: types,
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* @param {LH.StructuredData.ExpandedSchemaRepresentation|null} expandedObj Valid JSON-LD object in expanded form
|
|
108
|
+
* @return {Array<Pick<LH.StructuredData.ValidationError, "message" | "validTypes" | "path">>}
|
|
109
|
+
*/
|
|
110
|
+
module.exports = function validateSchemaOrg(expandedObj) {
|
|
111
|
+
/** @type {Array<Pick<LH.StructuredData.ValidationError, "message" | "validTypes" | "path">>} */
|
|
112
|
+
const errors = [];
|
|
113
|
+
|
|
114
|
+
if (expandedObj === null) {
|
|
115
|
+
return errors;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// If the array only has a single item, treat it as if it was at the root to simplify the error path.
|
|
119
|
+
// Arrays longer than a single item are handled in `walkObject` below.
|
|
120
|
+
if (Array.isArray(expandedObj) && expandedObj.length === 1) {
|
|
121
|
+
expandedObj = expandedObj[0];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
walkObject(expandedObj, (name, value, path, obj) => {
|
|
125
|
+
if (name === TYPE_KEYWORD) {
|
|
126
|
+
const keyErrors = validateObjectKeys(value, Object.keys(obj));
|
|
127
|
+
|
|
128
|
+
keyErrors.forEach(error => {
|
|
129
|
+
errors.push({
|
|
130
|
+
validTypes: error.validTypes,
|
|
131
|
+
message: error.message,
|
|
132
|
+
// get rid of the last chunk (/@type) as it's the same for all errors
|
|
133
|
+
path:
|
|
134
|
+
'/' +
|
|
135
|
+
path
|
|
136
|
+
.slice(0, -1)
|
|
137
|
+
.concat(error.key || [])
|
|
138
|
+
.map(cleanName)
|
|
139
|
+
.join('/'),
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
return errors;
|
|
146
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2018 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Call this script to update assets/jsonldcontext.json with the latest schema.org spec
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fetch = require('node-fetch');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
|
|
16
|
+
const SCHEMA_ORG_URL = 'https://schema.org';
|
|
17
|
+
const CONTEXT_FILE = path.join(__dirname, '../assets/jsonldcontext.json');
|
|
18
|
+
|
|
19
|
+
async function run() {
|
|
20
|
+
try {
|
|
21
|
+
const response = await fetch(SCHEMA_ORG_URL, {headers: {Accept: 'application/ld+json'}});
|
|
22
|
+
const data = await response.json();
|
|
23
|
+
fs.writeFileSync(CONTEXT_FILE, JSON.stringify(data, null, 2));
|
|
24
|
+
console.log('Success.'); // eslint-disable-line no-console
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error(e); // eslint-disable-line no-console
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
run();
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2018 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Call this script to update assets/schema-tree.json with the latest schema.org spec
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fetch = require('node-fetch');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
|
|
16
|
+
const SCHEMA_ORG_URL = 'https://schema.org/version/latest/schema.jsonld';
|
|
17
|
+
const SCHEMA_TREE_FILE = path.join(__dirname, '../assets/schema-tree.json');
|
|
18
|
+
|
|
19
|
+
/** @typedef {import('jsonlint-mod').SchemaTreeItem} SchemaDefinition */
|
|
20
|
+
|
|
21
|
+
/** @typedef {import('jsonlint-mod').JSONSchemaSource} SchemaSource */
|
|
22
|
+
|
|
23
|
+
/** @typedef {{'@id': string}} IDRef */
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {SchemaSource} data
|
|
27
|
+
*/
|
|
28
|
+
function processData(data) {
|
|
29
|
+
/** @type {SchemaDefinition[]} */
|
|
30
|
+
const types = [];
|
|
31
|
+
/** @type {SchemaDefinition[]} */
|
|
32
|
+
const properties = [];
|
|
33
|
+
|
|
34
|
+
/** @param {string} str */
|
|
35
|
+
function removePrefix(str) {
|
|
36
|
+
return str.replace('http://schema.org/', '');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Accepts some set of id references and returns the array of cleaned references without the `http://schema.org` prefix.
|
|
41
|
+
* @param {Array<IDRef>|IDRef|undefined} parents
|
|
42
|
+
*/
|
|
43
|
+
function cleanIdPrefixes(parents) {
|
|
44
|
+
if (Array.isArray(parents)) {
|
|
45
|
+
return parents.map(item => removePrefix(item['@id']));
|
|
46
|
+
} else if (parents && parents['@id']) {
|
|
47
|
+
return [removePrefix(parents['@id'])];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Go through all the graph entries to find the valid types and properties.
|
|
54
|
+
// i.e. this converts
|
|
55
|
+
// [
|
|
56
|
+
// {@id: 'http://schema.org/CafeOrCoffeeShop', @type: 'rdfs:Class', rdfs:subClassOf: {@id: 'http://schema.org/FoodEstablishment'}},
|
|
57
|
+
// {@id: 'http://schema.org/bestRating', @type: 'rdfs:Property', http://schema.org/domainIncludes: {@id: 'http://schema.org/Rating'}},
|
|
58
|
+
// ]
|
|
59
|
+
// into
|
|
60
|
+
// {
|
|
61
|
+
// types: [{name: 'CafeOrCoffeeShop', parent: ['FoodEstablishment']}],
|
|
62
|
+
// properties: [{name: 'bestRating', parent: ['Rating']}],
|
|
63
|
+
// }
|
|
64
|
+
data['@graph'].forEach(item => {
|
|
65
|
+
if (item['rdfs:label'] === undefined) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (item['@type'] === 'rdf:Property') {
|
|
70
|
+
properties.push({
|
|
71
|
+
name: item['rdfs:label'],
|
|
72
|
+
parent: cleanIdPrefixes(item['http://schema.org/domainIncludes']),
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
types.push({
|
|
76
|
+
name: item['rdfs:label'],
|
|
77
|
+
parent: cleanIdPrefixes(item['rdfs:subClassOf']),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return {types, properties};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function run() {
|
|
86
|
+
try {
|
|
87
|
+
const response = await fetch(SCHEMA_ORG_URL);
|
|
88
|
+
const data = await response.json();
|
|
89
|
+
const processed = processData(data);
|
|
90
|
+
fs.writeFileSync(SCHEMA_TREE_FILE, JSON.stringify(processed, null, 2));
|
|
91
|
+
console.log('Success.'); // eslint-disable-line no-console
|
|
92
|
+
} catch (e) {
|
|
93
|
+
console.error(e); // eslint-disable-line no-console
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
run();
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright 2018 The Lighthouse Authors. All Rights Reserved.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
5
|
+
*/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const parseJSON = require('./json-linter.js');
|
|
9
|
+
const validateJsonLD = require('./jsonld-keyword-validator.js');
|
|
10
|
+
const expandAsync = require('./json-expander.js');
|
|
11
|
+
const validateSchemaOrg = require('./schema-validator.js');
|
|
12
|
+
const getLineNumberFromJsonLDPath = require('./line-number-from-jsonld-path.js');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Validates JSON-LD input. Returns array of error objects.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} textInput
|
|
18
|
+
* @returns {Promise<Array<LH.StructuredData.ValidationError>>}
|
|
19
|
+
*/
|
|
20
|
+
module.exports = async function validate(textInput) {
|
|
21
|
+
// STEP 1: VALIDATE JSON
|
|
22
|
+
const parseError = parseJSON(textInput);
|
|
23
|
+
|
|
24
|
+
if (parseError) {
|
|
25
|
+
return [{
|
|
26
|
+
validator: 'json',
|
|
27
|
+
lineNumber: parseError.lineNumber,
|
|
28
|
+
message: parseError.message,
|
|
29
|
+
}];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const inputObject = JSON.parse(textInput);
|
|
33
|
+
|
|
34
|
+
// STEP 2: VALIDATE JSONLD
|
|
35
|
+
const jsonLdErrors = validateJsonLD(inputObject);
|
|
36
|
+
|
|
37
|
+
if (jsonLdErrors.length) {
|
|
38
|
+
return jsonLdErrors.map(error => {
|
|
39
|
+
return {
|
|
40
|
+
validator: 'json-ld',
|
|
41
|
+
path: error.path,
|
|
42
|
+
message: error.message,
|
|
43
|
+
lineNumber: getLineNumberFromJsonLDPath(inputObject, error.path),
|
|
44
|
+
};
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// STEP 3: EXPAND
|
|
49
|
+
/** @type {LH.StructuredData.ExpandedSchemaRepresentation|null} */
|
|
50
|
+
let expandedObj = null;
|
|
51
|
+
try {
|
|
52
|
+
expandedObj = await expandAsync(inputObject);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
return [{
|
|
55
|
+
validator: 'json-ld-expand',
|
|
56
|
+
message: error.message,
|
|
57
|
+
}];
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// STEP 4: VALIDATE SCHEMA
|
|
61
|
+
const schemaOrgErrors = validateSchemaOrg(expandedObj);
|
|
62
|
+
|
|
63
|
+
if (schemaOrgErrors.length) {
|
|
64
|
+
return schemaOrgErrors.map(error => {
|
|
65
|
+
return {
|
|
66
|
+
validator: 'schema-org',
|
|
67
|
+
path: error.path,
|
|
68
|
+
message: error.message,
|
|
69
|
+
lineNumber: error.path ? getLineNumberFromJsonLDPath(inputObject, error.path) : null,
|
|
70
|
+
validTypes: error.validTypes,
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return [];
|
|
76
|
+
};
|
|
77
|
+
|
|
@@ -44,7 +44,7 @@ function almostEqual(a, b) {
|
|
|
44
44
|
/**
|
|
45
45
|
* Merge touching rects based on what appears as one tappable area to the user.
|
|
46
46
|
* @param {LH.Artifacts.Rect[]} clientRects
|
|
47
|
-
* @
|
|
47
|
+
* @returns {LH.Artifacts.Rect[]}
|
|
48
48
|
*/
|
|
49
49
|
function mergeTouchingClientRects(clientRects) {
|
|
50
50
|
for (let i = 0; i < clientRects.length; i++) {
|