Merge branch 'master' into issue-1788

This commit is contained in:
Sean Yesmunt 2018-08-05 21:59:30 -04:00 committed by GitHub
commit 824c3fbc65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
52 changed files with 1343 additions and 357 deletions

View file

@ -38,6 +38,7 @@
"import/prefer-default-export": 0,
"no-return-assign": 0,
"react/require-default-props": 0,
"react/jsx-closing-tag-location": 0
"react/jsx-closing-tag-location": 0,
"jsx-a11y/no-noninteractive-element-to-interactive-role": 0
}
}

2
.gitignore vendored
View file

@ -5,4 +5,4 @@
yarn-error.log
package-lock.json
.idea/
/build/daemon.ver
/build/daemon*

View file

@ -6,12 +6,21 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
## [Unreleased]
### Added
* Wallet Encryption/Decryption user flows ([#1785](https://github.com/lbryio/lbry-desktop/pull/1785))
* Add FAQ to Publishing Area ([#1833](https://github.com/lbryio/lbry-desktop/pull/1833))
* Wallet Encryption/Decryption user flows ([#1785](https://github.com/lbryio/lbry-desktop/pull/1785))
* Add FAQ to Publishing Area ([#1833](https://github.com/lbryio/lbry-desktop/pull/1833))
* Better preview for content ([#620](https://github.com/lbryio/lbry-desktop/pull/620))
* Add new markdown and docx viewer ([#1826](https://github.com/lbryio/lbry-desktop/pull/1826))
* Add new viewer for human-readable text files ([#1826](https://github.com/lbryio/lbry-desktop/pull/1826))
* Add csv and json viewer ([#1410](https://github.com/lbryio/lbry-desktop/pull/1410))
### Changed
* Pass error message from spee.ch API during thumbnail upload ([#1840](https://github.com/lbryio/lbry-desktop/pull/1840))
* Use router pattern for rendering file viewer ([#1544](https://github.com/lbryio/lbry-desktop/pull/1544))
### Fixed
* **Wallet -> Get Credits** page now shows correct ShapeShift status when it's avialable ([#1836](https://github.com/lbryio/lbry-desktop/issues/1836))
* Fix middle click link error ([#1843](https://github.com/lbryio/lbry-desktop/issues/1843)}
* Problem with search auto-complete menu when scrolling over file viewer ([#1847](https://github.com/lbryio/lbry-desktop/issues/1847))
## [0.23.0] - 2018-07-25

View file

@ -1,6 +1,6 @@
{
"name": "LBRY",
"version": "0.23.0",
"version": "0.23.1",
"description": "A browser for the LBRY network, a digital marketplace controlled by its users.",
"keywords": [
"lbry"
@ -35,7 +35,9 @@
},
"dependencies": {
"bluebird": "^3.5.1",
"breakdance": "^3.0.1",
"classnames": "^2.2.5",
"codemirror": "^5.39.2",
"country-data": "^0.0.31",
"dom-scroll-into-view": "^1.2.1",
"electron-dl": "^1.11.0",
@ -51,6 +53,7 @@
"keytar": "^4.2.1",
"lbry-redux": "lbryio/lbry-redux#b4fffe863df316bc73183567ab978221ee623b8c",
"localforage": "^1.7.1",
"mammoth": "^1.4.6",
"mime": "^2.3.1",
"mixpanel-browser": "^2.17.1",
"moment": "^2.22.0",

View file

@ -1,4 +1,4 @@
import { app, BrowserWindow, dialog, screen } from 'electron';
import { app, BrowserWindow, dialog, shell, screen } from 'electron';
import isDev from 'electron-is-dev';
import windowStateKeeper from 'electron-window-state';
@ -123,6 +123,11 @@ export default appState => {
window.webContents.on('crashed', () => {
window = null;
});
window.webContents.on('new-window', (event, url) => {
event.preventDefault();
shell.openExternal(url);
});
return window;
};

View file

@ -11,9 +11,10 @@ type Props = {
showPlus: boolean,
isEstimate?: boolean,
large?: boolean,
plain?: boolean,
showLBC?: boolean,
fee?: boolean,
noStyle?: boolean,
inheritStyle?: boolean,
filePage?: boolean,
};
class CreditAmount extends React.PureComponent<Props> {
@ -22,6 +23,7 @@ class CreditAmount extends React.PureComponent<Props> {
showFree: false,
showFullPrice: false,
showPlus: false,
showLBC: true,
};
render() {
@ -33,9 +35,10 @@ class CreditAmount extends React.PureComponent<Props> {
showPlus,
large,
isEstimate,
plain,
noStyle,
fee,
showLBC,
inheritStyle,
filePage,
} = this.props;
const minimumRenderableAmount = 10 ** (-1 * precision);
@ -62,7 +65,7 @@ class CreditAmount extends React.PureComponent<Props> {
amountText = `+${amountText}`;
}
if (!plain) {
if (showLBC) {
amountText = `${amountText} ${__('LBC')}`;
}
@ -78,8 +81,8 @@ class CreditAmount extends React.PureComponent<Props> {
'credit-amount--free': !large && isFree,
'credit-amount--cost': !large && !isFree,
'credit-amount--large': large,
'credit-amount--plain': plain,
'credit-amount--no-style': noStyle,
'credit-amount--inherit': inheritStyle,
'credit-amount--file-page': filePage,
})}
>
{amountText}

View file

@ -4,9 +4,9 @@ import ReactDOMServer from 'react-dom/server';
import classnames from 'classnames';
import MarkdownPreview from 'component/common/markdown-preview';
import SimpleMDE from 'react-simplemde-editor';
import 'simplemde/dist/simplemde.min.css';
import 'simplemde/dist/simplemde.min.css'; // eslint-disable-line import/no-extraneous-dependencies
import Toggle from 'react-toggle';
import { openEditorMenu } from 'util/contextMenu';
import { openEditorMenu, stopContextMenu } from 'util/contextMenu';
type Props = {
name: string,
@ -23,6 +23,7 @@ type Props = {
children?: React.Node,
stretch?: boolean,
affixClass?: string, // class applied to prefix/postfix label
firstInList?: boolean, // at the top of a list, no padding top
};
export class FormField extends React.PureComponent<Props> {
@ -39,6 +40,7 @@ export class FormField extends React.PureComponent<Props> {
children,
stretch,
affixClass,
firstInList,
...inputProps
} = this.props;
@ -53,15 +55,10 @@ export class FormField extends React.PureComponent<Props> {
</select>
);
} else if (type === 'markdown') {
const stopContextMenu = event => {
event.preventDefault();
event.stopPropagation();
};
const handleEvents = {
contextmenu(codeMirror, event) {
openEditorMenu(event, codeMirror);
},
contextmenu: openEditorMenu,
};
input = (
<div className="form-field--SimpleMDE" onContextMenu={stopContextMenu}>
<SimpleMDE
@ -106,6 +103,7 @@ export class FormField extends React.PureComponent<Props> {
<div
className={classnames('form-field__input', {
'form-field--auto-height': type === 'markdown',
'form-field--first-item': firstInList,
})}
>
{prefix && (

View file

@ -92,9 +92,8 @@ class FileCard extends React.PureComponent<Props> {
onContextMenu={handleContextMenu}
>
<CardMedia thumbnail={thumbnail} />
<div className="card-media__internal-links">{showPrice && <FilePrice uri={uri} />}</div>
<div className="card__title-identity">
<div className="card__title--small">
<div className="card__title--small card__title--file-card">
<TruncatedText lines={3}>{title}</TruncatedText>
</div>
<div className="card__subtitle">
@ -103,13 +102,12 @@ class FileCard extends React.PureComponent<Props> {
) : (
<React.Fragment>
<UriIndicator uri={uri} link />
<div>
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
{fileInfo && <Icon icon={icons.LOCAL} />}
</div>
{isRewardContent && <Icon iconColor="red" icon={icons.FEATURED} />}
{fileInfo && <Icon icon={icons.LOCAL} />}
</React.Fragment>
)}
</div>
{showPrice && <FilePrice uri={uri} />}
</div>
</section>
);

View file

@ -9,6 +9,10 @@ type Props = {
uri: string,
fetching: boolean,
claim: ?{},
// below props are just passed to <CreditAmount />
filePage?: boolean,
inheritStyle?: boolean,
showLBC?: boolean,
};
class FilePrice extends React.PureComponent<Props> {
@ -33,13 +37,16 @@ class FilePrice extends React.PureComponent<Props> {
};
render() {
const { costInfo, showFullPrice } = this.props;
const { costInfo, showFullPrice, filePage, inheritStyle, showLBC } = this.props;
return costInfo ? (
<CreditAmount
showFree
filePage={filePage}
inheritStyle={inheritStyle}
showLBC={showLBC}
amount={costInfo.cost}
isEstimate={!costInfo.includesData}
showFree
showFullPrice={showFullPrice}
/>
) : null;

View file

@ -3,13 +3,18 @@ import React from 'react';
import LoadingScreen from 'component/common/loading-screen';
import PdfViewer from 'component/viewers/pdfViewer';
import ThreeViewer from 'component/viewers/threeViewer';
import DocumentViewer from 'component/viewers/documentViewer';
import DocxViewer from 'component/viewers/docxViewer';
import HtmlViewer from 'component/viewers/htmlViewer';
type Props = {
mediaType: string,
source: {
filePath: string,
fileName: string,
fileType: string,
downloadPath: string,
stream: opts => void,
blob: callback => void,
},
currentTheme: string,
};
@ -17,22 +22,36 @@ type Props = {
class FileRender extends React.PureComponent<Props> {
renderViewer() {
const { source, mediaType, currentTheme } = this.props;
const viewerProps = { source, theme: currentTheme };
// Extract relevant data to render file
const { blob, stream, fileName, fileType, contentType, downloadPath } = source;
// Human-readable files (scripts and plain-text files)
const readableFiles = ['text', 'document', 'script'];
// Supported mediaTypes
const mediaTypes = {
'3D-file': <ThreeViewer {...viewerProps} />,
'3D-file': <ThreeViewer source={{ fileType, downloadPath }} theme={currentTheme} />,
// Add routes to viewer...
};
// Supported fileType
const fileTypes = {
pdf: <PdfViewer {...viewerProps} />,
pdf: <PdfViewer source={downloadPath} />,
docx: <DocxViewer source={downloadPath} />,
html: <HtmlViewer source={downloadPath} />,
// Add routes to viewer...
};
const { fileType } = source;
const viewer = mediaType && source && (mediaTypes[mediaType] || fileTypes[fileType]);
// Check for a valid fileType or mediaType
let viewer = fileTypes[fileType] || mediaTypes[mediaType];
// Check for Human-readable files
if (!viewer && readableFiles.includes(mediaType)) {
viewer = <DocumentViewer source={{ stream, fileType, contentType }} theme={currentTheme} />;
}
// Message Error
const unsupportedMessage = __("Sorry, looks like we can't preview this file.");
const unsupported = <LoadingScreen status={unsupportedMessage} spinner={false} />;

View file

@ -11,7 +11,6 @@ import classnames from 'classnames';
import FilePrice from 'component/filePrice';
type Props = {
fullWidth: boolean, // removes the max-width css
showUri: boolean,
showLocal: boolean,
obscureNsfw: boolean,
@ -28,13 +27,15 @@ type Props = {
updatePublishForm: ({}) => void,
hideNoResult: boolean, // don't show the tile if there is no claim at this uri
displayHiddenMessage?: boolean,
displayDescription?: boolean,
small?: boolean,
};
class FileTile extends React.PureComponent<Props> {
static defaultProps = {
showUri: false,
showLocal: false,
fullWidth: false,
displayDescription: true,
};
componentDidMount() {
@ -57,13 +58,14 @@ class FileTile extends React.PureComponent<Props> {
showUri,
obscureNsfw,
claimIsMine,
fullWidth,
showLocal,
isDownloaded,
clearPublish,
updatePublishForm,
hideNoResult,
displayHiddenMessage,
displayDescription,
small,
} = this.props;
const shouldHide = !claimIsMine && obscureNsfw && metadata && metadata.nsfw;
@ -96,7 +98,7 @@ class FileTile extends React.PureComponent<Props> {
return !name && hideNoResult ? null : (
<section
className={classnames('file-tile card--link', {
'file-tile--fullwidth': fullWidth,
'file-tile--small': small,
})}
onClick={onClick}
onKeyUp={onClick}
@ -108,20 +110,29 @@ class FileTile extends React.PureComponent<Props> {
{isResolvingUri && <div className="card__title--small">{__('Loading...')}</div>}
{!isResolvingUri && (
<React.Fragment>
<div className="card__title--small card__title--file">
<TruncatedText lines={2}>{title || name}</TruncatedText>
<div
className={classnames({
'card__title--file': !small,
'card__title--x-small': small,
})}
>
<TruncatedText lines={3}>{title || name}</TruncatedText>
</div>
<div className="card__subtitle">
<div
className={classnames('card__subtitle', {
'card__subtitle--x-small': small,
})}
>
{showUri ? uri : channel || __('Anonymous')}
{isRewardContent && <Icon icon={icons.FEATURED} />}
{showLocal && isDownloaded && <Icon icon={icons.LOCAL} />}
</div>
<div className="card__subtext card__subtext--small">
<TruncatedText lines={3}>{description}</TruncatedText>
</div>
<div className="card__subtitle-price">
<FilePrice uri={uri} />
</div>
<FilePrice uri={uri} />
{displayDescription && (
<div className="card__subtext card__subtext--small">
<TruncatedText lines={3}>{description}</TruncatedText>
</div>
)}
{!name && (
<React.Fragment>
{__('This location is unused.')}{' '}

View file

@ -9,9 +9,9 @@ import FileRender from 'component/fileRender';
import Thumbnail from 'component/common/thumbnail';
import LoadingScreen from 'component/common/loading-screen';
class VideoPlayer extends React.PureComponent {
class MediaPlayer extends React.PureComponent {
static MP3_CONTENT_TYPES = ['audio/mpeg3', 'audio/mpeg'];
static FILE_MEDIA_TYPES = ['e-book', 'comic-book', 'document', '3D-file'];
static FILE_MEDIA_TYPES = ['text', 'script', 'e-book', 'comic-book', 'document', '3D-file'];
constructor(props) {
super(props);
@ -54,7 +54,7 @@ class VideoPlayer extends React.PureComponent {
};
// use renderAudio override for mp3
if (VideoPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
if (MediaPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
this.renderAudio(container, null, false);
}
// Render custom viewer: FileRender
@ -105,7 +105,7 @@ class VideoPlayer extends React.PureComponent {
if (this.playableType() && !startedPlaying && downloadCompleted) {
const container = this.media.children[0];
if (VideoPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
if (MediaPlayer.MP3_CONTENT_TYPES.indexOf(contentType) > -1) {
this.renderAudio(this.media, true);
} else {
player.render(this.file(), container, {
@ -158,10 +158,10 @@ class VideoPlayer extends React.PureComponent {
}
file() {
const { downloadPath, filename } = this.props;
const { downloadPath, fileName } = this.props;
return {
name: filename,
name: fileName,
createReadStream: opts => fs.createReadStream(downloadPath, opts),
};
}
@ -183,27 +183,30 @@ class VideoPlayer extends React.PureComponent {
// This files are supported using a custom viewer
const { mediaType } = this.props;
return VideoPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1;
return MediaPlayer.FILE_MEDIA_TYPES.indexOf(mediaType) > -1;
}
renderFile() {
// This is what render-media does with unplayable files
const { filename, downloadPath, contentType, mediaType } = this.props;
const { fileName, downloadPath, contentType, mediaType } = this.props;
toBlobURL(fs.createReadStream(downloadPath), contentType, (err, url) => {
if (err) {
this.setState({ unsupported: true });
return false;
}
// File to render
const fileSource = {
downloadPath,
filePath: url,
fileType: path.extname(filename).substring(1),
};
// Update state
this.setState({ fileSource });
});
// File to render
const fileSource = {
fileName,
contentType,
downloadPath,
fileType: path.extname(fileName).substring(1),
};
// Readable stream from file
fileSource.stream = opts => fs.createReadStream(downloadPath, opts);
// Blob url from stream
fileSource.blob = callback =>
toBlobURL(fs.createReadStream(downloadPath), contentType, callback);
// Update state
this.setState({ fileSource });
}
renderAudio(container, autoplay) {
@ -284,5 +287,5 @@ class VideoPlayer extends React.PureComponent {
}
}
export default VideoPlayer;
export default MediaPlayer;
/* eslint-disable */

View file

@ -163,7 +163,7 @@ class FileViewer extends React.PureComponent<Props> {
</div>
) : (
<Player
filename={fileInfo.file_name}
fileName={fileInfo.file_name}
poster={poster}
downloadPath={fileInfo.download_path}
mediaType={mediaType}

View file

@ -12,6 +12,7 @@ type Props = {
noPadding: ?boolean,
extraPadding: ?boolean,
notContained: ?boolean, // No max-width, but keep the padding
forContent: ?boolean,
loading: ?boolean,
};
@ -71,15 +72,24 @@ class Page extends React.PureComponent<Props, State> {
loaderTimeout: ?TimeoutID;
render() {
const { pageTitle, children, noPadding, extraPadding, notContained, loading } = this.props;
const {
pageTitle,
children,
noPadding,
extraPadding,
notContained,
loading,
forContent,
} = this.props;
const { showLoader } = this.state;
return (
<main
className={classnames('main', {
'main--contained': !notContained && !noPadding && !extraPadding,
'main--contained': !notContained && !noPadding && !extraPadding && !forContent,
'main--no-padding': noPadding,
'main--extra-padding': extraPadding,
'main--for-content': forContent,
})}
>
{pageTitle && (

View file

@ -0,0 +1,22 @@
import * as settings from 'constants/settings';
import { connect } from 'react-redux';
import { doFetchClaimsByChannel } from 'redux/actions/content';
import { makeSelectClaimsInChannelForCurrentPage } from 'lbry-redux';
import { doSetClientSetting } from 'redux/actions/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings';
import RecommendedVideos from './view';
const select = (state, props) => ({
claimsInChannel: makeSelectClaimsInChannelForCurrentPage(props.channelUri)(state),
autoplay: makeSelectClientSetting(settings.AUTOPLAY)(state),
});
const perform = dispatch => ({
fetchClaims: (uri, page) => dispatch(doFetchClaimsByChannel(uri, page)),
setAutoplay: value => dispatch(doSetClientSetting(settings.AUTOPLAY, value)),
});
export default connect(
select,
perform
)(RecommendedVideos);

View file

@ -0,0 +1,76 @@
// @flow
import React from 'react';
import FileTile from 'component/fileTile';
import { FormRow, FormField } from 'component/common/form';
import ToolTip from 'component/common/tooltip';
import type { Claim } from 'types/claim';
import { buildURI, parseURI } from 'lbry-redux';
type Props = {
uri: string,
channelUri: ?string,
claimsInChannel: ?Array<Claim>,
autoplay: boolean,
setAutoplay: boolean => void,
fetchClaims: (string, number) => void,
};
export default class RecommendedContent extends React.PureComponent<Props> {
componentDidMount() {
const { channelUri, fetchClaims, claimsInChannel } = this.props;
if (channelUri && !claimsInChannel) {
fetchClaims(channelUri, 1);
}
}
render() {
const { claimsInChannel, autoplay, uri, setAutoplay } = this.props;
let recommendedContent;
if (claimsInChannel) {
recommendedContent = claimsInChannel.filter(claim => {
const { name, claim_id: claimId, channel_name: channelName, value } = claim;
const { isChannel } = parseURI(uri);
// The uri may include the channel name
const recommendedUri =
isChannel && value && value.publisherSignature
? buildURI({
contentName: name,
claimName: channelName,
claimId: value.publisherSignature.certificateId,
})
: buildURI({ claimName: name, claimId });
return recommendedUri !== uri;
});
}
return (
<section className="card__list--recommended">
<FormRow>
<ToolTip onComponent body={__('Automatically download and play free content.')}>
<FormField
useToggle
firstInList
name="autoplay"
type="checkbox"
prefix={__('Autoplay')}
checked={autoplay}
onChange={e => setAutoplay(e.target.checked)}
/>
</ToolTip>
</FormRow>
{recommendedContent &&
recommendedContent.map(({ permanent_url: permanentUrl }) => (
<FileTile
small
displayDescription={false}
key={permanentUrl}
uri={`lbry://${permanentUrl}`}
/>
))}
</section>
);
}
}

View file

@ -31,7 +31,7 @@ class RewardSummary extends React.Component<Props> {
<React.Fragment>
{__('You have')}
&nbsp;
<CreditAmount noStyle amount={unclaimedRewardAmount} precision={8} />
<CreditAmount inheritStyle amount={unclaimedRewardAmount} precision={8} />
&nbsp;
{__('in unclaimed rewards')}.
</React.Fragment>

View file

@ -18,6 +18,7 @@ type Props = {
type State = {
thumbnailError: boolean,
thumbnailErrorImage: string,
};
class SelectThumbnail extends React.PureComponent<Props, State> {
@ -26,6 +27,7 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
this.state = {
thumbnailError: false,
thumbnailErrorImage: 'no-thumbnail.png',
};
(this: any).handleThumbnailChange = this.handleThumbnailChange.bind(this);
@ -36,7 +38,7 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
const newThumbnail = e.target.value.replace(' ', '');
updatePublishForm({ thumbnail: newThumbnail });
this.setState({ thumbnailError: false });
this.setState({ thumbnailError: false, thumbnailErrorImage: 'no-thumbnail.png' });
}
render() {
@ -49,9 +51,9 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
thumbnailPath,
resetThumbnailStatus,
} = this.props;
const { thumbnailError } = this.state;
const { thumbnailError, thumbnailErrorImage } = this.state;
const thumbnailSrc =
!thumbnail || thumbnailError ? Native.imagePath('no-thumbnail.png') : thumbnail;
!thumbnail || thumbnailError ? Native.imagePath(thumbnailErrorImage) : thumbnail;
return (
<div className="card__content">
@ -62,7 +64,11 @@ class SelectThumbnail extends React.PureComponent<Props, State> {
className="column__item thumbnail-preview"
alt={__('Thumbnail Preview')}
onError={() => {
this.setState({ thumbnailError: true });
this.setState({
thumbnailError: true,
thumbnailErrorImage:
thumbnail && thumbnail.length > 0 ? 'broken.png' : 'no-thumbnail.png',
});
}}
/>
<div className="column__item">

View file

@ -6,8 +6,8 @@ import DateTime from 'component/dateTime';
import Button from 'component/button';
import { buildURI } from 'lbry-redux';
import * as txnTypes from 'constants/transaction_types';
import type { Transaction } from '../view';
import * as ICONS from 'constants/icons';
import type { Transaction } from '../view';
type Props = {
transaction: Transaction,
@ -25,12 +25,6 @@ class TransactionListItem extends React.PureComponent<Props> {
(this: any).abandonClaim = this.abandonClaim.bind(this);
}
abandonClaim() {
const { txid, nout } = this.props.transaction;
this.props.revokeClaim(txid, nout);
}
getLink(type: string) {
if (type === txnTypes.TIP) {
return <Button icon={ICONS.UNLOCK} onClick={this.abandonClaim} title={__('Unlock Tip')} />;
@ -38,10 +32,14 @@ class TransactionListItem extends React.PureComponent<Props> {
return <Button icon={ICONS.TRASH} onClick={this.abandonClaim} title={__('Abandon Claim')} />;
}
capitalize(string: string) {
return string.charAt(0).toUpperCase() + string.slice(1);
abandonClaim() {
const { txid, nout } = this.props.transaction;
this.props.revokeClaim(txid, nout);
}
capitalize = (string: string) => string.charAt(0).toUpperCase() + string.slice(1);
render() {
const { reward, transaction, isRevokeable } = this.props;
const { amount, claim_id: claimId, claim_name: name, date, fee, txid, type } = transaction;
@ -55,12 +53,12 @@ class TransactionListItem extends React.PureComponent<Props> {
return (
<tr>
<td>
<CreditAmount amount={amount} plain noStyle showPlus precision={8} />
<CreditAmount inheritStyle showPlus amount={amount} precision={8} />
<br />
{fee !== 0 && (
<span className="table__item-label">
<CreditAmount plain noStyle fee amount={fee} precision={8} />
<CreditAmount inheritStyle fee amount={fee} precision={8} />
</span>
)}
</td>

View file

@ -18,7 +18,7 @@ export default (props: Props) => {
<Button
icon={icons.GLOBE}
button="alt"
label={__('View on Web')}
label={__('Share')}
href={`http://spee.ch/${speechURL}`}
/>
) : null;

View file

@ -0,0 +1,67 @@
// @flow
import React from 'react';
import CodeMirror from 'codemirror/lib/codemirror';
import { openSnippetMenu, stopContextMenu } from 'util/contextMenu';
// Addons
import 'codemirror/addon/selection/mark-selection';
// Syntax mode
import 'codemirror/mode/go/go';
import 'codemirror/mode/jsx/jsx';
import 'codemirror/mode/css/css';
import 'codemirror/mode/xml/xml';
import 'codemirror/mode/php/php';
import 'codemirror/mode/ruby/ruby';
import 'codemirror/mode/clike/clike';
import 'codemirror/mode/shell/shell';
import 'codemirror/mode/python/python';
import 'codemirror/mode/markdown/markdown';
import 'codemirror/mode/javascript/javascript';
type Props = {
theme: string,
value: string,
contentType: string,
};
class CodeViewer extends React.PureComponent<Props> {
constructor(props) {
super(props);
this.codeMirror = null;
this.textarea = React.createRef();
}
componentDidMount() {
const { theme, contentType } = this.props;
// Init CodeMirror
this.codeMirror = CodeMirror.fromTextArea(this.textarea.current, {
// Auto detect syntax with file contentType
mode: contentType,
// Adaptive theme
theme: theme === 'dark' ? 'one-dark' : 'default',
// Hide the cursor
readOnly: true,
// Styled text selection
styleSelectedText: true,
// Additional config opts
dragDrop: false,
lineNumbers: true,
lineWrapping: true,
});
// Add events
this.codeMirror.on('contextmenu', openSnippetMenu);
}
render() {
const { value } = this.props;
return (
<div className="code-viewer" onContextMenu={stopContextMenu}>
<textarea ref={this.textarea} disabled value={value} />
</div>
);
}
}
export default CodeViewer;

View file

@ -0,0 +1,79 @@
// @flow
import React from 'react';
import LoadingScreen from 'component/common/loading-screen';
import CodeViewer from 'component/viewers/codeViewer';
import MarkdownPreview from 'component/common/markdown-preview';
type Props = {
theme: string,
source: {
stream: opts => void,
fileType: string,
contentType: string,
},
};
class DocumentViewer extends React.PureComponent<Props> {
constructor(props) {
super(props);
this.state = {
error: null,
content: null,
loading: true,
};
}
componentDidMount() {
const { source } = this.props;
const stream = source.stream('utf8');
let data = '';
stream.on('data', chunk => {
data += chunk;
});
stream.on('end', () => {
this.setState({ content: data, loading: false });
});
stream.on('error', error => {
this.setState({ error: true, loading: false });
});
}
renderDocument(content = null) {
let viewer = null;
const { source, theme } = this.props;
const { fileType, contentType } = source;
const markdownType = ['md', 'markdown'];
if (markdownType.includes(fileType)) {
// Render markdown
viewer = <MarkdownPreview content={content} promptLinks />;
} else {
// Render plain text
viewer = <CodeViewer value={content} contentType={contentType} theme={theme} />;
}
return viewer;
}
render() {
const { error, loading, content } = this.state;
const isReady = content && !error;
const loadingMessage = __('Rendering document.');
const errorMessage = __("Sorry, looks like we can't load the document.");
return (
<div className="file-render__viewer document-viewer">
{loading && !error && <LoadingScreen status={loadingMessage} spinner />}
{error && <LoadingScreen status={errorMessage} spinner={!error} />}
{isReady && this.renderDocument(content)}
</div>
);
}
}
export default DocumentViewer;

View file

@ -0,0 +1,74 @@
// @flow
import React from 'react';
import mammoth from 'mammoth';
import Breakdance from 'breakdance';
import LoadingScreen from 'component/common/loading-screen';
import MarkdownPreview from 'component/common/markdown-preview';
type Props = {
source: string,
};
class DocxViewer extends React.PureComponent<Props> {
constructor(props) {
super(props);
this.state = {
error: null,
content: null,
loading: true,
};
}
componentDidMount() {
const { source } = this.props;
// Overwrite element and styles
const options = {
styleMap: [
"p[style-name='Title'] => h1:fresh",
"p[style-name='Heading 1'] => h1:fresh",
"p[style-name='Heading 2'] => h2:fresh",
"p[style-name='Heading 3'] => h3:fresh",
"p[style-name='Section Title'] => h1:fresh",
"p[style-name='Subsection Title'] => h2:fresh",
"p[style-name='Aside Heading'] => div.aside > h2:fresh",
"p[style-name='Aside Text'] => div.aside > p:fresh",
],
};
// Parse docx to html
mammoth
.convertToHtml({ path: source }, options)
.then(result => {
// Remove images and tables
const breakdance = new Breakdance({ omit: ['table', 'img'] });
// Convert html to markdown
const markdown = breakdance.render(result.value);
this.setState({ content: markdown, loading: false });
})
.catch(error => {
this.setState({ error: true, loading: false });
})
.done();
}
render() {
const { content, error, loading } = this.state;
const loadingMessage = __('Rendering document.');
const errorMessage = __("Sorry, looks like we can't load the document.");
return (
<div className="document-viewer file-render__viewer">
{loading && <LoadingScreen status={loadingMessage} spinner />}
{error && <LoadingScreen status={errorMessage} spinner={false} />}
{content && (
<div className="document-viewer__content">
<MarkdownPreview content={content} promptLinks />
</div>
)}
</div>
);
}
}
export default DocxViewer;

View file

@ -0,0 +1,20 @@
// @flow
import React from 'react';
import { stopContextMenu } from 'util/contextMenu';
type Props = {
source: string,
};
class HtmlViewer extends React.PureComponent<Props> {
render() {
const { source } = this.props;
return (
<div className="file-render__viewer" onContextMenu={stopContextMenu}>
<iframe sandbox="" title={__('File preview')} src={`file://${source}`} />
</div>
);
}
}
export default HtmlViewer;

View file

@ -1,12 +1,9 @@
// @flow
import React from 'react';
import { stopContextMenu } from 'util/contextMenu';
type Props = {
source: {
fileType: string,
filePath: string,
downloadPath: string,
},
source: string,
};
class PdfViewer extends React.PureComponent<Props> {
@ -15,20 +12,11 @@ class PdfViewer extends React.PureComponent<Props> {
this.viewer = React.createRef();
}
// TODO: Enable context-menu
stopContextMenu = event => {
event.preventDefault();
event.stopPropagation();
};
render() {
const { source } = this.props;
return (
<div className="file-render__viewer" onContextMenu={this.stopContextMenu}>
<webview
ref={this.viewer}
src={`chrome://pdf-viewer/index.html?src=file://${source.downloadPath}`}
/>
<div className="file-render__viewer" onContextMenu={stopContextMenu}>
<webview ref={this.viewer} src={`chrome://pdf-viewer/index.html?src=file://${source}`} />
</div>
);
}

View file

@ -14,7 +14,7 @@ type Props = {
autoRotate: boolean,
source: {
fileType: string,
filePath: string,
downloadPath: string,
},
};

View file

@ -17,13 +17,13 @@ const Loader = (fileType, manager) => {
return fileTypes[fileType] ? fileTypes[fileType]() : null;
};
const ThreeLoader = ({ fileType, filePath }, renderModel, managerEvents) => {
const ThreeLoader = ({ fileType = null, downloadPath = null }, renderModel, managerEvents) => {
if (fileType) {
const manager = Manager(managerEvents);
const loader = Loader(fileType, manager);
if (loader) {
loader.load(filePath, data => {
loader.load(`file://${downloadPath}`, data => {
renderModel(fileType, data);
});
}

View file

@ -31,7 +31,7 @@ class ModalAffirmPurchase extends React.PureComponent {
>
{__('This will purchase')} <strong>{title}</strong> {__('for')}{' '}
<strong>
<FilePrice uri={uri} showFullPrice look="plain" />
<FilePrice uri={uri} showFullPrice inheritStyle showLBC={false} />
</strong>{' '}
{__('credits')}.
</Modal>

View file

@ -1,9 +1,23 @@
// @flow
import React from 'react';
import { ipcRenderer } from 'electron';
import { Modal } from 'modal/modal';
import Button from 'component/button';
class ModalAutoUpdateDownloaded extends React.PureComponent {
type Props = {
closeModal: any => any,
declineAutoUpdate: () => any,
};
class ModalAutoUpdateDownloaded extends React.PureComponent<Props> {
constructor(props: ModalProps) {
super(props);
this.state = {
disabled: false,
};
}
render() {
const { closeModal, declineAutoUpdate } = this.props;
@ -14,7 +28,9 @@ class ModalAutoUpdateDownloaded extends React.PureComponent {
contentLabel={__('Update Downloaded')}
confirmButtonLabel={__('Use it Now')}
abortButtonLabel={__('Upgrade on Close')}
confirmButtonDisabled={this.state.disabled}
onConfirmed={() => {
this.setState({ disabled: true });
ipcRenderer.send('autoUpdateAccepted');
}}
onAborted={() => {

View file

@ -14,14 +14,12 @@ import Button from 'component/button';
import SubscribeButton from 'component/subscribeButton';
import ViewOnWebButton from 'component/viewOnWebButton';
import Page from 'component/page';
import * as settings from 'constants/settings';
import type { Claim } from 'types/claim';
import type { Subscription } from 'types/subscription';
import FileDownloadLink from 'component/fileDownloadLink';
import classnames from 'classnames';
import { FormField, FormRow } from 'component/common/form';
import ToolTip from 'component/common/tooltip';
import getMediaType from 'util/getMediaType';
import RecommendedContent from 'component/recommendedContent';
type Props = {
claim: Claim,
@ -37,14 +35,12 @@ type Props = {
rewardedContentClaimIds: Array<string>,
obscureNsfw: boolean,
claimIsMine: boolean,
autoplay: boolean,
costInfo: ?{},
navigate: (string, ?{}) => void,
openModal: ({ id: string }, { uri: string }) => void,
fetchFileInfo: string => void,
fetchCostInfo: string => void,
prepareEdit: ({}, string) => void,
setClientSetting: (string, boolean | string) => void,
checkSubscription: ({ channelName: string, uri: string }) => void,
subscriptions: Array<Subscription>,
};
@ -55,19 +51,14 @@ class FilePage extends React.Component<Props> {
'text',
'model',
'image',
'3D-file',
'script',
'document',
'3D-file',
// Bypass unplayable files
// TODO: Find a better way to detect supported types
'application',
];
constructor(props: Props) {
super(props);
(this: any).onAutoplayChange = this.onAutoplayChange.bind(this);
}
componentDidMount() {
const { uri, fileInfo, fetchFileInfo, fetchCostInfo } = this.props;
@ -88,10 +79,6 @@ class FilePage extends React.Component<Props> {
}
}
onAutoplayChange(event: SyntheticInputEvent<*>) {
this.props.setClientSetting(settings.AUTOPLAY, event.target.checked);
}
checkSubscription = (props: Props) => {
if (props.subscriptions.find(sub => sub.channelName === props.claim.channel_name)) {
props.checkSubscription({
@ -119,7 +106,6 @@ class FilePage extends React.Component<Props> {
claimIsMine,
prepareEdit,
navigate,
autoplay,
costInfo,
fileInfo,
} = this.props;
@ -160,98 +146,79 @@ class FilePage extends React.Component<Props> {
}
return (
<Page extraPadding>
{!claim || !metadata ? (
<section>
<span className="empty">{__('Empty claim or metadata info.')}</span>
</section>
) : (
<section className="card">
{showFile && (
<FileViewer className="content__embedded" uri={uri} mediaType={mediaType} />
)}
{!showFile &&
(thumbnail ? (
<Thumbnail shouldObscure={shouldObscureThumbnail} src={thumbnail} />
) : (
<div
className={classnames('content__empty', {
'content__empty--nsfw': shouldObscureThumbnail,
})}
>
<div className="card__media-text">
{__("Sorry, looks like we can't preview this file.")}
</div>
</div>
))}
<div className="card__content">
<div className="card__title-identity--file">
<h1 className="card__title card__title--file">{title}</h1>
<div className="card__title-identity-icons">
{isRewardContent && (
<Icon iconColor="red" tooltip="bottom" icon={icons.FEATURED} />
)}
<FilePrice uri={normalizeURI(uri)} />
<Page forContent>
<section className="content__wrapper">
{showFile && <FileViewer className="content__embedded" uri={uri} mediaType={mediaType} />}
{!showFile &&
(thumbnail ? (
<Thumbnail shouldObscure={shouldObscureThumbnail} src={thumbnail} />
) : (
<div
className={classnames('content__empty', {
'content__empty--nsfw': shouldObscureThumbnail,
})}
>
<div className="card__media-text">
{__("Sorry, looks like we can't preview this file.")}
</div>
</div>
<span className="card__subtitle card__subtitle--file">
{__('Published on')}&nbsp;
<DateTime block={height} show={DateTime.SHOW_DATE} />
</span>
{metadata.nsfw && <div>NSFW</div>}
<div className="card__channel-info">
<UriIndicator uri={uri} link />
</div>
<div className="card__actions card__actions--no-margin card__actions--between">
<div className="card__actions">
{claimIsMine ? (
<Button
button="primary"
icon={icons.EDIT}
label={__('Edit')}
onClick={() => {
prepareEdit(claim, editUri);
navigate('/publish');
}}
/>
) : (
<SubscribeButton uri={subscriptionUri} channelName={channelName} />
)}
{!claimIsMine && (
<Button
button="alt"
icon={icons.GIFT}
label={__('Enjoy this? Send a tip')}
onClick={() => openModal({ id: MODALS.SEND_TIP }, { uri })}
/>
)}
{speechSharable && (
<ViewOnWebButton claimId={claim.claim_id} claimName={claim.name} />
)}
</div>
))}
<div className="card__actions">
<FileDownloadLink uri={uri} />
<FileActions uri={uri} claimId={claim.claim_id} />
</div>
<div className="card__content">
<div className="card__title-identity--file">
<h1 className="card__title card__title--file">{title}</h1>
<div className="card__title-identity-icons">
{isRewardContent && <Icon iconColor="red" tooltip="bottom" icon={icons.FEATURED} />}
<FilePrice filePage uri={normalizeURI(uri)} />
</div>
<FormRow padded>
<ToolTip onComponent body={__('Automatically download and play free content.')}>
<FormField
name="autoplay"
type="checkbox"
postfix={__('Autoplay')}
checked={autoplay}
onChange={this.onAutoplayChange}
</div>
<span className="card__subtitle card__subtitle--file">
{__('Published on')}&nbsp;
<DateTime block={height} show={DateTime.SHOW_DATE} />
</span>
{metadata.nsfw && <div>NSFW</div>}
<div className="card__channel-info">
<UriIndicator uri={uri} link />
</div>
<div className="card__actions card__actions--no-margin card__actions--between">
<div className="card__actions">
{claimIsMine ? (
<Button
button="primary"
icon={icons.EDIT}
label={__('Edit')}
onClick={() => {
prepareEdit(claim, editUri);
navigate('/publish');
}}
/>
</ToolTip>
</FormRow>
) : (
<SubscribeButton uri={subscriptionUri} channelName={channelName} />
)}
{!claimIsMine && (
<Button
button="alt"
icon={icons.GIFT}
label={__('Send a tip')}
onClick={() => openModal({ id: MODALS.SEND_TIP }, { uri })}
/>
)}
{speechSharable && (
<ViewOnWebButton claimId={claim.claim_id} claimName={claim.name} />
)}
</div>
<div className="card__actions">
<FileDownloadLink uri={uri} />
<FileActions uri={uri} claimId={claim.claim_id} />
</div>
</div>
<div className="card__content--extra-padding">
<FileDetails uri={uri} />
</div>
</section>
)}
</div>
</section>
<RecommendedContent uri={uri} channelUri={`lbry://${subscriptionUri}`} />
</Page>
);
}

View file

@ -73,7 +73,7 @@ class SearchPage extends React.PureComponent<Props> {
<Icon icon={icons.HELP} />
</ToolTip>
</div>
<FileTile fullWidth showUri displayHiddenMessage uri={normalizeURI(query)} />
<FileTile showUri displayHiddenMessage uri={normalizeURI(query)} />
</React.Fragment>
)}
<FileListSearch query={query} />

View file

@ -120,7 +120,7 @@ export const doUploadThumbnail = (filePath: string, nsfw: boolean) => (dispatch:
thumbnail: `${json.data.url}${fileExt}`,
},
})
: uploadError('Upload failed')
: uploadError(json.message)
)
.catch(err => uploadError(err.message));
};

View file

@ -74,7 +74,7 @@ export const shapeShiftInit = () => (dispatch: Dispatch): ThunkAction => {
let supportedCoins = [];
Object.keys(coinData).forEach(symbol => {
if (coinData[symbol].status === SHAPESHIFT_STATUSES.UNAVAILABLE) {
if (coinData[symbol].status === SHAPESHIFT_STATUSES.AVAILABLE) {
supportedCoins.push(coinData[symbol]);
}
});

View file

@ -156,6 +156,7 @@ p {
}
.page {
z-index: 0;
position: absolute;
top: var(--header-height);
left: 0;
@ -203,6 +204,12 @@ p {
padding-right: 100px;
}
.main--for-content {
padding: $spacing-width * 2/3;
display: flex;
justify-content: center;
}
.page__header {
padding: $spacing-vertical * 2/3;
padding-bottom: 0;
@ -245,16 +252,15 @@ p {
/* Custom text selection */
*::selection {
background: var(--color-primary-light);
background: var(--text-selection-bg);
color: var(--text-selection-color);
}
.credit-amount {
border-radius: 5px;
font-family: 'metropolis-bold';
font-size: 10px;
padding: 5px;
white-space: nowrap;
padding: $spacing-vertical * 1/6 0;
}
.credit-amount--large {
@ -262,30 +268,36 @@ p {
font-size: 36px;
}
.credit-amount--file-page {
border-radius: 5px;
padding: 5px;
}
.credit-amount--free {
color: var(--color-dark-blue);
background-color: var(--color-secondary);
color: var(--color-secondary);
&.credit-amount--file-page {
color: var(--color-dark-blue);
background-color: var(--color-secondary);
}
}
.credit-amount--cost {
color: var(--color-black);
background-color: var(--color-yellow);
color: var(--color-yellow);
&.credit-amount--file-page {
color: var(--color-black);
background-color: var(--color-yellow);
}
}
.credit-amount--plain {
.credit-amount--inherit {
background-color: inherit;
color: inherit;
font-weight: inherit;
font-size: inherit;
}
.credit-amount.credit-amount--no-style {
padding: 0;
font-size: inherit;
font-weight: inherit;
color: inherit;
background-color: transparent;
font-family: 'metropolis-medium';
padding: 0;
}
.divider__horizontal {

View file

@ -9,7 +9,7 @@ $large-breakpoint: 1921px;
:root {
/* Widths & spacings */
--side-nav-width: 220px;
--side-nav-width: 190px;
--side-nav-width-m: 240px;
--side-nav-width-l: 320px;
--font-size-subtext-multiple: 0.92;
@ -62,9 +62,11 @@ $large-breakpoint: 1921px;
--text-help-color: var(--color-help);
--text-max-width: 660px;
--text-link-padding: 4px;
--text-selection-bg: var(--color-purple);
--text-selection-color: #fff;
/* Text Selectiom */
--text-selection-bg: var(--color-primary-light);
--text-selection-color: var(--color-white);
--editor-text-selection-bg: rgba(57, 148, 131, 0.8);
/* Form */
--form-label-color: rgba(0, 0, 0, 0.54);
@ -153,9 +155,14 @@ $large-breakpoint: 1921px;
--success-msg-border: var(--color-green-blue);
--success-msg-bg: var(--color-green-light);
/* File Tile Card */
--file-tile--media-height: 125px;
--file-tile--media-width: calc(125px * (16 / 9));
/* File */
--file-tile-media-height: 125px;
--file-tile-media-width: calc(125px * (16 / 9));
--file-tile-media-height-small: 60px;
--file-tile-media-width-small: calc(60px * (16 / 9));
--file-page-min-width: 400px;
--recommended-content-width: 300px;
--recommended-content-width-medium: 400px;
/* Modal */
--modal-width: 440px;

View file

@ -2,6 +2,7 @@
@import '_reset.scss';
@import '_vars.scss';
@import '_gui.scss';
@import 'component/_syntax-highlighter.scss';
@import 'component/_table.scss';
@import 'component/_button.scss';
@import 'component/_card.scss';
@ -26,3 +27,4 @@
@import 'component/_file-render.scss';
@import 'component/_search.scss';
@import 'component/_toggle.scss';
@import 'component/_search.scss';

View file

@ -38,7 +38,6 @@
@media only screen and (min-width: $medium-breakpoint) {
font-size: 14px;
padding-top: 4px;
}
}
}
@ -114,13 +113,17 @@
.card__title--small {
font-size: 14px;
line-height: 18px;
padding-top: $spacing-vertical / 3;
@media only screen and (min-width: $large-breakpoint) {
font-size: 16px;
}
}
.card__title--x-small {
font-size: 12px;
line-height: 12px;
}
.card__title--file {
font-family: 'metropolis-bold';
font-size: 28px;
@ -130,25 +133,36 @@
font-size: 18px;
}
.card__title--file-card {
padding-top: $spacing-vertical * 1/3;
}
.card__subtitle {
margin: 0;
font-size: 14px;
font-family: 'metropolis-medium';
color: var(--card-text-color);
display: flex;
align-items: center;
.icon {
margin-top: $spacing-vertical * 1/6;
&:not(:first-of-type) {
margin: 0 $spacing-vertical * 1/3;
}
margin: 0 0 0 $spacing-vertical * 1/3;
}
}
.card__subtitle--x-small {
font-size: 12px;
}
.card__subtitle-price {
padding-top: $spacing-vertical * 1/3;
}
.card__title--small + .card__subtitle,
.card__title--x-small + .card__subtitle {
padding-top: $spacing-vertical * 1/3;
}
.card__meta {
color: var(--color-help);
font-size: 14px;
@ -312,7 +326,11 @@
.card-row__scroll-btns {
display: flex;
padding-right: $spacing-width;
padding-right: $spacing-width * 1/3;
@media (min-width: $medium-breakpoint) {
padding-right: $spacing-width;
}
}
.card-row__scrollhouse {
@ -401,6 +419,15 @@
}
}
.card__list--recommended {
flex: 0 0 var(--recommended-content-width);
padding-left: $spacing-width;
@media (min-width: $medium-breakpoint) {
flex: 0 0 var(--recommended-content-width-medium);
}
}
.card__success-msg {
border-left: 2px solid var(--success-msg-border);
color: var(--success-msg-color);

View file

@ -1,3 +1,8 @@
.content__wrapper {
max-width: var(--card-max-width);
flex: 1 0 var(--file-page-min-width);
}
.content__embedded {
background-color: var(--color-black);
width: 100%;
@ -96,25 +101,6 @@
}
}
.file-render {
width: 100%;
height: 100%;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
overflow: hidden;
.file-render__viewer {
width: 100%;
height: 100%;
background: black;
}
}
img {
max-height: 100%;
max-width: 100%;

View file

@ -22,11 +22,11 @@
.file-tile {
display: flex;
margin-top: $spacing-vertical;
padding-top: $spacing-vertical;
.card__media {
height: var(--file-tile--media-height);
flex: 0 0 var(--file-tile--media-width);
height: var(--file-tile-media-height);
flex: 0 0 var(--file-tile-media-width);
}
.card__subtitle {
@ -34,8 +34,13 @@
}
}
.file-tile--fullwidth {
max-width: none;
.file-tile.file-tile--small {
padding-top: $spacing-vertical * 2/3;
.card__media {
height: var(--file-tile-media-height-small);
flex: 0 0 var(--file-tile-media-width-small);
}
}
.file-tile__info {

View file

@ -9,17 +9,79 @@
bottom: 0;
z-index: 1;
overflow: hidden;
}
.file-render__viewer {
margin: 0;
.file-render__viewer {
margin: 0;
width: 100%;
height: 100%;
background-color: black;
iframe,
webview {
width: 100%;
height: 100%;
background: black;
iframe,
webview {
width: 100%;
height: 100%;
}
}
}
.document-viewer {
overflow: auto;
background-color: var(--card-bg);
font-size: calc(var(--font-size-subtext-multiple) * 1em);
}
.document-viewer .markdown-preview {
height: 100%;
overflow: auto;
padding: $spacing-vertical $spacing-width;
}
.code-viewer,
.document-viewer__content {
overflow: auto;
width: 100%;
height: 100%;
}
/* Code-viewer */
.code-viewer .CodeMirror {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
min-height: 100px;
/* Block native text selection */
user-select: none;
.CodeMirror-code {
font-size: 1em;
font-weight: 350;
line-height: 1.5em;
font-family: Menlo, Consolas, 'DejaVu Sans Mono', inconsolata, monospace;
letter-spacing: 0.3px;
word-spacing: 1px;
}
.CodeMirror-linenumber {
color: var(--card-text-color);
}
.CodeMirror .CodeMirror-lines {
padding: 4px 0;
}
.CodeMirror-line {
padding-left: 16px;
}
.CodeMirror-gutters {
border-right: 1px solid var(--color-divider);
background: var(--color-bg-alt);
padding-right: 8px;
}
.cm-invalidchar {
display: none;
}
}

View file

@ -51,6 +51,10 @@
width: 100%;
}
.form-field__input.form-field--first-item {
padding: 0;
}
.form-field__input {
display: flex;
padding-top: $spacing-vertical / 3;

View file

@ -6,9 +6,13 @@
z-index: 1;
justify-content: space-between;
align-items: center;
padding: 0 $spacing-width;
padding: 0 $spacing-width * 1/3;
background-color: var(--color-bg);
box-shadow: var(--box-shadow-header);
@media (min-width: $medium-breakpoint) {
padding: 0 $spacing-width;
}
}
.header__navigation {

View file

@ -1,96 +1,88 @@
.CodeMirror {
background: var(--color-canvas) !important;
border: 0px !important;
border-radius: 0px !important;
color: var(--text-color) !important;
box-shadow: var(--box-shadow-layer);
border: 0px;
border-radius: 0px;
background: var(--card-bg);
color: var(--text-color);
}
.editor-toolbar {
opacity: 1 !important;
border: 0 !important;
opacity: 1;
border: 0;
background: var(--color-bg-alt);
border-radius: 0 !important;
border-radius: 0;
box-shadow: var(--box-shadow-layer);
}
.editor-toolbar:hover {
opacity: 1;
}
.editor-toolbar i.separator {
border: 0 !important;
border-right: var(--divider) !important;
border: 0;
}
.editor-toolbar.fullscreen {
background: var(--color-bg) !important;
background: var(--color-bg-alt);
}
div.editor-toolbar a {
opacity: 0.64;
.editor-toolbar.fullscreen::before,
.editor-toolbar.fullscreen::after {
display: none;
}
.editor-toolbar a {
opacity: 0.6;
color: var(--text-color) !important;
transition: opacity 0.3s ease;
}
.editor-toolbar a.active,
.editor-toolbar a:hover {
opacity: 1;
background: var(--button-bg) !important;
border-color: transparent !important;
background: var(--button-bg);
border-color: transparent;
}
.editor-toolbar.disabled-for-preview a:not(.no-disable) {
background: var(--color-bg-alt) !important;
border-color: transparent !important;
background: var(--color-bg-alt);
border-color: transparent;
opacity: 0.3;
}
.editor-statusbar {
color: var(--form-label-color) !important;
color: var(--form-label-color);
}
.editor-preview {
font-size: calc(var(--font-size-subtext-multiple) * 1em);
background: var(--color-bg) !important;
background: var(--color-bg);
border: 0;
}
.editor-preview-side {
background: var(--color-bg-alt) !important;
border: 1px solid var(--input-border-color) !important;
}
.CodeMirror .CodeMirror-code .cm-tag {
color: #63a35c;
}
.CodeMirror .CodeMirror-code .cm-attribute {
color: #795da3;
}
.CodeMirror .CodeMirror-code .cm-string {
color: #183691;
}
.CodeMirror .CodeMirror-selected {
background: var(--text-selection-bg) !important;
color: var(--text-selection-color) !important;
}
.CodeMirror .CodeMirror-cursor {
border-color: var(--color-primary) !important;
}
.CodeMirror .CodeMirror-code .cm-comment {
background: rgba(0, 0, 0, 0.05);
}
.CodeMirror .CodeMirror-code .cm-link {
color: #7f8c8d;
}
.CodeMirror .CodeMirror-code .cm-url {
color: #aab2b3;
border-color: var(--color-primary);
}
.CodeMirror .CodeMirror-placeholder {
opacity: 0.5;
}
/* Fix selection */
.CodeMirror-line::selection,
.CodeMirror-line > span::selection,
.CodeMirror-line > span > span::selection {
background: var(--text-selection-bg);
}
.CodeMirror .CodeMirror-selected {
background: transparent;
}
.CodeMirror .CodeMirror-selectedtext {
background: var(--editor-text-selection-bg) !important;
color: var(--text-selection-color) !important;
}
.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word) {
background: none;
text-decoration: underline;

View file

@ -63,6 +63,11 @@
}
}
/* Image */
img {
margin: 16px 0;
}
/* Horizontal Rule */
hr {
border: 1px solid var(--color-divider);

View file

@ -1,7 +1,7 @@
.nav {
width: var(--side-nav-width);
background-color: var(--nav-bg-color);
padding: $spacing-width;
padding: $spacing-width * 1/3;
color: var(--nav-color);
hr {
@ -11,8 +11,13 @@
margin: $spacing-vertical $spacing-vertical * 2/3;
}
@media (min-width: $medium-breakpoint) {
padding-left: $spacing-width;
width: calc(var(--side-nav-width) * 1.2);
}
@media (min-width: $large-breakpoint) {
width: calc(var(--side-nav-width) * 1.1);
width: calc(var(--side-nav-width) * 1.4);
}
}

View file

@ -0,0 +1,147 @@
/*
Name: one-dark 1.1.1
Author: Török Ádám (http://github.com/Aerobird98)
Original Atom One Dark Theme (https://github.com/atom/one-dark-ui & https://github.com/atom/one-dark-syntax)
*/
/* basic */
.CodeMirror.cm-s-one-dark {
color: #abb2bf;
}
.CodeMirror.cm-s-one-dark .CodeMirror-lines {
color: #abb2bf !important;
background-color: transparent;
}
.CodeMirror.cm-s-one-dark .CodeMirror-cursor {
border-left: 2px solid #56b6c2 !important;
}
/* addon: edit/machingbrackets.js & addon: edit/matchtags.js */
.CodeMirror.cm-s-one-dark .CodeMirror-matchingbracket,
.CodeMirror.cm-s-one-dark .CodeMirror-matchingtag {
border-bottom: 2px solid #56b6c2;
color: #abb2bf !important;
background-color: transparent;
}
.CodeMirror.cm-s-one-dark .CodeMirror-nonmatchingbracket {
border-bottom: 2px solid #e06c75;
color: #abb2bf !important;
background-color: transparent;
}
/* addon: fold/foldgutter.js */
.CodeMirror.cm-s-one-dark .CodeMirror-foldmarker,
.CodeMirror.cm-s-one-dark .CodeMirror-foldgutter,
.CodeMirror.cm-s-one-dark .CodeMirror-foldgutter-open,
.CodeMirror.cm-s-one-dark .CodeMirror-foldgutter-folded {
border: none;
text-shadow: none;
color: #5c6370 !important;
background-color: transparent;
}
/* addon: selection/active-line.js */
.CodeMirror.cm-s-one-dark .CodeMirror-activeline-background {
background-color: rgba(153, 187, 255, 0.04);
}
/* basic syntax */
.CodeMirror.cm-s-one-dark .cm-header {
color: #e06c75;
}
.CodeMirror.cm-s-one-dark .cm-quote {
color: #5c6370;
font-style: italic;
}
.CodeMirror.cm-s-one-dark .cm-negative {
color: #e06c75;
}
.CodeMirror.cm-s-one-dark .cm-positive {
color: #e06c75;
}
.CodeMirror.cm-s-one-dark .cm-strong {
color: #d19a66;
font-weight: bold;
}
.CodeMirror.cm-s-one-dark .cm-header .cm-strong {
color: #d19a66;
font-weight: bold;
}
.CodeMirror.cm-s-one-dark .cm-em {
color: #c678dd;
font-style: italic;
}
.CodeMirror.cm-s-one-dark .cm-header .cm-em {
color: #c678dd;
font-style: italic;
}
.CodeMirror.cm-s-one-dark .cm-tag {
color: #e06c75;
}
.CodeMirror.cm-s-one-dark .cm-attribute {
color: #d19a66;
}
.CodeMirror.cm-s-one-dark .cm-link {
color: #98c379;
border-bottom: solid 1px #98c379;
}
.CodeMirror.cm-s-one-dark .cm-builtin {
color: #e06c75;
}
.CodeMirror.cm-s-one-dark .cm-keyword {
color: #c678dd;
}
.CodeMirror.cm-s-one-dark .cm-def {
color: #e5c07b;
} /* original: #d19a66; */
.CodeMirror.cm-s-one-dark .cm-atom {
color: #d19a66;
}
.CodeMirror.cm-s-one-dark .cm-number {
color: #d19a66;
}
.CodeMirror.cm-s-one-dark .cm-property {
color: #56b6c2;
} /* original: #abb2bf */
.CodeMirror.cm-s-one-dark .cm-qualifier {
color: #d19a66;
}
.CodeMirror.cm-s-one-dark .cm-variable {
color: #e06c75;
}
.CodeMirror.cm-s-one-dark .cm-string {
color: #98c379;
}
.CodeMirror.cm-s-one-dark .cm-punctuation {
color: #abb2bf;
}
.CodeMirror.cm-s-one-dark .cm-operator {
color: #56b6c2;
} /* original: #abb2bf */
.CodeMirror.cm-s-one-dark .cm-meta {
color: #abb2bf;
}
.CodeMirror.cm-s-one-dark .cm-bracket {
color: #abb2bf;
}
.CodeMirror.cm-s-one-dark .cm-comment {
color: #5c6370;
font-style: italic;
}
.CodeMirror.cm-s-one-dark .cm-error {
color: #e06c75;
}
/* css syntax corrections */
.CodeMirror.cm-s-one-dark .cm-m-css.cm-variable {
color: #828997;
}
.CodeMirror.cm-s-one-dark .cm-m-css.cm-property {
color: #abb2bf;
}
.CodeMirror.cm-s-one-dark .cm-m-css.cm-atom {
color: #56b6c2;
}
.CodeMirror.cm-s-one-dark .cm-m-css.cm-builtin {
color: #56b6c2;
}
/* lua syntax corrections */
.CodeMirror.cm-s-one-dark .cm-m-lua.cm-variable {
color: #56b6c2;
}

View file

@ -23,9 +23,9 @@ function injectDevelopmentTemplate(event, templates) {
export function openContextMenu(event, templates = [], canEdit = false, selection = '') {
const { type, value } = event.target;
const isSomethingSelected = selection.length > 0 || window.getSelection().toString().length > 0;
const isInput = event.target.matches('input') && (type === 'text' || type === 'number');
const isTextField = canEdit || isInput || event.target.matches('textarea');
const isSomethingSelected = selection.length > 0 || window.getSelection().toString().length > 0;
templates.push({
label: 'Copy',
@ -63,7 +63,7 @@ export function openContextMenu(event, templates = [], canEdit = false, selectio
}
// This function is used for the markdown description on the publish page
export function openEditorMenu(event, codeMirror) {
export function openEditorMenu(codeMirror, event) {
const value = codeMirror.doc.getValue();
const selection = codeMirror.doc.getSelection();
const templates = [
@ -86,6 +86,25 @@ export function openEditorMenu(event, codeMirror) {
openContextMenu(event, templates, true, selection);
}
// This function is used for the CodeViewer component
export function openSnippetMenu(codeMirror, event) {
const value = codeMirror.doc.getValue();
const selection = codeMirror.doc.getSelection();
const templates = [
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall',
click: () => {
codeMirror.execCommand('selectAll');
},
// Enabled if there is text to select
enabled: value.length > 0,
},
];
openContextMenu(event, templates, false, selection);
}
export function openCopyLinkMenu(text, event) {
const templates = [
{
@ -97,3 +116,9 @@ export function openCopyLinkMenu(text, event) {
];
openContextMenu(event, templates);
}
// Block context menu
export function stopContextMenu(event) {
event.preventDefault();
event.stopPropagation();
}

View file

@ -3,7 +3,9 @@ import mime from 'mime';
const formats = [
[/\.(mp4|m4v|webm|flv|f4v|ogv)$/i, 'video'],
[/\.(mp3|m4a|aac|wav|flac|ogg|opus)$/i, 'audio'],
[/\.(html|htm|xml|pdf|odf|doc|docx|md|markdown|txt|epub|org)$/i, 'document'],
[/\.(h|go|ja|java|js|jsx|c|cpp|cs|css|rb|scss|sh|php|py)$/i, 'script'],
[/\.(json|csv|txt|log|md|markdown|docx|pdf|xml|yml|yaml)$/i, 'document'],
[/\.(pdf|odf|doc|docx|epub|org|rtf)$/i, 'e-book'],
[/\.(stl|obj|fbx|gcode)$/i, '3D-file'],
];

BIN
static/img/broken.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View file

@ -1,7 +1,6 @@
:root {
/* Colors */
--color-divider: #53637C;;
--color-canvas: transparent;
--color-help: #8696AF;
@ -12,12 +11,11 @@
--color-placeholder: var(--color-bg-alt);
/* Text */
--text-color: #FFF;
--text-color: var(--color-white);
--text-help-color: var(--color-help);
--text-selection-color: #fff;
/* Form */
--form-label-color: #FFF;
--form-label-color: var(--color-white);
/* Input */
--input-bg: transparent;
@ -90,7 +88,7 @@
/* Scrollbar */
--scrollbar-thumb-bg: rgba(255, 255, 255, 0.20);
--scrollbar-thumb-hover-bg: #8696AF;
/* Shadows */
--box-shadow-header: 0px 6px 20px 1px rgba(0, 0, 0, 0.2);
}

347
yarn.lock
View file

@ -309,7 +309,7 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
argparse@^1.0.7:
argparse@^1.0.7, argparse@~1.0.3:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
dependencies:
@ -1282,7 +1282,7 @@ bluebird@^3.4.7, bluebird@^3.5.0, bluebird@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
bluebird@~3.4.1:
bluebird@~3.4.0, bluebird@~3.4.1:
version "3.4.7"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
@ -1368,6 +1368,43 @@ braces@^2.3.0, braces@^2.3.1:
split-string "^3.0.2"
to-regex "^3.0.1"
breakdance-util@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/breakdance-util/-/breakdance-util-0.1.5.tgz#c76bb92bac25f94d2adb90ead3b3e54140466b98"
dependencies:
diacritics-map "^0.1.0"
get-value "^2.0.6"
is-self-closing "^1.0.0"
kind-of "^3.1.0"
snapdragon-util "^1.0.6"
strip-color "^0.1.0"
typeof-article "^0.1.1"
word-regex "^0.1.1"
breakdance@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/breakdance/-/breakdance-3.0.1.tgz#475a989c8389f522876890ba14f397adfb0e3184"
dependencies:
breakdance-util "^0.1.5"
cheerio "^0.22.0"
condense-newlines "^0.2.1"
define-property "^1.0.0"
detect-indent "^5.0.0"
export-files "^2.1.1"
extend-shallow "^2.0.1"
is-self-closing "^1.0.0"
isobject "^3.0.0"
mixin-deep "^1.2.0"
repeat-string "^1.6.1"
snapdragon "^0.11.0"
snapdragon-cheerio "^1.1.0"
snapdragon-node "^1.0.6"
snapdragon-util "^2.1.1"
strip-attributes "^0.2.0"
trim-leading-lines "^0.1.1"
trim-trailing-lines "^1.1.0"
unescape "^0.2.0"
brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@ -1775,6 +1812,27 @@ cheerio@^0.19.0:
htmlparser2 "~3.8.1"
lodash "^3.2.0"
cheerio@^0.22.0:
version "0.22.0"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e"
dependencies:
css-select "~1.2.0"
dom-serializer "~0.1.0"
entities "~1.1.1"
htmlparser2 "^3.9.1"
lodash.assignin "^4.0.9"
lodash.bind "^4.1.4"
lodash.defaults "^4.0.1"
lodash.filter "^4.4.0"
lodash.flatten "^4.2.0"
lodash.foreach "^4.3.0"
lodash.map "^4.4.0"
lodash.merge "^4.4.0"
lodash.pick "^4.2.1"
lodash.reduce "^4.4.0"
lodash.reject "^4.4.0"
lodash.some "^4.4.0"
chokidar@^1.0.0, chokidar@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
@ -1949,6 +2007,10 @@ codemirror@*:
version "5.39.0"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.39.0.tgz#4654f7d2f7e525e04a62e72d9482348ccb37dce5"
codemirror@^5.39.2:
version "5.39.2"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.39.2.tgz#778aa13b55ebf280745c309cb1b148e3fc06f698"
collapse-white-space@^1.0.0, collapse-white-space@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.4.tgz#ce05cf49e54c3277ae573036a26851ba430a0091"
@ -2099,6 +2161,14 @@ concat-stream@1.6.2, concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^
readable-stream "^2.2.2"
typedarray "^0.0.6"
condense-newlines@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f"
dependencies:
extend-shallow "^2.0.1"
is-whitespace "^0.3.0"
kind-of "^3.0.2"
configstore@^3.0.0:
version "3.1.2"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f"
@ -2323,7 +2393,7 @@ css-loader@^0.28.9:
postcss-value-parser "^3.3.0"
source-list-map "^2.0.0"
css-select@^1.1.0:
css-select@^1.1.0, css-select@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858"
dependencies:
@ -2458,7 +2528,7 @@ debug@2.2.0:
dependencies:
ms "0.7.1"
debug@2.6.9, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
debug@2.6.9, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.2, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
@ -2650,6 +2720,10 @@ detect-indent@^4.0.0:
dependencies:
repeating "^2.0.0"
detect-indent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
detect-libc@^1.0.2, detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
@ -2673,6 +2747,10 @@ devtron@^1.4.0:
highlight.js "^9.3.0"
humanize-plus "^1.8.1"
diacritics-map@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/diacritics-map/-/diacritics-map-0.1.0.tgz#6dfc0ff9d01000a2edf2865371cac316e94977af"
diff@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf"
@ -2757,7 +2835,7 @@ domain-browser@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
domelementtype@1:
domelementtype@1, domelementtype@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
@ -2777,6 +2855,12 @@ domhandler@2.3:
dependencies:
domelementtype "1"
domhandler@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803"
dependencies:
domelementtype "1"
domutils@1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.1.6.tgz#bddc3de099b9a2efacc51c623f28f416ecc57485"
@ -2796,6 +2880,13 @@ domutils@1.5, domutils@1.5.1:
dom-serializer "0"
domelementtype "1"
domutils@^1.5.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
dependencies:
dom-serializer "0"
domelementtype "1"
dot-prop@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
@ -2810,6 +2901,12 @@ dotenv@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.0.0.tgz#24e37c041741c5f4b25324958ebbc34bca965935"
duck@~0.1.11:
version "0.1.11"
resolved "https://registry.yarnpkg.com/duck/-/duck-0.1.11.tgz#3adc1a3d2fbdd5879ffd3bda05ce0f69355e9093"
dependencies:
underscore "~1.4.4"
duplexer2@~0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
@ -3145,7 +3242,7 @@ entities@1.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26"
entities@~1.1.1:
entities@^1.1.1, entities@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
@ -3612,6 +3709,12 @@ expand-template@^1.0.2:
version "1.1.1"
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-1.1.1.tgz#981f188c0c3a87d2e28f559bc541426ff94f21dd"
export-files@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/export-files/-/export-files-2.1.1.tgz#bbf64574053a09e4eb98e5f43501d572b2c3ce7f"
dependencies:
lazy-cache "^1.0.3"
express@^4.13.3, express@^4.16.2:
version "4.16.3"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
@ -4613,6 +4716,17 @@ html-webpack-plugin@^2.30.1:
pretty-error "^2.0.2"
toposort "^1.0.0"
htmlparser2@^3.9.1:
version "3.9.2"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
dependencies:
domelementtype "^1.3.0"
domhandler "^2.3.0"
domutils "^1.5.1"
entities "^1.1.1"
inherits "^2.0.1"
readable-stream "^2.0.2"
htmlparser2@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.3.0.tgz#cc70d05a59f6542e43f0e685c982e14c924a9efe"
@ -5198,6 +5312,12 @@ is-retry-allowed@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
is-self-closing@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-self-closing/-/is-self-closing-1.0.1.tgz#5f406b527c7b12610176320338af0fa3896416e4"
dependencies:
self-closing-tags "^1.0.1"
is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
@ -5230,6 +5350,10 @@ is-whitespace-character@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.2.tgz#ede53b4c6f6fb3874533751ec9280d01928d03ed"
is-whitespace@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f"
is-windows@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c"
@ -5460,6 +5584,12 @@ jsx-loader@^0.13.2:
jstransform "11"
loader-utils "^0.2.2"
jszip@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-2.5.0.tgz#7444fd8551ddf3e5da7198fea0c91bc8308cc274"
dependencies:
pako "~0.2.5"
kebab-case@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/kebab-case/-/kebab-case-1.0.0.tgz#3f9e4990adcad0c686c0e701f7645868f75f91eb"
@ -5475,7 +5605,7 @@ killable@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
dependencies:
@ -5511,6 +5641,12 @@ lazy-cache@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
lazy-cache@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264"
dependencies:
set-getter "^0.1.0"
lazy-val@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.3.tgz#bb97b200ef00801d94c317e29dc6ed39e31c5edc"
@ -5706,6 +5842,14 @@ lodash.assign@^4.0.3, lodash.assign@^4.0.6, lodash.assign@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7"
lodash.assignin@^4.0.9:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2"
lodash.bind@^4.1.4:
version "4.2.1"
resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35"
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
@ -5718,6 +5862,22 @@ lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
lodash.defaults@^4.0.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
lodash.filter@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace"
lodash.flatten@^4.2.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
lodash.foreach@^4.3.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53"
lodash.forin@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.forin/-/lodash.forin-4.4.0.tgz#5d3f20ae564011fbe88381f7d98949c9c9519731"
@ -5734,22 +5894,46 @@ lodash.isequal@4.5.0, lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
lodash.map@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
lodash.merge@^4.4.0:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
lodash.mergewith@^4.6.0:
version "4.6.1"
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
lodash.pick@^4.2.1:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
lodash.pickby@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.pickby/-/lodash.pickby-4.6.0.tgz#7dea21d8c18d7703a27c704c15d3b84a67e33aff"
lodash.reduce@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b"
lodash.reject@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415"
lodash.set@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
lodash.some@^4.4.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
lodash.tail@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664"
@ -5766,7 +5950,7 @@ lodash.unset@^4.5.2:
version "4.5.2"
resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed"
lodash@3.10.1, lodash@^3.10.1, lodash@^3.2.0:
lodash@3.10.1, lodash@^3.10.1, lodash@^3.2.0, lodash@^3.5.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
@ -5811,6 +5995,14 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lop@~0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/lop/-/lop-0.4.0.tgz#4f0e4384d5c4f455d0b86d254fd52a9d05593c2c"
dependencies:
duck "~0.1.11"
option "~0.2.1"
underscore "~1.4.4"
loud-rejection@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
@ -5854,6 +6046,19 @@ make-runnable@^1.3.6:
bluebird "^3.5.0"
yargs "^4.7.1"
mammoth@^1.4.6:
version "1.4.6"
resolved "https://registry.yarnpkg.com/mammoth/-/mammoth-1.4.6.tgz#1818934b0b34bb56f23b07e0670af31778543a8e"
dependencies:
argparse "~1.0.3"
bluebird "~3.4.0"
jszip "~2.5.0"
lop "~0.4.0"
path-is-absolute "^1.0.0"
sax "~1.1.1"
underscore "~1.8.3"
xmlbuilder "~2.6.4"
map-cache@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@ -6625,14 +6830,14 @@ object-visit@^1.0.0:
dependencies:
isobject "^3.0.0"
object.omit@^2.0.0:
object.omit@^2.0.0, object.omit@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
dependencies:
for-own "^0.1.4"
is-extendable "^0.1.1"
object.pick@^1.3.0:
object.pick@^1.2.0, object.pick@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
dependencies:
@ -6685,6 +6890,10 @@ optimist@~0.6.0, optimist@~0.6.1:
minimist "~0.0.1"
wordwrap "~0.0.2"
option@~0.2.1:
version "0.2.4"
resolved "https://registry.yarnpkg.com/option/-/option-0.2.4.tgz#fd475cdf98dcabb3cb397a3ba5284feb45edbfe4"
optionator@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.6.0.tgz#b63ecbbf0e315fad4bc9827b45dc7ba45284fcb6"
@ -6822,7 +7031,7 @@ package-json@^4.0.0:
registry-url "^3.0.3"
semver "^5.1.0"
pako@~0.2.0:
pako@~0.2.0, pako@~0.2.5:
version "0.2.9"
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
@ -8265,6 +8474,10 @@ sax@>=0.6.0, sax@^1.2.4, sax@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
sax@~1.1.1:
version "1.1.6"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.6.tgz#5d616be8a5e607d54e114afae55b7eaf2fcc3240"
schema-utils@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf"
@ -8295,6 +8508,10 @@ select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
self-closing-tags@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/self-closing-tags/-/self-closing-tags-1.0.1.tgz#6c5fa497994bb826b484216916371accee490a5d"
selfsigned@^1.9.1:
version "1.10.3"
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.3.tgz#d628ecf9e3735f84e8bafba936b3cf85bea43823"
@ -8366,6 +8583,12 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
set-getter@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376"
dependencies:
to-object-path "^0.3.0"
set-immediate-shim@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
@ -8488,6 +8711,26 @@ slice-ansi@1.0.0:
dependencies:
is-fullwidth-code-point "^2.0.0"
snapdragon-cheerio@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/snapdragon-cheerio/-/snapdragon-cheerio-1.1.0.tgz#16f3bd3fa1615f85c5f826504c5bb406cd340eb7"
dependencies:
cheerio "^0.22.0"
define-property "^0.2.5"
extend-shallow "^2.0.1"
is-self-closing "^1.0.0"
snapdragon-node "^1.0.6"
snapdragon-util "^2.0.0"
snapdragon-node@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-1.0.6.tgz#2448d5ef6fea7f5e8fd5326a0a114854da271356"
dependencies:
define-property "^0.2.5"
isobject "^3.0.0"
lazy-cache "^2.0.2"
snapdragon-util "^1.0.3"
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
@ -8496,12 +8739,44 @@ snapdragon-node@^2.0.1:
isobject "^3.0.0"
snapdragon-util "^3.0.1"
snapdragon-util@^1.0.3, snapdragon-util@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-1.0.6.tgz#8b3d2d6dec8930c90e054ba052e562ca1b3a621e"
dependencies:
define-property "^0.2.5"
kind-of "^3.1.0"
lazy-cache "^2.0.2"
snapdragon-node "^1.0.6"
snapdragon-util@^2.0.0, snapdragon-util@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-2.1.1.tgz#552779df8a1493a0e78c06cc80953a262770957a"
dependencies:
kind-of "^3.1.0"
snapdragon-util@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
dependencies:
kind-of "^3.2.0"
snapdragon@^0.11.0:
version "0.11.5"
resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.11.5.tgz#522812d175f24f919629fd37406b02e434e645e6"
dependencies:
component-emitter "^1.2.1"
debug "^2.6.2"
define-property "^0.2.5"
extend-shallow "^2.0.1"
get-value "^2.0.6"
isobject "^3.0.0"
map-cache "^0.2.2"
snapdragon-node "^1.0.6"
snapdragon-util "^2.1.1"
source-map "^0.5.6"
source-map-resolve "^0.5.0"
use "^3.1.0"
snapdragon@^0.8.1:
version "0.8.2"
resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d"
@ -8853,6 +9128,16 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
strip-attributes@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/strip-attributes/-/strip-attributes-0.2.0.tgz#30ba227c6abf6356a51b2b68626c795f19280945"
dependencies:
cheerio "^0.22.0"
extend-shallow "^2.0.1"
isobject "^3.0.0"
object.omit "^2.0.1"
object.pick "^1.2.0"
strip-bom@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
@ -8863,6 +9148,10 @@ strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
strip-color@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/strip-color/-/strip-color-0.1.0.tgz#106f65d3d3e6a2d9401cac0eb0ce8b8a702b4f7b"
strip-dirs@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5"
@ -9165,6 +9454,12 @@ tree-kill@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.0.tgz#5846786237b4239014f05db156b643212d4c6f36"
trim-leading-lines@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/trim-leading-lines/-/trim-leading-lines-0.1.1.tgz#0e7cac3e83042dcf95a74ed36966f17744d5c169"
dependencies:
is-whitespace "^0.3.0"
trim-lines@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.1.tgz#da738ff58fa74817588455e30b11b85289f2a396"
@ -9177,7 +9472,7 @@ trim-right@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
trim-trailing-lines@^1.0.0:
trim-trailing-lines@^1.0.0, trim-trailing-lines@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.1.tgz#e0ec0810fd3c3f1730516b45f49083caaf2774d9"
@ -9236,6 +9531,12 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typeof-article@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/typeof-article/-/typeof-article-0.1.1.tgz#9f07e733c3fbb646ffa9e61c08debacd460e06af"
dependencies:
kind-of "^3.1.0"
typo-js@*:
version "1.0.3"
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.0.3.tgz#54d8ebc7949f1a7810908b6002c6841526c99d5a"
@ -9320,6 +9621,18 @@ underscore@>1.4.4:
version "1.9.1"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
underscore@~1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604"
underscore@~1.8.3:
version "1.8.3"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022"
unescape@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/unescape/-/unescape-0.2.0.tgz#b78b9b60c86f1629df181bf53eee3bc8d6367ddf"
unherit@^1.0.4:
version "1.1.1"
resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.1.tgz#132748da3e88eab767e08fabfbb89c5e9d28628c"
@ -9862,6 +10175,10 @@ window-size@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"
word-regex@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/word-regex/-/word-regex-0.1.2.tgz#a3bc7f2d222ce4a93c246c3ef69458f61f511639"
wordwrap@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
@ -9943,6 +10260,12 @@ xmlbuilder@^9.0.7:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
xmlbuilder@~2.6.4:
version "2.6.5"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-2.6.5.tgz#6ff7ad60fb72d22764f007a164b77f2bf1400526"
dependencies:
lodash "^3.5.0"
xmldom@0.1.x:
version "0.1.27"
resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9"