Merge branch 'sketch-preview-files' into 'master'
Load a preview of Sketch 43 files See merge request !10470
This commit is contained in:
commit
c713292992
|
@ -0,0 +1,73 @@
|
||||||
|
import JSZip from 'jszip';
|
||||||
|
import JSZipUtils from 'jszip-utils';
|
||||||
|
|
||||||
|
export default class SketchLoader {
|
||||||
|
constructor(container) {
|
||||||
|
this.container = container;
|
||||||
|
this.loadingIcon = this.container.querySelector('.js-loading-icon');
|
||||||
|
|
||||||
|
this.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
load() {
|
||||||
|
return this.getZipFile()
|
||||||
|
.then(data => JSZip.loadAsync(data))
|
||||||
|
.then(asyncResult => asyncResult.files['previews/preview.png'].async('uint8array'))
|
||||||
|
.then((content) => {
|
||||||
|
const url = window.URL || window.webkitURL;
|
||||||
|
const blob = new Blob([new Uint8Array(content)], {
|
||||||
|
type: 'image/png',
|
||||||
|
});
|
||||||
|
const previewUrl = url.createObjectURL(blob);
|
||||||
|
|
||||||
|
this.render(previewUrl);
|
||||||
|
})
|
||||||
|
.catch(this.error.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
getZipFile() {
|
||||||
|
return new JSZip.external.Promise((resolve, reject) => {
|
||||||
|
JSZipUtils.getBinaryContent(this.container.dataset.endpoint, (err, data) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render(previewUrl) {
|
||||||
|
const previewLink = document.createElement('a');
|
||||||
|
const previewImage = document.createElement('img');
|
||||||
|
|
||||||
|
previewLink.href = previewUrl;
|
||||||
|
previewLink.target = '_blank';
|
||||||
|
previewImage.src = previewUrl;
|
||||||
|
previewImage.className = 'img-responsive';
|
||||||
|
|
||||||
|
previewLink.appendChild(previewImage);
|
||||||
|
this.container.appendChild(previewLink);
|
||||||
|
|
||||||
|
this.removeLoadingIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
const errorMsg = document.createElement('p');
|
||||||
|
|
||||||
|
errorMsg.className = 'prepend-top-default append-bottom-default text-center';
|
||||||
|
errorMsg.textContent = `
|
||||||
|
Cannot show preview. For previews on sketch files, they must have the file format
|
||||||
|
introduced by Sketch version 43 and above.
|
||||||
|
`;
|
||||||
|
this.container.appendChild(errorMsg);
|
||||||
|
|
||||||
|
this.removeLoadingIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeLoadingIcon() {
|
||||||
|
if (this.loadingIcon) {
|
||||||
|
this.loadingIcon.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* eslint-disable no-new */
|
||||||
|
import SketchLoader from './sketch';
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const el = document.getElementById('js-sketch-viewer');
|
||||||
|
|
||||||
|
new SketchLoader(el);
|
||||||
|
});
|
|
@ -50,6 +50,10 @@ class Blob < SimpleDelegator
|
||||||
text? && language&.name == 'Jupyter Notebook'
|
text? && language&.name == 'Jupyter Notebook'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def sketch?
|
||||||
|
binary? && extname.downcase.delete('.') == 'sketch'
|
||||||
|
end
|
||||||
|
|
||||||
def size_within_svg_limits?
|
def size_within_svg_limits?
|
||||||
size <= MAXIMUM_SVG_SIZE
|
size <= MAXIMUM_SVG_SIZE
|
||||||
end
|
end
|
||||||
|
@ -69,6 +73,8 @@ class Blob < SimpleDelegator
|
||||||
'image'
|
'image'
|
||||||
elsif ipython_notebook?
|
elsif ipython_notebook?
|
||||||
'notebook'
|
'notebook'
|
||||||
|
elsif sketch?
|
||||||
|
'sketch'
|
||||||
elsif text?
|
elsif text?
|
||||||
'text'
|
'text'
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
- content_for :page_specific_javascripts do
|
||||||
|
= page_specific_javascript_bundle_tag('common_vue')
|
||||||
|
= page_specific_javascript_bundle_tag('sketch_viewer')
|
||||||
|
|
||||||
|
.file-content#js-sketch-viewer{ data: { endpoint: namespace_project_raw_path(@project.namespace, @project, @id) } }
|
||||||
|
.js-loading-icon.text-center.prepend-top-default.append-bottom-default.js-loading-icon{ 'aria-label' => 'Loading Sketch preview' }
|
||||||
|
= icon('spinner spin 2x', 'aria-hidden' => 'true');
|
|
@ -326,3 +326,21 @@
|
||||||
:why: https://github.com/domenic/opener/blob/1.4.3/LICENSE.txt
|
:why: https://github.com/domenic/opener/blob/1.4.3/LICENSE.txt
|
||||||
:versions: []
|
:versions: []
|
||||||
:when: 2017-02-21 22:33:41.729629000 Z
|
:when: 2017-02-21 22:33:41.729629000 Z
|
||||||
|
- - :approve
|
||||||
|
- jszip
|
||||||
|
- :who: Phil Hughes
|
||||||
|
:why: https://github.com/Stuk/jszip/blob/master/LICENSE.markdown
|
||||||
|
:versions: []
|
||||||
|
:when: 2017-04-05 10:38:46.275721000 Z
|
||||||
|
- - :approve
|
||||||
|
- jszip-utils
|
||||||
|
- :who: Phil Hughes
|
||||||
|
:why: https://github.com/Stuk/jszip-utils/blob/master/LICENSE.markdown
|
||||||
|
:versions: []
|
||||||
|
:when: 2017-04-05 10:39:32.676232000 Z
|
||||||
|
- - :approve
|
||||||
|
- pako
|
||||||
|
- :who: Phil Hughes
|
||||||
|
:why: https://github.com/nodeca/pako/blob/master/LICENSE
|
||||||
|
:versions: []
|
||||||
|
:when: 2017-04-05 10:43:45.897720000 Z
|
||||||
|
|
|
@ -37,6 +37,7 @@ var config = {
|
||||||
monitoring: './monitoring/monitoring_bundle.js',
|
monitoring: './monitoring/monitoring_bundle.js',
|
||||||
network: './network/network_bundle.js',
|
network: './network/network_bundle.js',
|
||||||
notebook_viewer: './blob/notebook_viewer.js',
|
notebook_viewer: './blob/notebook_viewer.js',
|
||||||
|
sketch_viewer: './blob/sketch_viewer.js',
|
||||||
profile: './profile/profile_bundle.js',
|
profile: './profile/profile_bundle.js',
|
||||||
protected_branches: './protected_branches/protected_branches_bundle.js',
|
protected_branches: './protected_branches/protected_branches_bundle.js',
|
||||||
snippet: './snippet/snippet_bundle.js',
|
snippet: './snippet/snippet_bundle.js',
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
"jquery": "^2.2.1",
|
"jquery": "^2.2.1",
|
||||||
"jquery-ujs": "^1.2.1",
|
"jquery-ujs": "^1.2.1",
|
||||||
"js-cookie": "^2.1.3",
|
"js-cookie": "^2.1.3",
|
||||||
|
"jszip": "^3.1.3",
|
||||||
|
"jszip-utils": "^0.0.2",
|
||||||
"mousetrap": "^1.4.6",
|
"mousetrap": "^1.4.6",
|
||||||
"pikaday": "^1.5.1",
|
"pikaday": "^1.5.1",
|
||||||
"raphael": "^2.2.7",
|
"raphael": "^2.2.7",
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
/* eslint-disable no-new */
|
||||||
|
import JSZip from 'jszip';
|
||||||
|
import SketchLoader from '~/blob/sketch';
|
||||||
|
|
||||||
|
describe('Sketch viewer', () => {
|
||||||
|
const generateZipFileArrayBuffer = (zipFile, resolve, done) => {
|
||||||
|
zipFile
|
||||||
|
.generateAsync({ type: 'arrayBuffer' })
|
||||||
|
.then((content) => {
|
||||||
|
resolve(content);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
done();
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
preloadFixtures('static/sketch_viewer.html.raw');
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
loadFixtures('static/sketch_viewer.html.raw');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with error message', () => {
|
||||||
|
beforeEach((done) => {
|
||||||
|
spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve, reject) => {
|
||||||
|
reject();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
new SketchLoader(document.getElementById('js-sketch-viewer'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders error message', () => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('#js-sketch-viewer p'),
|
||||||
|
).not.toBeNull();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
document.querySelector('#js-sketch-viewer p').textContent.trim(),
|
||||||
|
).toContain('Cannot show preview.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes render the loading icon', () => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('.js-loading-icon'),
|
||||||
|
).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('success', () => {
|
||||||
|
beforeEach((done) => {
|
||||||
|
spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve) => {
|
||||||
|
const zipFile = new JSZip();
|
||||||
|
zipFile.folder('previews')
|
||||||
|
.file('preview.png', 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAA1JREFUeNoBAgD9/wAAAAIAAVMrnDAAAAAASUVORK5CYII=', {
|
||||||
|
base64: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
generateZipFileArrayBuffer(zipFile, resolve, done);
|
||||||
|
}));
|
||||||
|
|
||||||
|
new SketchLoader(document.getElementById('js-sketch-viewer'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not render error message', () => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('#js-sketch-viewer p'),
|
||||||
|
).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes render the loading icon', () => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('.js-loading-icon'),
|
||||||
|
).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders preview img', () => {
|
||||||
|
const img = document.querySelector('#js-sketch-viewer img');
|
||||||
|
|
||||||
|
expect(img).not.toBeNull();
|
||||||
|
expect(img.classList.contains('img-responsive')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders link to image', () => {
|
||||||
|
const img = document.querySelector('#js-sketch-viewer img');
|
||||||
|
const link = document.querySelector('#js-sketch-viewer a');
|
||||||
|
|
||||||
|
expect(link.href).toBe(img.src);
|
||||||
|
expect(link.target).toBe('_blank');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('incorrect file', () => {
|
||||||
|
beforeEach((done) => {
|
||||||
|
spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve) => {
|
||||||
|
const zipFile = new JSZip();
|
||||||
|
|
||||||
|
generateZipFileArrayBuffer(zipFile, resolve, done);
|
||||||
|
}));
|
||||||
|
|
||||||
|
new SketchLoader(document.getElementById('js-sketch-viewer'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders error message', () => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('#js-sketch-viewer p'),
|
||||||
|
).not.toBeNull();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
document.querySelector('#js-sketch-viewer p').textContent.trim(),
|
||||||
|
).toContain('Cannot show preview.');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,2 @@
|
||||||
|
.file-content#js-sketch-viewer{ data: { endpoint: '/test_sketch_file.sketch' } }
|
||||||
|
.js-loading-icon
|
|
@ -67,6 +67,20 @@ describe Blob do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#sketch?' do
|
||||||
|
it 'is falsey with image extension' do
|
||||||
|
git_blob = Gitlab::Git::Blob.new(name: "design.png")
|
||||||
|
|
||||||
|
expect(described_class.decorate(git_blob)).not_to be_sketch
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'is truthy with sketch extension' do
|
||||||
|
git_blob = Gitlab::Git::Blob.new(name: "design.sketch")
|
||||||
|
|
||||||
|
expect(described_class.decorate(git_blob)).to be_sketch
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#video?' do
|
describe '#video?' do
|
||||||
it 'is falsey with image extension' do
|
it 'is falsey with image extension' do
|
||||||
git_blob = Gitlab::Git::Blob.new(name: 'image.png')
|
git_blob = Gitlab::Git::Blob.new(name: 'image.png')
|
||||||
|
@ -92,7 +106,8 @@ describe Blob do
|
||||||
language: nil,
|
language: nil,
|
||||||
lfs_pointer?: false,
|
lfs_pointer?: false,
|
||||||
svg?: false,
|
svg?: false,
|
||||||
text?: false
|
text?: false,
|
||||||
|
binary?: false
|
||||||
)
|
)
|
||||||
|
|
||||||
described_class.decorate(double).tap do |blob|
|
described_class.decorate(double).tap do |blob|
|
||||||
|
@ -135,6 +150,11 @@ describe Blob do
|
||||||
blob = stubbed_blob(text?: true, ipython_notebook?: true)
|
blob = stubbed_blob(text?: true, ipython_notebook?: true)
|
||||||
expect(blob.to_partial_path(project)).to eq 'notebook'
|
expect(blob.to_partial_path(project)).to eq 'notebook'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'handles Sketch files' do
|
||||||
|
blob = stubbed_blob(text?: true, sketch?: true, binary?: true)
|
||||||
|
expect(blob.to_partial_path(project)).to eq 'sketch'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#size_within_svg_limits?' do
|
describe '#size_within_svg_limits?' do
|
||||||
|
|
38
yarn.lock
38
yarn.lock
|
@ -1245,6 +1245,10 @@ core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
|
||||||
version "2.4.1"
|
version "2.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
|
||||||
|
|
||||||
|
core-js@~2.3.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
|
@ -1581,6 +1585,10 @@ es6-map@^0.1.3:
|
||||||
es6-symbol "~3.1.0"
|
es6-symbol "~3.1.0"
|
||||||
event-emitter "~0.3.4"
|
event-emitter "~0.3.4"
|
||||||
|
|
||||||
|
es6-promise@~3.0.2:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
|
||||||
|
|
||||||
es6-promise@~4.0.3:
|
es6-promise@~4.0.3:
|
||||||
version "4.0.5"
|
version "4.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.0.5.tgz#7882f30adde5b240ccfa7f7d78c548330951ae42"
|
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.0.5.tgz#7882f30adde5b240ccfa7f7d78c548330951ae42"
|
||||||
|
@ -2335,6 +2343,10 @@ ignore@^3.2.0:
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.2.tgz#1c51e1ef53bab6ddc15db4d9ac4ec139eceb3410"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.2.tgz#1c51e1ef53bab6ddc15db4d9ac4ec139eceb3410"
|
||||||
|
|
||||||
|
immediate@~3.0.5:
|
||||||
|
version "3.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||||
|
|
||||||
imurmurhash@^0.1.4:
|
imurmurhash@^0.1.4:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
|
@ -2764,6 +2776,20 @@ jsprim@^1.2.2:
|
||||||
json-schema "0.2.3"
|
json-schema "0.2.3"
|
||||||
verror "1.3.6"
|
verror "1.3.6"
|
||||||
|
|
||||||
|
jszip-utils@^0.0.2:
|
||||||
|
version "0.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/jszip-utils/-/jszip-utils-0.0.2.tgz#457d5cbca60a1c2e0706e9da2b544e8e7bc50bf8"
|
||||||
|
|
||||||
|
jszip@^3.1.3:
|
||||||
|
version "3.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.1.3.tgz#8a920403b2b1651c0fc126be90192d9080957c37"
|
||||||
|
dependencies:
|
||||||
|
core-js "~2.3.0"
|
||||||
|
es6-promise "~3.0.2"
|
||||||
|
lie "~3.1.0"
|
||||||
|
pako "~1.0.2"
|
||||||
|
readable-stream "~2.0.6"
|
||||||
|
|
||||||
karma-coverage-istanbul-reporter@^0.2.0:
|
karma-coverage-istanbul-reporter@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-0.2.0.tgz#5766263338adeb0026f7e4ac7a89a5f056c5642c"
|
resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-0.2.0.tgz#5766263338adeb0026f7e4ac7a89a5f056c5642c"
|
||||||
|
@ -2868,6 +2894,12 @@ levn@^0.3.0, levn@~0.3.0:
|
||||||
prelude-ls "~1.1.2"
|
prelude-ls "~1.1.2"
|
||||||
type-check "~0.3.2"
|
type-check "~0.3.2"
|
||||||
|
|
||||||
|
lie@~3.1.0:
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
|
||||||
|
dependencies:
|
||||||
|
immediate "~3.0.5"
|
||||||
|
|
||||||
load-json-file@^1.0.0:
|
load-json-file@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
|
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
|
||||||
|
@ -3349,6 +3381,10 @@ pako@~0.2.0:
|
||||||
version "0.2.9"
|
version "0.2.9"
|
||||||
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
|
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
|
||||||
|
|
||||||
|
pako@~1.0.2:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.5.tgz#d2205dfe5b9da8af797e7c163db4d1f84e4600bc"
|
||||||
|
|
||||||
parse-asn1@^5.0.0:
|
parse-asn1@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.0.0.tgz#35060f6d5015d37628c770f4e091a0b5a278bc23"
|
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.0.0.tgz#35060f6d5015d37628c770f4e091a0b5a278bc23"
|
||||||
|
@ -3661,7 +3697,7 @@ readable-stream@~1.0.2:
|
||||||
isarray "0.0.1"
|
isarray "0.0.1"
|
||||||
string_decoder "~0.10.x"
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
readable-stream@~2.0.0:
|
readable-stream@~2.0.0, readable-stream@~2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Reference in New Issue