Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F7123351
D5819.id21470.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
24 KB
Subscribers
None
D5819.id21470.diff
View Options
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
Details
Attached
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
Attached To
D5819: assets/webapp: Add UI guided tour
Event Timeline
Log In to Comment