Page MenuHomeSoftware Heritage

D5819.id21470.diff
No OneTemporary

D5819.id21470.diff

diff --git a/assets/config/webpack.config.development.js b/assets/config/webpack.config.development.js
--- a/assets/config/webpack.config.development.js
+++ b/assets/config/webpack.config.development.js
@@ -344,6 +344,11 @@
outputPath: 'img/thirdParty/'
}
}]
+ },
+ {
+ test: /\.ya?ml$/,
+ type: 'json',
+ use: 'yaml-loader'
}
],
// tell webpack to not parse already minified files to speedup build process
diff --git a/assets/src/bundles/browse/swhid-utils.js b/assets/src/bundles/browse/swhid-utils.js
--- a/assets/src/bundles/browse/swhid-utils.js
+++ b/assets/src/bundles/browse/swhid-utils.js
@@ -85,9 +85,15 @@
$('#swh-identifiers').css('width', '1000px');
}
+ // prevent automatic closing of SWHIDs tab during guided tour
+ // as it is displayed programmatically
+ function clickScreenToCloseFilter() {
+ return $('.introjs-overlay').length > 0;
+ }
+
const tabSlideOptions = {
tabLocation: 'right',
- clickScreenToCloseFilters: ['.ui-slideouttab-panel', '.modal'],
+ clickScreenToCloseFilters: [clickScreenToCloseFilter, '.ui-slideouttab-panel', '.modal'],
offset: function() {
const width = $(window).width();
if (width < BREAKPOINT_SM) {
diff --git a/assets/src/bundles/guided_tour/guided-tour-steps.yaml b/assets/src/bundles/guided_tour/guided-tour-steps.yaml
new file mode 100644
--- /dev/null
+++ b/assets/src/bundles/guided_tour/guided-tour-steps.yaml
@@ -0,0 +1,155 @@
+# Copyright (C) 2021 The Software Heritage developers
+# See the AUTHORS file at the top-level directory of this distribution
+# License: GNU Affero General Public License version 3, or any later version
+# See top-level LICENSE file for more information
+
+homepage:
+ - title: Welcome to the guided tour !
+ intro: |
+ This guided tour will showcase Software Heritage web application
+ features in order to help you navigate into the archive
+
+ - title: Homepage
+ intro: |
+ This is the entry point of Software Heritage web application,
+ let's see what we can do from here.
+
+ - element: .swh-search-box
+ title: Search archived software origins
+ intro: |
+ An origin corresponds to a location from which a coherent set of
+ source codes has been obtained, like a git repository, a directory
+ containing tarballs, etc.<br/><br/>
+ Software origins are identified by URLs (git clone URLs for instance).<br/><br/>
+ That form enables to search for terms in the full set of archived software
+ origin URLs. You will be redirected to a dedicated interface displaying search
+ results. Clicking on an origin URL will then take you to the source code browsing
+ interface. If you enter a complete archived origin URL, you will be immediately
+ redirected to its source code browsing interface.
+
+ - element: .swh-origin-save-link
+ title: Save code now
+ intro: |
+ If you haven't found the software origin you were looking for, you can use the
+ Save Code Now interface to submit a save request that will be immediately processed.
+
+ - element: .swh-vault-link
+ title: Downloads from the vault
+ intro: |
+ Show the list of downloads you requested from the Software Heritage Vault
+ while browsing the archive. <br/>
+ Those downloads correspond to tarballs containing source directories
+ archived by Software Heritage. <br/>
+ That list of downloads is stored in your browser local storage so it
+ will be persistent across your visits.
+
+ - element: .swh-help-link
+ title: Launch guided tour
+ intro: Replay that guided tour.
+
+ - element: "#swh-login"
+ title: Login or register
+ intro: |
+ Come and join our users community with a Software Heritage account.
+ Click here and register in less than 30 seconds.
+ When authenticated, you can benefit from extended features like a a higher
+ rate-limit quota for the Web API.<br/><br/>
+ If you are already logged in, that link will take you to your user
+ profile interface where you can generate bearer token for Web API
+ authentication.
+
+ - element: "#swh-web-api-link"
+ title: Software Heritage Web API
+ intro: |
+ In the Software Heritage Web API documentation you will find the complete list
+ of endpoints and how to use each one with a detailed example.<br/>
+ Please note that the Web API can also be queried from your web browser
+ through a dedicated HTML interface displaying query results.
+
+ - title: Browsing source code of an archived software origin
+ intro: |
+ Come on in, let's introduce the Web UI to browse the content of an
+ archived software origin.
+
+browseOrigin:
+ - title: Browse source code of an archived software origin
+ intro: |
+ You just arrived into the first view of the archived source code of an origin.
+ The displayed source code files are taken from the most recent snapshot taken by
+ Software Heritage. By default, the content of the HEAD branch is displayed.
+ Continue your journey and dive deeper into the code and its development history.
+
+ - element: "#swh-browse-code-nav-link"
+ title: Browse source code
+ intro: |
+ Here you can browse the source code of a software origin. <br/>
+ Clicking on the Code tab will always bring you back to the code in the HEAD branch.
+ position: bottom
+
+ - element: "#swh-browse-snapshot-branches-nav-link"
+ title: Browse branches
+ intro: |
+ Here you can browse the list of branches for a software origin. <br/>
+ Links are offered to browse the source code contained in each branch.
+ position: bottom
+
+ - element: "#swh-browse-snapshot-releases-nav-link"
+ title: Browse releases
+ intro: |
+ Here you can browse the list of releases for a software origin. <br/>
+ Links are offered to browse the source code contained in each release. <br/>
+ Please note that for git origins, only annotated tags are considered as releases.
+ For non annotated git tags, you can browse them in the Branches tab.
+ position: bottom
+
+ - element: "#swh-browse-origin-visits-nav-link"
+ title: Browse origin visits
+ intro: |
+ Here you can find when did Software Heritage captured the source code.
+ These visits are called snapshots and visualized in various ways: timeline,
+ calendar and simple list.
+ Like with a way-back machine, you can travel in time and see the code as it was
+ when crawled by Software Heritage.
+ position: bottom
+
+ - element: "#swh-branches-releases-dd"
+ title: Switch between branches and releases
+ intro: |
+ You can easily switch between different branches and releases using this dropdown.
+ position: bottom
+
+ - element: "#swh-breadcrumbs-container"
+ title: Current navigation path
+ intro: |
+ You can see here the current path you are taking in the code, which will make it
+ easier to navigate back.
+ position: bottom
+
+ - element: "#swhids-handle"
+ title: Get SWHIDs of browsed objects
+ intro: |
+ When clicking on this handle, a tab will be displayed containing Software Heritage
+ IDentifiers of currently browsed objects.
+ position: left
+
+ - element: .swhid-ui
+ title: Copy SWHID for a given browsed object
+ intro: |
+ You can easily copy to clipboard a SWHID or its resolve URL using the dedicated
+ buttons on the bottom-right.
+ position: left
+
+browseContent:
+ - element: .hljs-ln-numbers[data-line-number="1"]
+ title: Highlight a source code line
+ intro: |
+ Click on the line number to highlight the corresponding line of code,
+ then click on Next
+ position: left
+
+ - element: .hljs-ln-numbers[data-line-number="10"]
+ title: Highlight a range of source code lines,
+ intro: |
+ Hold Shift and click on the line number to highlight a range of
+ source code lines
+ position: left
diff --git a/assets/src/bundles/guided_tour/index.js b/assets/src/bundles/guided_tour/index.js
new file mode 100644
--- /dev/null
+++ b/assets/src/bundles/guided_tour/index.js
@@ -0,0 +1,132 @@
+/**
+ * Copyright (C) 2021 The Software Heritage developers
+ * See the AUTHORS file at the top-level directory of this distribution
+ * License: GNU Affero General Public License version 3, or any later version
+ * See top-level LICENSE file for more information
+ */
+
+import * as introJs from 'intro.js';
+import 'intro.js/introjs.css';
+import './swh-introjs.css';
+import guidedTourSteps from './guided-tour-steps.yaml';
+
+let guidedTour = [];
+let tour = null;
+
+// init guided tour configuration when page loads in order
+// to hack on it in cypress tests
+$(() => {
+ // tour is defined by an array of objects containing:
+ // - URL of page to run a tour
+ // - intro.js configuration with tour steps
+ // - optional intro.js callback function for tour interactivity
+ guidedTour = [
+ {
+ url: Urls.swh_web_homepage(),
+ introJsOptions: {
+ disableInteraction: true,
+ scrollToElement: false,
+ steps: guidedTourSteps.homepage
+ }
+ },
+ {
+ url: `${Urls.browse_origin_directory()}?origin_url=https://github.com/memononen/libtess2`,
+ introJsOptions: {
+ disableInteraction: true,
+ scrollToElement: false,
+ steps: guidedTourSteps.browseOrigin
+ },
+ onBeforeChange: function(targetElement) {
+ // open SWHIDs tab before its tour step
+ if (targetElement.className.indexOf('swhid-ui') !== -1) {
+ if (!$('#swh-identifiers').tabSlideOut('isOpen')) {
+ $('.introjs-helperLayer, .introjs-tooltipReferenceLayer').hide();
+ $('#swh-identifiers').tabSlideOut('open');
+ setTimeout(() => {
+ $('.introjs-helperLayer, .introjs-tooltipReferenceLayer').show();
+ tour.nextStep();
+ }, 500);
+ return false;
+ }
+ }
+ return true;
+ }
+ },
+ {
+ url: `${Urls.browse_origin_content()}?origin_url=https://github.com/memononen/libtess2&path=README.md`,
+ introJsOptions: {
+ steps: guidedTourSteps.browseContent
+ },
+ onBeforeChange: function(targetElement) {
+ // forbid move to next step until user clicks on line numbers
+ if (targetElement.dataset.lineNumber === '10') {
+ const background = $('.hljs-ln-numbers[data-line-number="1"]').css('background-color');
+ return background !== 'rgba(0, 0, 0, 0)';
+ }
+ return true;
+ }
+ }
+ ];
+ // init guided tour on page if guided_tour query parameter is present
+ const searchParams = new URLSearchParams(window.location.search);
+ if (searchParams && searchParams.has('guided_tour')) {
+ initGuidedTour(parseInt(searchParams.get('guided_tour')));
+ }
+});
+
+export function getGuidedTour() {
+ return guidedTour;
+}
+
+export function initGuidedTour(page = 0) {
+ if (page >= guidedTour.length) {
+ return;
+ }
+ const pageUrl = new URL(window.location.origin + guidedTour[page].url);
+ const currentUrl = new URL(window.location.href);
+ const guidedTourNext = currentUrl.searchParams.get('guided_tour_next');
+ currentUrl.searchParams.delete('guided_tour');
+ currentUrl.searchParams.delete('guided_tour_next');
+ const pageUrlStr = decodeURIComponent(pageUrl.toString());
+ const currentUrlStr = decodeURIComponent(currentUrl.toString());
+ if (currentUrlStr !== pageUrlStr) {
+ // go to guided tour page URL if current one does not match
+ pageUrl.searchParams.set('guided_tour', page);
+ if (page === 0) {
+ // user will be redirected to the page he was at the end of the tour
+ pageUrl.searchParams.set('guided_tour_next', currentUrlStr);
+ }
+ window.location = decodeURIComponent(pageUrl.toString());
+ } else {
+ // create intro.js guided tour and configure it
+ tour = introJs().setOptions(guidedTour[page].introJsOptions);
+ tour.setOption('showBullets', false);
+ if (page < guidedTour.length - 1) {
+ // if not on the last page of the tour, rename next button label
+ // and schedule next page loading when clicking on it
+ tour.setOption('doneLabel', 'Next page')
+ .oncomplete(() => {
+ const nextPageUrl = new URL(window.location.origin + guidedTour[page + 1].url);
+ nextPageUrl.searchParams.set('guided_tour', page + 1);
+ if (guidedTourNext) {
+ nextPageUrl.searchParams.set('guided_tour_next', guidedTourNext);
+ }
+ window.location.href = decodeURIComponent(nextPageUrl.toString());
+ });
+ } else {
+ tour.oncomplete(() => {
+ if (guidedTourNext) {
+ window.location.href = guidedTourNext;
+ }
+ });
+ }
+ if (guidedTour[page].hasOwnProperty('onBeforeChange')) {
+ tour.onbeforechange(guidedTour[page].onBeforeChange);
+ }
+ setTimeout(() => {
+ // run guided tour with a little delay to ensure every asynchronous operations
+ // after page load have been executed
+ tour.start();
+ }, 500);
+ }
+};
diff --git a/assets/src/bundles/guided_tour/swh-introjs.css b/assets/src/bundles/guided_tour/swh-introjs.css
new file mode 100644
--- /dev/null
+++ b/assets/src/bundles/guided_tour/swh-introjs.css
@@ -0,0 +1,18 @@
+/**
+ * Copyright (C) 2021 The Software Heritage developers
+ * See the AUTHORS file at the top-level directory of this distribution
+ * License: GNU Affero General Public License version 3, or any later version
+ * See top-level LICENSE file for more information
+ */
+
+.introjs-tooltip {
+ min-width: 500px;
+}
+
+.introjs-tooltip.introjs-floating {
+ /* center tooltip not attached to a DOM element to the center of the screen */
+ position: fixed !important;
+ top: 50% !important;
+ margin: 0 auto !important;
+ transform: translate(-50%, -50%) !important;
+}
diff --git a/cypress/integration/guided-tour.spec.js b/cypress/integration/guided-tour.spec.js
new file mode 100644
--- /dev/null
+++ b/cypress/integration/guided-tour.spec.js
@@ -0,0 +1,103 @@
+/**
+ * Copyright (C) 2021 The Software Heritage developers
+ * See the AUTHORS file at the top-level directory of this distribution
+ * License: GNU Affero General Public License version 3, or any later version
+ * See top-level LICENSE file for more information
+ */
+
+describe('Guided Tour Tests', function() {
+
+ // utility function to traverse all guided tour steps in a page
+ const clickNextStepButtons = () => {
+ cy.get('.introjs-nextbutton').then($button => {
+ const buttonText = $button.text();
+ if (buttonText === 'Next') {
+ cy.get('.introjs-nextbutton')
+ .click()
+ .then(() => {
+ cy.get('.introjs-tooltip').should('be.visible');
+ clickNextStepButtons();
+ });
+ }
+ });
+ };
+
+ it('should start UI guided tour when clicking on help button', function() {
+ cy.ambassadorLogin();
+ cy.visit('/');
+ cy.get('.swh-help-link')
+ .click();
+
+ cy.get('.introjs-tooltip')
+ .should('exist');
+ });
+
+ it('should change guided tour page after current page steps', function() {
+ cy.ambassadorLogin();
+ cy.visit('/');
+
+ cy.get('.swh-help-link')
+ .click();
+
+ cy.url().then(url => {
+ clickNextStepButtons();
+ cy.get('.introjs-nextbutton')
+ .should('have.text', 'Next page')
+ .click();
+ cy.url().should('not.eq', url);
+ });
+
+ });
+
+ it('should automatically open SWHIDs tab on second page of the guided tour', function() {
+ const guidedTourPageIndex = 1;
+ cy.ambassadorLogin();
+ cy.visit('/').window().then(win => {
+ const guidedTour = win.swh.guided_tour.getGuidedTour();
+ // jump to third guided tour page
+ cy.visit(guidedTour[guidedTourPageIndex].url);
+ cy.window().then(win => {
+ // SWHIDs tab should be closed when tour begins
+ cy.get('.ui-slideouttab-open').should('not.exist');
+ // init guided tour on the page
+ win.swh.guided_tour.initGuidedTour(guidedTourPageIndex);
+ clickNextStepButtons();
+ // SWHIDs tab should be opened when tour begins
+ cy.get('.ui-slideouttab-open').should('exist');
+ });
+ });
+ });
+
+ it('should stay at first step while line numbers not clicked on content view tour', function() {
+ const guidedTourPageIndex = 2;
+ cy.ambassadorLogin();
+ // jump to third guided tour page
+ cy.visit('/').window().then(win => {
+ const guidedTour = win.swh.guided_tour.getGuidedTour();
+ cy.visit(guidedTour[guidedTourPageIndex].url);
+ cy.window().then(win => {
+ // init guided tour on the page
+ win.swh.guided_tour.initGuidedTour(guidedTourPageIndex);
+
+ cy.get('.introjs-tooltip-header').then($header => {
+ const headerText = $header.text();
+ // user did not click yet on line numbers and should stay
+ // blocked on first step of the tour
+ cy.get('.introjs-nextbutton')
+ .click();
+ cy.get('.introjs-tooltip-header')
+ .should('have.text', headerText);
+ // click on line numbers
+ cy.get('.hljs-ln-numbers[data-line-number="1"]')
+ .click();
+ // check move to next step is allowed
+ cy.get('.introjs-nextbutton')
+ .click();
+ cy.get('.introjs-tooltip-header')
+ .should('not.have.text', headerText);
+
+ });
+ });
+ });
+ });
+});
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"highlightjs-line-numbers.js": "^2.8.0",
"html-encoder-decoder": "^1.3.9",
"iframe-resizer": "^4.3.2",
+ "intro.js": "^4.1.0",
"jquery": "^3.6.0",
"js-cookie": "^2.2.1",
"js-year-calendar": "^1.0.2",
@@ -114,7 +115,8 @@
"webpack": "^5.41.0",
"webpack-bundle-tracker": "^1.1.0",
"webpack-cli": "^4.7.2",
- "webpack-dev-server": "^3.11.2"
+ "webpack-dev-server": "^3.11.2",
+ "yaml-loader": "^0.6.0"
},
"resolutions": {
"jquery": "^3.6.0"
diff --git a/swh/web/templates/homepage.html b/swh/web/templates/homepage.html
--- a/swh/web/templates/homepage.html
+++ b/swh/web/templates/homepage.html
@@ -24,7 +24,7 @@
{% block content %}
-<div class="p-3 swh-background-gray">
+<div class="p-3 swh-search-box swh-background-gray">
<h4>Search</h4>
{% include "includes/origin-search-form.html" %}
@@ -32,7 +32,7 @@
<p class="text-right">
... or check our
-<a style="color: #e20026;" href="{% url 'api-1-homepage' %}">
+<a id="swh-web-api-link" style="color: #e20026;" href="{% url 'api-1-homepage' %}">
<i style="color: #e20026;" class="nav-icon mdi mdi-24px mdi-cogs"></i>Web API
</a>
</p>
diff --git a/swh/web/templates/includes/show-swhids.html b/swh/web/templates/includes/show-swhids.html
--- a/swh/web/templates/includes/show-swhids.html
+++ b/swh/web/templates/includes/show-swhids.html
@@ -11,9 +11,9 @@
<div id="swh-identifiers" style="display: none;">
{% if swhids_info|length > 1 %}
- <a id="right-handle" class="handle ui-slideouttab-handle ui-slideouttab-handle-rounded"><i class="mdi mdi-link-variant mdi-fw" aria-hidden="true"></i>Permalinks</a>
+ <a id="swhids-handle" class="handle ui-slideouttab-handle ui-slideouttab-handle-rounded"><i class="mdi mdi-link-variant mdi-fw" aria-hidden="true"></i>Permalinks</a>
{% else %}
- <a id="right-handle" class="handle ui-slideouttab-handle ui-slideouttab-handle-rounded"><i class="mdi mdi-link-variant mdi-fw" aria-hidden="true"></i>Permalink</a>
+ <a id="swhids-handle" class="handle ui-slideouttab-handle ui-slideouttab-handle-rounded"><i class="mdi mdi-link-variant mdi-fw" aria-hidden="true"></i>Permalink</a>
{% endif %}
<div id="swh-identifiers-content">
<p>
diff --git a/swh/web/templates/includes/top-navigation.html b/swh/web/templates/includes/top-navigation.html
--- a/swh/web/templates/includes/top-navigation.html
+++ b/swh/web/templates/includes/top-navigation.html
@@ -103,7 +103,7 @@
{% endif %}
{% endif %}
- <div class="flex-grow-1">
+ <div id="swh-breadcrumbs-container" class="flex-grow-1">
{% include "includes/breadcrumbs.html" %}
</div>
diff --git a/swh/web/templates/layout.html b/swh/web/templates/layout.html
--- a/swh/web/templates/layout.html
+++ b/swh/web/templates/layout.html
@@ -21,6 +21,7 @@
{% render_bundle 'vendors' %}
{% render_bundle 'webapp' %}
+ {% render_bundle 'guided_tour' %}
<script>
/*
@@ -119,23 +120,23 @@
{% if user.is_authenticated %}
Logged in as
{% if 'OIDC' in user.backend %}
- <a href="{% url 'oidc-profile' %}"><strong>{{ user.username }}</strong></a>,
- <a href="{% url 'oidc-logout' %}?next_path={% url 'logout' %}?remote_user=1">logout</a>
+ <a id="swh-login" href="{% url 'oidc-profile' %}"><strong>{{ user.username }}</strong></a>,
+ <a href= "{% url 'oidc-logout' %}?next_path={% url 'logout' %}?remote_user=1">logout</a>
{% else %}
- <strong>{{ user.username }}</strong>,
+ <strong id="swh-login">{{ user.username }}</strong>,
<a href="{{ logout_url }}">logout</a>
{% endif %}
{% elif oidc_enabled %}
{% if request.path != logout_url %}
- <a href="{% url 'oidc-login' %}?next_path={{ request.build_absolute_uri }}">login</a>
+ <a id="swh-login" href="{% url 'oidc-login' %}?next_path={{ request.build_absolute_uri }}">login</a>
{% else %}
- <a href="{% url 'oidc-login' %}">login</a>
+ <a id="swh-login" href="{% url 'oidc-login' %}">login</a>
{% endif %}
{% else %}
{% if request.path != logout_url %}
- <a href="{% url 'login' %}?next={{ request.build_absolute_uri }}">login</a>
+ <a id="swh-login" href="{% url 'login' %}?next={{ request.build_absolute_uri }}">login</a>
{% else %}
- <a href="{% url 'login' %}">login</a>
+ <a id="swh-login" href="{% url 'login' %}">login</a>
{% endif %}
{% endif %}
</li>
@@ -208,7 +209,11 @@
</a>
</li>
<li class="nav-item swh-help-item" title="How to browse the archive ?">
- <a href="{% url 'browse-help' %}" class="nav-link swh-help-link">
+ {% if user.is_authenticated and user.is_staff or "swh.ambassador" in user.get_all_permissions %}
+ <a href="#" class="nav-link swh-help-link" onclick="swh.guided_tour.initGuidedTour()">
+ {% else %}
+ <a href="{% url 'browse-help' %}" class="nav-link swh-help-link">
+ {% endif %}
<i style="color: #e20026;" class="nav-icon mdi mdi-24px mdi-help-circle"></i>
<p>Help</p>
</a>
diff --git a/yarn.lock b/yarn.lock
--- a/yarn.lock
+++ b/yarn.lock
@@ -7609,6 +7609,11 @@
resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9"
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
+intro.js@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/intro.js/-/intro.js-4.1.0.tgz#7e4ae5877df0c452b23d1fd96f2666eb87796b22"
+ integrity sha512-+Y+UsP+yvqqlEOjFExMBXKopn3nzwc91PaUl0SrvqiVs6ztko1DzfkoXR2AnfirZVZZhr5Aej6wlXRlvIkuMcA==
+
invariant@^2.2.2:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
@@ -13575,11 +13580,24 @@
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+yaml-loader@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/yaml-loader/-/yaml-loader-0.6.0.tgz#fe1c48b9f4803dace55a59a1474e790ba6ab1b48"
+ integrity sha512-1bNiLelumURyj+zvVHOv8Y3dpCri0F2S+DCcmps0pA1zWRLjS+FhZQg4o3aUUDYESh73+pKZNI18bj7stpReow==
+ dependencies:
+ loader-utils "^1.4.0"
+ yaml "^1.8.3"
+
yaml@^1.10.0, yaml@^1.7.2:
version "1.10.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e"
integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==
+yaml@^1.8.3:
+ version "1.10.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
yargs-parser@20.2.4, yargs-parser@^20.2.3:
version "20.2.4"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"

File Metadata

Mime Type
text/plain
Expires
Thu, Dec 19, 3:40 AM (17 h, 44 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3234660

Event Timeline