Check for IDE update at startup (#797)

* Remove check for updates on startup setting

* Remove useless exported function

* Update template-package.json used to package IDE

* Add function to get channel file during packaging step

* Add updates check

* move ide updater on backend

* configure updater options

* add auto update preferences

* TMP check updates on start and download

* index on check-update-startup: fcb8f6e TMP check updates on start and download

* set version to skip on local storage

* add IDE setting to toggle update check on start-up

* comment out check for updates on startup and auto update settings

* Update Theia to 1.22.1

* updated CI

* download changelog and show it in IDE updater dialog

* remove useless file

* remove useless code

* add i18n to updater dialog

* fix i18n

* refactor UpdateInfo typing

* add macos zip to artifacts

* Simply use `--ignore-engines`

* Use correct --ignore-engines

* Fix semver#valid call

* Use C++17

* updated documentation

* add update channel preference

* update updater url

* updated documentation

* Fix the C++ version

* Build flag for cpp

* add disclaimer with correct node version

* Update `electron-builder`

* Fix `Electron.Menu` issue

* Skip electron rebuild

* Rebuild native dependencies beforehand

* Use resolutions section

* Update template-package.json as well

* move ide-updater to electron application

* refactor ide-updater service

* update yarn.lock

* update i18n

* Revert "Add gRPC user agent (#834)"

This reverts commit 5ab3a747a6e8bf551b5c0e59a98154d387e0a200.

* fix ide download url

* update latest file in CI

* fix i18n check

Co-authored-by: Silvano Cerza <silvanocerza@gmail.com>
Co-authored-by: Francesco Stasi <f.stasi@me.com>
Co-authored-by: Mark Sujew <msujew@yahoo.de>
This commit is contained in:
Alberto Iannaccone 2022-02-15 18:01:19 +01:00 committed by GitHub
parent 9ecff86bbe
commit f660058c75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1915 additions and 346 deletions

View File

@ -60,7 +60,9 @@ jobs:
if [ $IS_FORK = true ]; then if [ $IS_FORK = true ]; then
echo "Skipping the app signing: building from a fork." echo "Skipping the app signing: building from a fork."
else else
export BUILD_SUFFIX="linux";
if [ "${{ runner.OS }}" = "macOS" ]; then if [ "${{ runner.OS }}" = "macOS" ]; then
export BUILD_SUFFIX="mac";
export CSC_LINK="${{ runner.temp }}/signing_certificate.p12" export CSC_LINK="${{ runner.temp }}/signing_certificate.p12"
# APPLE_SIGNING_CERTIFICATE_P12 secret was produced by following the procedure from: # APPLE_SIGNING_CERTIFICATE_P12 secret was produced by following the procedure from:
# https://www.kencochrane.com/2020/08/01/build-and-sign-golang-binaries-for-macos-with-github-actions/#exporting-the-developer-certificate # https://www.kencochrane.com/2020/08/01/build-and-sign-golang-binaries-for-macos-with-github-actions/#exporting-the-developer-certificate
@ -69,6 +71,7 @@ jobs:
export CSC_KEY_PASSWORD="${{ secrets.KEYCHAIN_PASSWORD }}" export CSC_KEY_PASSWORD="${{ secrets.KEYCHAIN_PASSWORD }}"
elif [ "${{ runner.OS }}" = "Windows" ]; then elif [ "${{ runner.OS }}" = "Windows" ]; then
export BUILD_SUFFIX="";
export CSC_LINK="${{ runner.temp }}/signing_certificate.pfx" export CSC_LINK="${{ runner.temp }}/signing_certificate.pfx"
npm config set msvs_version 2017 --global npm config set msvs_version 2017 --global
echo "${{ secrets.WINDOWS_SIGNING_CERTIFICATE_PFX }}" | base64 --decode > "$CSC_LINK" echo "${{ secrets.WINDOWS_SIGNING_CERTIFICATE_PFX }}" | base64 --decode > "$CSC_LINK"
@ -80,6 +83,14 @@ jobs:
yarn --cwd ./electron/packager/ yarn --cwd ./electron/packager/
yarn --cwd ./electron/packager/ package yarn --cwd ./electron/packager/ package
export BUILD_PREFIX="stable"
if [ "$IS_NIGHTLY" = true ]; then
export BUILD_PREFIX="nightly"
fi
mv electron/build/dist/latest-$BUILD_SUFFIX.yml electron/build/dist/$BUILD_PREFIX-$BUILD_SUFFIX.yml
rm electron/build/dist/alpha* electron/build/dist/beta*
- name: Upload [GitHub Actions] - name: Upload [GitHub Actions]
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
@ -98,7 +109,9 @@ jobs:
- path: '*Linux_64bit.zip' - path: '*Linux_64bit.zip'
name: Linux_X86-64 name: Linux_X86-64
- path: '*macOS_64bit.dmg' - path: '*macOS_64bit.dmg'
name: macOS name: macOS_dmg
- path: '*macOS_64bit.zip'
name: macOS_zip
- path: '*Windows_64bit.exe' - path: '*Windows_64bit.exe'
name: Windows_X86-64_interactive_installer name: Windows_X86-64_interactive_installer
- path: '*Windows_64bit.msi' - path: '*Windows_64bit.msi'

View File

@ -65,6 +65,7 @@
"css-element-queries": "^1.2.0", "css-element-queries": "^1.2.0",
"dateformat": "^3.0.3", "dateformat": "^3.0.3",
"deepmerge": "2.0.1", "deepmerge": "2.0.1",
"electron-updater": "^4.6.5",
"fuzzy": "^0.1.3", "fuzzy": "^0.1.3",
"glob": "^7.1.6", "glob": "^7.1.6",
"google-protobuf": "^3.11.4", "google-protobuf": "^3.11.4",
@ -82,6 +83,7 @@
"ps-tree": "^1.2.0", "ps-tree": "^1.2.0",
"query-string": "^7.0.1", "query-string": "^7.0.1",
"react-disable": "^0.1.0", "react-disable": "^0.1.0",
"react-markdown": "^8.0.0",
"react-select": "^3.0.4", "react-select": "^3.0.4",
"react-tabs": "^3.1.2", "react-tabs": "^3.1.2",
"react-window": "^1.8.6", "react-window": "^1.8.6",

View File

@ -1,36 +1,42 @@
// @ts-check // @ts-check
(async () => { (async () => {
const { Octokit } = require('@octokit/rest'); const { Octokit } = require('@octokit/rest');
const fs = require("fs"); const fs = require('fs');
const path = require("path"); const path = require('path');
const octokit = new Octokit({ const octokit = new Octokit({
userAgent: 'Arduino IDE compose-changelog.js', userAgent: 'Arduino IDE compose-changelog.js',
}); });
const response = await octokit.rest.repos.listReleases({ const response = await octokit.rest.repos
.listReleases({
owner: 'arduino', owner: 'arduino',
repo: 'arduino-ide', repo: 'arduino-ide',
}).catch(err => { })
.catch((err) => {
console.error(err); console.error(err);
process.exit(1); process.exit(1);
}) });
const releases = response.data; const releases = response.data;
let fullChangelog = releases.reduce((acc, item) => { let fullChangelog = releases.reduce((acc, item, index) => {
// Process each line separately // Process each line separately
const body = item.body.split('\n').map(processLine).join('\n') const body = item.body.split('\n').map(processLine).join('\n');
// item.name is the name of the release changelog // item.name is the name of the release changelog
return acc + `# ${item.name}\n\n${body}\n\n---\n\n`; return (
acc +
`## ${item.name}\n\n${body}${
index !== releases.length - 1 ? '\n\n---\n\n' : '\n'
}`
);
}, ''); }, '');
const args = process.argv.slice(2) const args = process.argv.slice(2);
if (args.length == 0) { if (args.length == 0) {
console.error("Missing argument to destination file") console.error('Missing argument to destination file');
process.exit(1) process.exit(1);
} }
const changelogFile = path.resolve(args[0]); const changelogFile = path.resolve(args[0]);
@ -38,19 +44,18 @@
changelogFile, changelogFile,
fullChangelog, fullChangelog,
{ {
flag: "w+", flag: 'w+',
}, },
err => { (err) => {
if (err) { if (err) {
console.error(err); console.error(err);
process.exit(1); process.exit(1);
} }
console.log("Changelog written to", changelogFile); console.log('Changelog written to', changelogFile);
} }
) );
})(); })();
// processLine applies different substitutions to line string. // processLine applies different substitutions to line string.
// We're assuming that there are no more than one substitution // We're assuming that there are no more than one substitution
// per line to be applied. // per line to be applied.
@ -61,7 +66,8 @@ const processLine = (line) => {
// * [#123](https://github.com/arduino/arduino-ide/pull/123/) // * [#123](https://github.com/arduino/arduino-ide/pull/123/)
// * [#123](https://github.com/arduino/arduino-ide/issues/123/) // * [#123](https://github.com/arduino/arduino-ide/issues/123/)
// If it does return the line as is. // If it does return the line as is.
let r = /(\(|\[)#\d+(\)|\])(\(|\[)https:\/\/github\.com\/arduino\/arduino-ide\/(pull|issues)\/(\d+)\/?(\)|\])/gm; let r =
/(\(|\[)#\d+(\)|\])(\(|\[)https:\/\/github\.com\/arduino\/arduino-ide\/(pull|issues)\/(\d+)\/?(\)|\])/gm;
if (r.test(line)) { if (r.test(line)) {
return line; return line;
} }
@ -70,9 +76,12 @@ const processLine = (line) => {
// * #123 // * #123
// If it does it's changed to: // If it does it's changed to:
// * [#123](https://github.com/arduino/arduino-ide/pull/123) // * [#123](https://github.com/arduino/arduino-ide/pull/123)
r = /#(\d+)/gm; r = /(?<![\w\d\/_]{1})#((\d)+)(?![\w\d\/_]{1})/gm;
if (r.test(line)) { if (r.test(line)) {
return line.replace(r, `[#$1](https://github.com/arduino/arduino-ide/pull/$1)`) return line.replace(
r,
`[#$1](https://github.com/arduino/arduino-ide/pull/$1)`
);
} }
// Check if a link with one of the following format exists: // Check if a link with one of the following format exists:
@ -85,7 +94,8 @@ const processLine = (line) => {
// * [#123](https://github.com/arduino/arduino-ide/issues/123) // * [#123](https://github.com/arduino/arduino-ide/issues/123)
// * [#123](https://github.com/arduino/arduino-ide/pull/123/) // * [#123](https://github.com/arduino/arduino-ide/pull/123/)
// * [#123](https://github.com/arduino/arduino-ide/issues/123/) // * [#123](https://github.com/arduino/arduino-ide/issues/123/)
r = /(https:\/\/github\.com\/arduino\/arduino-ide\/(pull|issues)\/(\d+)\/?)/gm; r =
/(https:\/\/github\.com\/arduino\/arduino-ide\/(pull|issues)\/(\d+)\/?)/gm;
if (r.test(line)) { if (r.test(line)) {
return line.replace(r, `[#$3]($1)`); return line.replace(r, `[#$3]($1)`);
} }
@ -95,11 +105,12 @@ const processLine = (line) => {
// * https://github.com/arduino/arduino-ide/compare/2.0.0-rc2...2.0.0-rc3/ // * https://github.com/arduino/arduino-ide/compare/2.0.0-rc2...2.0.0-rc3/
// If it does it's changed to: // If it does it's changed to:
// * [`2.0.0-rc2...2.0.0-rc3`](https://github.com/arduino/arduino-ide/compare/2.0.0-rc2...2.0.0-rc3) // * [`2.0.0-rc2...2.0.0-rc3`](https://github.com/arduino/arduino-ide/compare/2.0.0-rc2...2.0.0-rc3)
r = /(https:\/\/github\.com\/arduino\/arduino-ide\/compare\/([^\/]*))\/?\s?/gm; r =
/(https:\/\/github\.com\/arduino\/arduino-ide\/compare\/([^\/]*))\/?\s?/gm;
if (r.test(line)) { if (r.test(line)) {
return line.replace(r, '[`$2`]($1)');; return line.replace(r, '[`$2`]($1)');
} }
// If nothing matches just return the line as is // If nothing matches just return the line as is
return line; return line;
} };

View File

@ -68,8 +68,12 @@ import { ArduinoPreferences } from './arduino-preferences';
import { SketchesServiceClientImpl } from '../common/protocol/sketches-service-client-impl'; import { SketchesServiceClientImpl } from '../common/protocol/sketches-service-client-impl';
import { SaveAsSketch } from './contributions/save-as-sketch'; import { SaveAsSketch } from './contributions/save-as-sketch';
import { SketchbookWidgetContribution } from './widgets/sketchbook/sketchbook-widget-contribution'; import { SketchbookWidgetContribution } from './widgets/sketchbook/sketchbook-widget-contribution';
import { IDEUpdaterCommands } from './ide-updater/ide-updater-commands';
import { IDEUpdaterDialog } from './dialogs/ide-updater/ide-updater-dialog';
import { IDEUpdater } from '../common/protocol/ide-updater';
const INIT_LIBS_AND_PACKAGES = 'initializedLibsAndPackages'; const INIT_LIBS_AND_PACKAGES = 'initializedLibsAndPackages';
export const SKIP_IDE_VERSION = 'skipIDEVersion';
@injectable() @injectable()
export class ArduinoFrontendContribution export class ArduinoFrontendContribution
@ -78,8 +82,7 @@ export class ArduinoFrontendContribution
TabBarToolbarContribution, TabBarToolbarContribution,
CommandContribution, CommandContribution,
MenuContribution, MenuContribution,
ColorContribution ColorContribution {
{
@inject(ILogger) @inject(ILogger)
protected logger: ILogger; protected logger: ILogger;
@ -157,6 +160,15 @@ export class ArduinoFrontendContribution
@inject(LocalStorageService) @inject(LocalStorageService)
protected readonly localStorageService: LocalStorageService; protected readonly localStorageService: LocalStorageService;
@inject(IDEUpdaterCommands)
protected readonly updater: IDEUpdaterCommands;
@inject(IDEUpdaterDialog)
protected readonly updaterDialog: IDEUpdaterDialog;
@inject(IDEUpdater)
protected readonly updaterService: IDEUpdater;
protected invalidConfigPopup: protected invalidConfigPopup:
| Promise<void | 'No' | 'Yes' | undefined> | Promise<void | 'No' | 'Yes' | undefined>
| undefined; | undefined;
@ -251,7 +263,7 @@ export class ArduinoFrontendContribution
}); });
} }
onStart(app: FrontendApplication): void { async onStart(app: FrontendApplication): Promise<void> {
// Initialize all `pro-mode` widgets. This is a NOOP if in normal mode. // Initialize all `pro-mode` widgets. This is a NOOP if in normal mode.
for (const viewContribution of [ for (const viewContribution of [
this.fileNavigatorContributions, this.fileNavigatorContributions,
@ -266,6 +278,19 @@ export class ArduinoFrontendContribution
viewContribution.initializeLayout(app); viewContribution.initializeLayout(app);
} }
} }
this.updaterService.init(
this.arduinoPreferences.get('arduino.ide.updateChannel')
);
this.updater.checkForUpdates().then(async (updateInfo) => {
if (!updateInfo) return;
const versionToSkip = await this.localStorageService.getData<string>(
SKIP_IDE_VERSION
);
if (versionToSkip === updateInfo.version) return;
this.updaterDialog.open(updateInfo);
});
const start = async ({ selectedBoard }: BoardsConfig.Config) => { const start = async ({ selectedBoard }: BoardsConfig.Config) => {
if (selectedBoard) { if (selectedBoard) {
const { name, fqbn } = selectedBoard; const { name, fqbn } = selectedBoard;

View File

@ -262,6 +262,19 @@ import {
UserFieldsDialogWidget, UserFieldsDialogWidget,
} from './dialogs/user-fields/user-fields-dialog'; } from './dialogs/user-fields/user-fields-dialog';
import { nls } from '@theia/core/lib/common'; import { nls } from '@theia/core/lib/common';
import { IDEUpdaterCommands } from './ide-updater/ide-updater-commands';
import {
IDEUpdater,
IDEUpdaterClient,
IDEUpdaterPath,
} from '../common/protocol/ide-updater';
import { IDEUpdaterClientImpl } from './ide-updater/ide-updater-client-impl';
import {
IDEUpdaterDialog,
IDEUpdaterDialogProps,
IDEUpdaterDialogWidget,
} from './dialogs/ide-updater/ide-updater-dialog';
import { ElectronIpcConnectionProvider } from '@theia/core/lib/electron-browser/messaging/electron-ipc-connection-provider';
const ElementQueries = require('css-element-queries/src/ElementQueries'); const ElementQueries = require('css-element-queries/src/ElementQueries');
@ -407,8 +420,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(SerialService) bind(SerialService)
.toDynamicValue((context) => { .toDynamicValue((context) => {
const connection = context.container.get(WebSocketConnectionProvider); const connection = context.container.get(WebSocketConnectionProvider);
const client = const client = context.container.get<SerialServiceClient>(
context.container.get<SerialServiceClient>(SerialServiceClient); SerialServiceClient
);
return connection.createProxy(SerialServicePath, client); return connection.createProxy(SerialServicePath, client);
}) })
.inSingletonScope(); .inSingletonScope();
@ -472,8 +486,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
.inSingletonScope(); .inSingletonScope();
rebind(TheiaEditorWidgetFactory).to(EditorWidgetFactory).inSingletonScope(); rebind(TheiaEditorWidgetFactory).to(EditorWidgetFactory).inSingletonScope();
rebind(TabBarToolbarFactory).toFactory( rebind(TabBarToolbarFactory).toFactory(
({ container: parentContainer }) => ({ container: parentContainer }) => () => {
() => {
const container = parentContainer.createChild(); const container = parentContainer.createChild();
container.bind(TabBarToolbar).toSelf().inSingletonScope(); container.bind(TabBarToolbar).toSelf().inSingletonScope();
return container.get(TabBarToolbar); return container.get(TabBarToolbar);
@ -642,13 +655,15 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
// Enable the dirty indicator on uncloseable widgets. // Enable the dirty indicator on uncloseable widgets.
rebind(TabBarRendererFactory).toFactory((context) => () => { rebind(TabBarRendererFactory).toFactory((context) => () => {
const contextMenuRenderer = const contextMenuRenderer = context.container.get<ContextMenuRenderer>(
context.container.get<ContextMenuRenderer>(ContextMenuRenderer); ContextMenuRenderer
);
const decoratorService = context.container.get<TabBarDecoratorService>( const decoratorService = context.container.get<TabBarDecoratorService>(
TabBarDecoratorService TabBarDecoratorService
); );
const iconThemeService = const iconThemeService = context.container.get<IconThemeService>(
context.container.get<IconThemeService>(IconThemeService); IconThemeService
);
return new TabBarRenderer( return new TabBarRenderer(
contextMenuRenderer, contextMenuRenderer,
decoratorService, decoratorService,
@ -756,9 +771,32 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
title: 'UploadCertificate', title: 'UploadCertificate',
}); });
bind(IDEUpdaterDialogWidget).toSelf().inSingletonScope();
bind(IDEUpdaterDialog).toSelf().inSingletonScope();
bind(IDEUpdaterDialogProps).toConstantValue({
title: 'IDEUpdater',
});
bind(UserFieldsDialogWidget).toSelf().inSingletonScope(); bind(UserFieldsDialogWidget).toSelf().inSingletonScope();
bind(UserFieldsDialog).toSelf().inSingletonScope(); bind(UserFieldsDialog).toSelf().inSingletonScope();
bind(UserFieldsDialogProps).toConstantValue({ bind(UserFieldsDialogProps).toConstantValue({
title: 'UserFields', title: 'UserFields',
}); });
bind(IDEUpdaterCommands).toSelf().inSingletonScope();
bind(CommandContribution).toService(IDEUpdaterCommands);
// Frontend binding for the IDE Updater service
bind(IDEUpdaterClientImpl).toSelf().inSingletonScope();
bind(IDEUpdaterClient).toService(IDEUpdaterClientImpl);
bind(IDEUpdater)
.toDynamicValue((context) => {
const client = context.container.get(IDEUpdaterClientImpl);
return ElectronIpcConnectionProvider.createProxy(
context.container,
IDEUpdaterPath,
client
);
})
.inSingletonScope();
}); });

View File

@ -9,6 +9,11 @@ import {
import { nls } from '@theia/core/lib/common'; import { nls } from '@theia/core/lib/common';
import { CompilerWarningLiterals, CompilerWarnings } from '../common/protocol'; import { CompilerWarningLiterals, CompilerWarnings } from '../common/protocol';
export enum UpdateChannel {
Stable = 'stable',
Nightly = 'nightly',
}
export const ArduinoConfigSchema: PreferenceSchema = { export const ArduinoConfigSchema: PreferenceSchema = {
type: 'object', type: 'object',
properties: { properties: {
@ -64,13 +69,14 @@ export const ArduinoConfigSchema: PreferenceSchema = {
), ),
default: 0, default: 0,
}, },
'arduino.ide.autoUpdate': { 'arduino.ide.updateChannel': {
type: 'boolean', type: 'string',
enum: Object.values(UpdateChannel) as UpdateChannel[],
default: UpdateChannel.Stable,
description: nls.localize( description: nls.localize(
'arduino/preferences/ide.autoUpdate', 'arduino/preferences/ide.updateChannel',
'True to enable automatic update checks. The IDE will check for updates automatically and periodically.' "Release channel to get updated from. 'stable' is the stable release, 'nightly' is the latest development build."
), ),
default: true,
}, },
'arduino.board.certificates': { 'arduino.board.certificates': {
type: 'string', type: 'string',
@ -171,7 +177,7 @@ export interface ArduinoConfiguration {
'arduino.upload.verify': boolean; 'arduino.upload.verify': boolean;
'arduino.window.autoScale': boolean; 'arduino.window.autoScale': boolean;
'arduino.window.zoomLevel': number; 'arduino.window.zoomLevel': number;
'arduino.ide.autoUpdate': boolean; 'arduino.ide.updateChannel': UpdateChannel;
'arduino.board.certificates': string; 'arduino.board.certificates': string;
'arduino.sketchbook.showAllFiles': boolean; 'arduino.sketchbook.showAllFiles': boolean;
'arduino.cloud.enabled': boolean; 'arduino.cloud.enabled': boolean;
@ -188,16 +194,10 @@ export interface ArduinoConfiguration {
export const ArduinoPreferences = Symbol('ArduinoPreferences'); export const ArduinoPreferences = Symbol('ArduinoPreferences');
export type ArduinoPreferences = PreferenceProxy<ArduinoConfiguration>; export type ArduinoPreferences = PreferenceProxy<ArduinoConfiguration>;
export function createArduinoPreferences(
preferences: PreferenceService
): ArduinoPreferences {
return createPreferenceProxy(preferences, ArduinoConfigSchema);
}
export function bindArduinoPreferences(bind: interfaces.Bind): void { export function bindArduinoPreferences(bind: interfaces.Bind): void {
bind(ArduinoPreferences).toDynamicValue((ctx) => { bind(ArduinoPreferences).toDynamicValue((ctx) => {
const preferences = ctx.container.get<PreferenceService>(PreferenceService); const preferences = ctx.container.get<PreferenceService>(PreferenceService);
return createArduinoPreferences(preferences); return createPreferenceProxy(preferences, ArduinoConfigSchema);
}); });
bind(PreferenceContribution).toConstantValue({ bind(PreferenceContribution).toConstantValue({
schema: ArduinoConfigSchema, schema: ArduinoConfigSchema,

View File

@ -0,0 +1,28 @@
import * as React from 'react';
export type ProgressBarProps = {
percent?: number;
showPercentage?: boolean;
};
export default function ProgressBar({
percent = 0,
showPercentage = false,
}: ProgressBarProps): React.ReactElement {
const roundedPercent = Math.round(percent);
return (
<div className="progress-bar">
<div className="progress-bar--outer">
<div
className="progress-bar--inner"
style={{ width: `${roundedPercent}%` }}
/>
</div>
{showPercentage && (
<div className="progress-bar--percentage">
<div className="progress-bar--percentage-text">{roundedPercent}%</div>
</div>
)}
</div>
);
}

View File

@ -0,0 +1,159 @@
import { nls } from '@theia/core/lib/common';
import { shell } from 'electron';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import ReactMarkdown from 'react-markdown';
import { ProgressInfo, UpdateInfo } from '../../../common/protocol/ide-updater';
import ProgressBar from '../../components/ProgressBar';
export type IDEUpdaterComponentProps = {
updateInfo: UpdateInfo;
downloadFinished?: boolean;
downloadStarted?: boolean;
progress?: ProgressInfo;
error?: Error;
onDownload: () => void;
onClose: () => void;
onSkipVersion: () => void;
onCloseAndInstall: () => void;
};
export const IDEUpdaterComponent = ({
updateInfo: { version, releaseNotes },
downloadStarted = false,
downloadFinished = false,
progress,
error,
onDownload,
onClose,
onSkipVersion,
onCloseAndInstall,
}: IDEUpdaterComponentProps): React.ReactElement => {
const changelogDivRef = React.useRef() as React.MutableRefObject<
HTMLDivElement
>;
React.useEffect(() => {
if (!!releaseNotes) {
let changelog: string;
if (typeof releaseNotes === 'string') changelog = releaseNotes;
else
changelog = releaseNotes.reduce((acc, item) => {
return item.note ? (acc += `${item.note}\n\n`) : acc;
}, '');
ReactDOM.render(
<ReactMarkdown
components={{
a: ({ href, children, ...props }) => (
<a onClick={() => href && shell.openExternal(href)} {...props}>
{children}
</a>
),
}}
>
{changelog}
</ReactMarkdown>,
changelogDivRef.current
);
}
}, [releaseNotes]);
const closeButton = (
<button onClick={onClose} type="button" className="theia-button secondary">
{nls.localize('arduino/ide-updater/notNowButton', 'Not now')}
</button>
);
return (
<div className="ide-updater-dialog--content">
{downloadFinished ? (
<div className="ide-updater-dialog--downloaded">
<div>
{nls.localize(
'arduino/ide-updater/versionDownloaded',
'Arduino IDE {0} has been downloaded.',
version
)}
</div>
<div>
{nls.localize(
'arduino/ide-updater/closeToInstallNotice',
'Close the software and install the update on your machine.'
)}
</div>
<div className="buttons-container">
{closeButton}
<button
onClick={onCloseAndInstall}
type="button"
className="theia-button close-and-install"
>
{nls.localize(
'arduino/ide-updater/closeAndInstallButton',
'Close and Install'
)}
</button>
</div>
</div>
) : downloadStarted ? (
<div className="ide-updater-dialog--downloading">
<div>
{nls.localize(
'arduino/ide-updater/downloadingNotice',
'Downloading the latest version of the Arduino IDE.'
)}
</div>
<ProgressBar percent={progress?.percent} showPercentage />
</div>
) : (
<div className="ide-updater-dialog--pre-download">
<div className="ide-updater-dialog--logo-container">
<div className="ide-updater-dialog--logo"></div>
</div>
<div className="ide-updater-dialog--new-version-text dialogSection">
<div className="dialogRow">
<div className="bold">
{nls.localize(
'arduino/ide-updater/updateAvailable',
'Update Available'
)}
</div>
</div>
<div className="dialogRow">
{nls.localize(
'arduino/ide-updater/newVersionAvailable',
'A new version of Arduino IDE ({0}) is available for download.',
version
)}
</div>
{releaseNotes && (
<div className="dialogRow">
<div className="changelog-container" ref={changelogDivRef} />
</div>
)}
<div className="buttons-container">
<button
onClick={onSkipVersion}
type="button"
className="theia-button secondary skip-version"
>
{nls.localize(
'arduino/ide-updater/skipVersionButton',
'Skip Version'
)}
</button>
<div className="push"></div>
{closeButton}
<button
onClick={onDownload}
type="button"
className="theia-button primary"
>
{nls.localize('arduino/ide-updater/downloadButton', 'Download')}
</button>
</div>
</div>
</div>
)}
{!!error && <div className="error-container">{error}</div>}
</div>
);
};

View File

@ -0,0 +1,166 @@
import * as React from 'react';
import { inject, injectable } from 'inversify';
import { DialogProps } from '@theia/core/lib/browser/dialogs';
import { AbstractDialog } from '../../theia/dialogs/dialogs';
import { Widget } from '@phosphor/widgets';
import { Message } from '@phosphor/messaging';
import { ReactWidget } from '@theia/core/lib/browser/widgets/react-widget';
import { nls } from '@theia/core';
import { IDEUpdaterComponent } from './ide-updater-component';
import { IDEUpdaterCommands } from '../../ide-updater/ide-updater-commands';
import {
IDEUpdaterClient,
ProgressInfo,
UpdateInfo,
} from '../../../common/protocol/ide-updater';
import { LocalStorageService } from '@theia/core/lib/browser';
import { SKIP_IDE_VERSION } from '../../arduino-frontend-contribution';
@injectable()
export class IDEUpdaterDialogWidget extends ReactWidget {
protected isOpen = new Object();
updateInfo: UpdateInfo;
progressInfo: ProgressInfo | undefined;
error: Error | undefined;
downloadFinished: boolean;
downloadStarted: boolean;
onClose: () => void;
@inject(IDEUpdaterCommands)
protected readonly updater: IDEUpdaterCommands;
@inject(IDEUpdaterClient)
protected readonly updaterClient: IDEUpdaterClient;
@inject(LocalStorageService)
protected readonly localStorageService: LocalStorageService;
init(updateInfo: UpdateInfo, onClose: () => void): void {
this.updateInfo = updateInfo;
this.progressInfo = undefined;
this.error = undefined;
this.downloadStarted = false;
this.downloadFinished = false;
this.onClose = onClose;
this.updaterClient.onError((e) => {
this.error = e;
this.update();
});
this.updaterClient.onDownloadProgressChanged((e) => {
this.progressInfo = e;
this.update();
});
this.updaterClient.onDownloadFinished((e) => {
this.downloadFinished = true;
this.update();
});
}
async onSkipVersion(): Promise<void> {
this.localStorageService.setData<string>(
SKIP_IDE_VERSION,
this.updateInfo.version
);
this.close();
}
close(): void {
super.close();
this.onClose();
}
onDispose(): void {
if (this.downloadStarted && !this.downloadFinished)
this.updater.stopDownload();
}
async onDownload(): Promise<void> {
this.progressInfo = undefined;
this.downloadStarted = true;
this.error = undefined;
this.updater.downloadUpdate();
this.update();
}
onCloseAndInstall(): void {
this.updater.quitAndInstall();
}
protected render(): React.ReactNode {
return !!this.updateInfo ? (
<form>
<IDEUpdaterComponent
updateInfo={this.updateInfo}
downloadStarted={this.downloadStarted}
downloadFinished={this.downloadFinished}
progress={this.progressInfo}
onClose={this.close.bind(this)}
onSkipVersion={this.onSkipVersion.bind(this)}
onDownload={this.onDownload.bind(this)}
onCloseAndInstall={this.onCloseAndInstall.bind(this)}
/>
</form>
) : null;
}
}
@injectable()
export class IDEUpdaterDialogProps extends DialogProps {}
@injectable()
export class IDEUpdaterDialog extends AbstractDialog<UpdateInfo> {
@inject(IDEUpdaterDialogWidget)
protected readonly widget: IDEUpdaterDialogWidget;
constructor(
@inject(IDEUpdaterDialogProps)
protected readonly props: IDEUpdaterDialogProps
) {
super({
title: nls.localize(
'arduino/updater/ideUpdaterDialog',
'Software Update'
),
});
this.contentNode.classList.add('ide-updater-dialog');
this.acceptButton = undefined;
}
get value(): UpdateInfo {
return this.widget.updateInfo;
}
protected onAfterAttach(msg: Message): void {
if (this.widget.isAttached) {
Widget.detach(this.widget);
}
Widget.attach(this.widget, this.contentNode);
super.onAfterAttach(msg);
this.update();
}
async open(
data: UpdateInfo | undefined = undefined
): Promise<UpdateInfo | undefined> {
if (data && data.version) {
this.widget.init(data, this.close.bind(this));
return super.open();
}
}
protected onUpdateRequest(msg: Message): void {
super.onUpdateRequest(msg);
this.widget.update();
}
protected onActivateRequest(msg: Message): void {
super.onActivateRequest(msg);
this.widget.activate();
}
close(): void {
this.widget.dispose();
super.close();
}
}

View File

@ -260,18 +260,6 @@ export class SettingsComponent extends React.Component<
'Verify code after upload' 'Verify code after upload'
)} )}
</label> </label>
<label className="flex-line">
<input
type="checkbox"
checked={this.state.checkForUpdates}
onChange={this.checkForUpdatesDidChange}
disabled={true}
/>
{nls.localize(
'arduino/preferences/checkForUpdates',
'Check for updates on startup'
)}
</label>
<label className="flex-line"> <label className="flex-line">
<input <input
type="checkbox" type="checkbox"
@ -444,7 +432,9 @@ export class SettingsComponent extends React.Component<
); );
} }
protected noopKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => { protected noopKeyDown = (
event: React.KeyboardEvent<HTMLInputElement>
): void => {
if (this.isControlKey(event)) { if (this.isControlKey(event)) {
return; return;
} }
@ -454,7 +444,7 @@ export class SettingsComponent extends React.Component<
protected numbersOnlyKeyDown = ( protected numbersOnlyKeyDown = (
event: React.KeyboardEvent<HTMLInputElement> event: React.KeyboardEvent<HTMLInputElement>
) => { ): void => {
if (this.isControlKey(event)) { if (this.isControlKey(event)) {
return; return;
} }
@ -466,7 +456,7 @@ export class SettingsComponent extends React.Component<
} }
}; };
protected browseSketchbookDidClick = async () => { protected browseSketchbookDidClick = async (): Promise<void> => {
const uri = await this.props.fileDialogService.showOpenDialog({ const uri = await this.props.fileDialogService.showOpenDialog({
title: nls.localize( title: nls.localize(
'arduino/preferences/newSketchbookLocation', 'arduino/preferences/newSketchbookLocation',
@ -483,7 +473,7 @@ export class SettingsComponent extends React.Component<
} }
}; };
protected editAdditionalUrlDidClick = async () => { protected editAdditionalUrlDidClick = async (): Promise<void> => {
const additionalUrls = await new AdditionalUrlsDialog( const additionalUrls = await new AdditionalUrlsDialog(
this.state.additionalUrls, this.state.additionalUrls,
this.props.windowService this.props.windowService
@ -495,7 +485,7 @@ export class SettingsComponent extends React.Component<
protected editorFontSizeDidChange = ( protected editorFontSizeDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
const { value } = event.target; const { value } = event.target;
if (value) { if (value) {
this.setState({ editorFontSize: parseInt(value, 10) }); this.setState({ editorFontSize: parseInt(value, 10) });
@ -504,7 +494,7 @@ export class SettingsComponent extends React.Component<
protected additionalUrlsDidChange = ( protected additionalUrlsDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
this.setState({ this.setState({
additionalUrls: event.target.value.split(',').map((url) => url.trim()), additionalUrls: event.target.value.split(',').map((url) => url.trim()),
}); });
@ -512,13 +502,13 @@ export class SettingsComponent extends React.Component<
protected autoScaleInterfaceDidChange = ( protected autoScaleInterfaceDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
this.setState({ autoScaleInterface: event.target.checked }); this.setState({ autoScaleInterface: event.target.checked });
}; };
protected interfaceScaleDidChange = ( protected interfaceScaleDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
const { value } = event.target; const { value } = event.target;
const percentage = parseInt(value, 10); const percentage = parseInt(value, 10);
if (isNaN(percentage)) { if (isNaN(percentage)) {
@ -532,31 +522,25 @@ export class SettingsComponent extends React.Component<
protected verifyAfterUploadDidChange = ( protected verifyAfterUploadDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
this.setState({ verifyAfterUpload: event.target.checked }); this.setState({ verifyAfterUpload: event.target.checked });
}; };
protected checkForUpdatesDidChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
this.setState({ checkForUpdates: event.target.checked });
};
protected sketchbookShowAllFilesDidChange = ( protected sketchbookShowAllFilesDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
this.setState({ sketchbookShowAllFiles: event.target.checked }); this.setState({ sketchbookShowAllFiles: event.target.checked });
}; };
protected autoSaveDidChange = ( protected autoSaveDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
this.setState({ autoSave: event.target.checked ? 'on' : 'off' }); this.setState({ autoSave: event.target.checked ? 'on' : 'off' });
}; };
protected quickSuggestionsOtherDidChange = ( protected quickSuggestionsOtherDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
// need to persist react events through lifecycle https://reactjs.org/docs/events.html#event-pooling // need to persist react events through lifecycle https://reactjs.org/docs/events.html#event-pooling
const newVal = event.target.checked ? true : false; const newVal = event.target.checked ? true : false;
@ -570,7 +554,9 @@ export class SettingsComponent extends React.Component<
}); });
}; };
protected themeDidChange = (event: React.ChangeEvent<HTMLSelectElement>) => { protected themeDidChange = (
event: React.ChangeEvent<HTMLSelectElement>
): void => {
const { selectedIndex } = event.target.options; const { selectedIndex } = event.target.options;
const theme = ThemeService.get().getThemes()[selectedIndex]; const theme = ThemeService.get().getThemes()[selectedIndex];
if (theme) { if (theme) {
@ -580,14 +566,14 @@ export class SettingsComponent extends React.Component<
protected languageDidChange = ( protected languageDidChange = (
event: React.ChangeEvent<HTMLSelectElement> event: React.ChangeEvent<HTMLSelectElement>
) => { ): void => {
const selectedLanguage = event.target.value; const selectedLanguage = event.target.value;
this.setState({ currentLanguage: selectedLanguage }); this.setState({ currentLanguage: selectedLanguage });
}; };
protected compilerWarningsDidChange = ( protected compilerWarningsDidChange = (
event: React.ChangeEvent<HTMLSelectElement> event: React.ChangeEvent<HTMLSelectElement>
) => { ): void => {
const { selectedIndex } = event.target.options; const { selectedIndex } = event.target.options;
const compilerWarnings = CompilerWarningLiterals[selectedIndex]; const compilerWarnings = CompilerWarningLiterals[selectedIndex];
if (compilerWarnings) { if (compilerWarnings) {
@ -597,26 +583,28 @@ export class SettingsComponent extends React.Component<
protected verboseOnCompileDidChange = ( protected verboseOnCompileDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
this.setState({ verboseOnCompile: event.target.checked }); this.setState({ verboseOnCompile: event.target.checked });
}; };
protected verboseOnUploadDidChange = ( protected verboseOnUploadDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
this.setState({ verboseOnUpload: event.target.checked }); this.setState({ verboseOnUpload: event.target.checked });
}; };
protected sketchpathDidChange = ( protected sketchpathDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
const sketchbookPath = event.target.value; const sketchbookPath = event.target.value;
if (sketchbookPath) { if (sketchbookPath) {
this.setState({ sketchbookPath }); this.setState({ sketchbookPath });
} }
}; };
protected noProxyDidChange = (event: React.ChangeEvent<HTMLInputElement>) => { protected noProxyDidChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
if (event.target.checked) { if (event.target.checked) {
this.setState({ network: 'none' }); this.setState({ network: 'none' });
} else { } else {
@ -626,7 +614,7 @@ export class SettingsComponent extends React.Component<
protected manualProxyDidChange = ( protected manualProxyDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
if (event.target.checked) { if (event.target.checked) {
this.setState({ network: Network.Default() }); this.setState({ network: Network.Default() });
} else { } else {
@ -636,7 +624,7 @@ export class SettingsComponent extends React.Component<
protected httpProtocolDidChange = ( protected httpProtocolDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
if (this.state.network !== 'none') { if (this.state.network !== 'none') {
const network = this.cloneProxySettings; const network = this.cloneProxySettings;
network.protocol = event.target.checked ? 'http' : 'socks'; network.protocol = event.target.checked ? 'http' : 'socks';
@ -646,7 +634,7 @@ export class SettingsComponent extends React.Component<
protected socksProtocolDidChange = ( protected socksProtocolDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
if (this.state.network !== 'none') { if (this.state.network !== 'none') {
const network = this.cloneProxySettings; const network = this.cloneProxySettings;
network.protocol = event.target.checked ? 'socks' : 'http'; network.protocol = event.target.checked ? 'socks' : 'http';
@ -656,7 +644,7 @@ export class SettingsComponent extends React.Component<
protected hostnameDidChange = ( protected hostnameDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
if (this.state.network !== 'none') { if (this.state.network !== 'none') {
const network = this.cloneProxySettings; const network = this.cloneProxySettings;
network.hostname = event.target.value; network.hostname = event.target.value;
@ -664,7 +652,9 @@ export class SettingsComponent extends React.Component<
} }
}; };
protected portDidChange = (event: React.ChangeEvent<HTMLInputElement>) => { protected portDidChange = (
event: React.ChangeEvent<HTMLInputElement>
): void => {
if (this.state.network !== 'none') { if (this.state.network !== 'none') {
const network = this.cloneProxySettings; const network = this.cloneProxySettings;
network.port = event.target.value; network.port = event.target.value;
@ -674,7 +664,7 @@ export class SettingsComponent extends React.Component<
protected usernameDidChange = ( protected usernameDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
if (this.state.network !== 'none') { if (this.state.network !== 'none') {
const network = this.cloneProxySettings; const network = this.cloneProxySettings;
network.username = event.target.value; network.username = event.target.value;
@ -684,7 +674,7 @@ export class SettingsComponent extends React.Component<
protected passwordDidChange = ( protected passwordDidChange = (
event: React.ChangeEvent<HTMLInputElement> event: React.ChangeEvent<HTMLInputElement>
) => { ): void => {
if (this.state.network !== 'none') { if (this.state.network !== 'none') {
const network = this.cloneProxySettings; const network = this.cloneProxySettings;
network.password = event.target.value; network.password = event.target.value;

View File

@ -18,24 +18,22 @@ import {
import { nls } from '@theia/core/lib/common'; import { nls } from '@theia/core/lib/common';
import { AsyncLocalizationProvider } from '@theia/core/lib/common/i18n/localization'; import { AsyncLocalizationProvider } from '@theia/core/lib/common/i18n/localization';
const EDITOR_SETTING = 'editor'; export const EDITOR_SETTING = 'editor';
const FONT_SIZE_SETTING = `${EDITOR_SETTING}.fontSize`; export const FONT_SIZE_SETTING = `${EDITOR_SETTING}.fontSize`;
const AUTO_SAVE_SETTING = `${EDITOR_SETTING}.autoSave`; export const AUTO_SAVE_SETTING = `${EDITOR_SETTING}.autoSave`;
const QUICK_SUGGESTIONS_SETTING = `${EDITOR_SETTING}.quickSuggestions`; export const QUICK_SUGGESTIONS_SETTING = `${EDITOR_SETTING}.quickSuggestions`;
const ARDUINO_SETTING = 'arduino'; export const ARDUINO_SETTING = 'arduino';
const WINDOW_SETTING = `${ARDUINO_SETTING}.window`; export const WINDOW_SETTING = `${ARDUINO_SETTING}.window`;
// const IDE_SETTING = `${ARDUINO_SETTING}.ide`; export const COMPILE_SETTING = `${ARDUINO_SETTING}.compile`;
const COMPILE_SETTING = `${ARDUINO_SETTING}.compile`; export const UPLOAD_SETTING = `${ARDUINO_SETTING}.upload`;
const UPLOAD_SETTING = `${ARDUINO_SETTING}.upload`; export const SKETCHBOOK_SETTING = `${ARDUINO_SETTING}.sketchbook`;
const SKETCHBOOK_SETTING = `${ARDUINO_SETTING}.sketchbook`; export const AUTO_SCALE_SETTING = `${WINDOW_SETTING}.autoScale`;
const AUTO_SCALE_SETTING = `${WINDOW_SETTING}.autoScale`; export const ZOOM_LEVEL_SETTING = `${WINDOW_SETTING}.zoomLevel`;
const ZOOM_LEVEL_SETTING = `${WINDOW_SETTING}.zoomLevel`; export const COMPILE_VERBOSE_SETTING = `${COMPILE_SETTING}.verbose`;
// const AUTO_UPDATE_SETTING = `${IDE_SETTING}.autoUpdate`; export const COMPILE_WARNINGS_SETTING = `${COMPILE_SETTING}.warnings`;
const COMPILE_VERBOSE_SETTING = `${COMPILE_SETTING}.verbose`; export const UPLOAD_VERBOSE_SETTING = `${UPLOAD_SETTING}.verbose`;
const COMPILE_WARNINGS_SETTING = `${COMPILE_SETTING}.warnings`; export const UPLOAD_VERIFY_SETTING = `${UPLOAD_SETTING}.verify`;
const UPLOAD_VERBOSE_SETTING = `${UPLOAD_SETTING}.verbose`; export const SHOW_ALL_FILES_SETTING = `${SKETCHBOOK_SETTING}.showAllFiles`;
const UPLOAD_VERIFY_SETTING = `${UPLOAD_SETTING}.verify`;
const SHOW_ALL_FILES_SETTING = `${SKETCHBOOK_SETTING}.showAllFiles`;
export interface Settings extends Index { export interface Settings extends Index {
editorFontSize: number; // `editor.fontSize` editorFontSize: number; // `editor.fontSize`
@ -48,7 +46,6 @@ export interface Settings extends Index {
autoScaleInterface: boolean; // `arduino.window.autoScale` autoScaleInterface: boolean; // `arduino.window.autoScale`
interfaceScale: number; // `arduino.window.zoomLevel` https://github.com/eclipse-theia/theia/issues/8751 interfaceScale: number; // `arduino.window.zoomLevel` https://github.com/eclipse-theia/theia/issues/8751
checkForUpdates?: boolean; // `arduino.ide.autoUpdate`
verboseOnCompile: boolean; // `arduino.compile.verbose` verboseOnCompile: boolean; // `arduino.compile.verbose`
compilerWarnings: CompilerWarnings; // `arduino.compile.warnings` compilerWarnings: CompilerWarnings; // `arduino.compile.warnings`
verboseOnUpload: boolean; // `arduino.upload.verbose` verboseOnUpload: boolean; // `arduino.upload.verbose`
@ -93,7 +90,6 @@ export class SettingsService {
@postConstruct() @postConstruct()
protected async init(): Promise<void> { protected async init(): Promise<void> {
await this.appStateService.reachedState('ready'); // Hack for https://github.com/eclipse-theia/theia/issues/8993
const settings = await this.loadSettings(); const settings = await this.loadSettings();
this._settings = deepClone(settings); this._settings = deepClone(settings);
this.ready.resolve(); this.ready.resolve();
@ -110,7 +106,6 @@ export class SettingsService {
quickSuggestions, quickSuggestions,
autoScaleInterface, autoScaleInterface,
interfaceScale, interfaceScale,
// checkForUpdates,
verboseOnCompile, verboseOnCompile,
compilerWarnings, compilerWarnings,
verboseOnUpload, verboseOnUpload,
@ -135,7 +130,6 @@ export class SettingsService {
}), }),
this.preferenceService.get<boolean>(AUTO_SCALE_SETTING, true), this.preferenceService.get<boolean>(AUTO_SCALE_SETTING, true),
this.preferenceService.get<number>(ZOOM_LEVEL_SETTING, 0), this.preferenceService.get<number>(ZOOM_LEVEL_SETTING, 0),
// this.preferenceService.get<string>(AUTO_UPDATE_SETTING, true),
this.preferenceService.get<boolean>(COMPILE_VERBOSE_SETTING, true), this.preferenceService.get<boolean>(COMPILE_VERBOSE_SETTING, true),
this.preferenceService.get<any>(COMPILE_WARNINGS_SETTING, 'None'), this.preferenceService.get<any>(COMPILE_WARNINGS_SETTING, 'None'),
this.preferenceService.get<boolean>(UPLOAD_VERBOSE_SETTING, true), this.preferenceService.get<boolean>(UPLOAD_VERBOSE_SETTING, true),
@ -154,7 +148,6 @@ export class SettingsService {
quickSuggestions, quickSuggestions,
autoScaleInterface, autoScaleInterface,
interfaceScale, interfaceScale,
// checkForUpdates,
verboseOnCompile, verboseOnCompile,
compilerWarnings, compilerWarnings,
verboseOnUpload, verboseOnUpload,
@ -234,7 +227,6 @@ export class SettingsService {
quickSuggestions, quickSuggestions,
autoScaleInterface, autoScaleInterface,
interfaceScale, interfaceScale,
// checkForUpdates,
verboseOnCompile, verboseOnCompile,
compilerWarnings, compilerWarnings,
verboseOnUpload, verboseOnUpload,
@ -284,7 +276,6 @@ export class SettingsService {
interfaceScale, interfaceScale,
PreferenceScope.User PreferenceScope.User
), ),
// this.preferenceService.set(AUTO_UPDATE_SETTING, checkForUpdates, PreferenceScope.User),
this.preferenceService.set( this.preferenceService.set(
COMPILE_VERBOSE_SETTING, COMPILE_VERBOSE_SETTING,
verboseOnCompile, verboseOnCompile,

View File

@ -0,0 +1,40 @@
import { Emitter } from '@theia/core';
import { injectable } from '@theia/core/shared/inversify';
import { UpdateInfo, ProgressInfo } from 'electron-updater';
import { IDEUpdaterClient } from '../../common/protocol/ide-updater';
@injectable()
export class IDEUpdaterClientImpl implements IDEUpdaterClient {
protected readonly onErrorEmitter = new Emitter<Error>();
protected readonly onCheckingForUpdateEmitter = new Emitter<void>();
protected readonly onUpdateAvailableEmitter = new Emitter<UpdateInfo>();
protected readonly onUpdateNotAvailableEmitter = new Emitter<UpdateInfo>();
protected readonly onDownloadProgressEmitter = new Emitter<ProgressInfo>();
protected readonly onDownloadFinishedEmitter = new Emitter<UpdateInfo>();
readonly onError = this.onErrorEmitter.event;
readonly onCheckingForUpdate = this.onCheckingForUpdateEmitter.event;
readonly onUpdateAvailable = this.onUpdateAvailableEmitter.event;
readonly onUpdateNotAvailable = this.onUpdateNotAvailableEmitter.event;
readonly onDownloadProgressChanged = this.onDownloadProgressEmitter.event;
readonly onDownloadFinished = this.onDownloadFinishedEmitter.event;
notifyError(message: Error): void {
this.onErrorEmitter.fire(message);
}
notifyCheckingForUpdate(message: void): void {
this.onCheckingForUpdateEmitter.fire(message);
}
notifyUpdateAvailable(message: UpdateInfo): void {
this.onUpdateAvailableEmitter.fire(message);
}
notifyUpdateNotAvailable(message: UpdateInfo): void {
this.onUpdateNotAvailableEmitter.fire(message);
}
notifyDownloadProgressChanged(message: ProgressInfo): void {
this.onDownloadProgressEmitter.fire(message);
}
notifyDownloadFinished(message: UpdateInfo): void {
this.onDownloadFinishedEmitter.fire(message);
}
}

View File

@ -0,0 +1,71 @@
import {
Command,
CommandContribution,
CommandRegistry,
MessageService,
} from '@theia/core';
import { injectable, inject } from 'inversify';
import { IDEUpdater, UpdateInfo } from '../../common/protocol/ide-updater';
@injectable()
export class IDEUpdaterCommands implements CommandContribution {
constructor(
@inject(IDEUpdater)
private readonly updater: IDEUpdater,
@inject(MessageService)
protected readonly messageService: MessageService
) {}
registerCommands(registry: CommandRegistry): void {
registry.registerCommand(IDEUpdaterCommands.CHECK_FOR_UPDATES, {
execute: this.checkForUpdates.bind(this),
});
registry.registerCommand(IDEUpdaterCommands.DOWNLOAD_UPDATE, {
execute: this.downloadUpdate.bind(this),
});
registry.registerCommand(IDEUpdaterCommands.STOP_DOWNLOAD, {
execute: this.stopDownload.bind(this),
});
registry.registerCommand(IDEUpdaterCommands.INSTALL_UPDATE, {
execute: this.quitAndInstall.bind(this),
});
}
async checkForUpdates(): Promise<UpdateInfo | void> {
return await this.updater.checkForUpdates();
}
async downloadUpdate(): Promise<void> {
await this.updater.downloadUpdate();
}
async stopDownload(): Promise<void> {
await this.updater.stopDownload();
}
quitAndInstall(): void {
this.updater.quitAndInstall();
}
}
export namespace IDEUpdaterCommands {
export const CHECK_FOR_UPDATES: Command = {
id: 'arduino-ide-check-for-updates',
category: 'Arduino',
label: 'Check for Arduino IDE updates',
};
export const DOWNLOAD_UPDATE: Command = {
id: 'arduino-ide-download-update',
category: 'Arduino',
label: 'Download Arduino IDE updates',
};
export const STOP_DOWNLOAD: Command = {
id: 'arduino-ide-stop-download',
category: 'Arduino',
label: 'Stop download of Arduino IDE updates',
};
export const INSTALL_UPDATE: Command = {
id: 'arduino-ide-install-update',
category: 'Arduino',
label: 'Install Arduino IDE updates',
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,67 @@
.ide-updater-dialog {
width: 546px;
}
.ide-updater-dialog .bold {
font-weight: bold;
}
.ide-updater-dialog--pre-download {
display: flex;
}
.ide-updater-dialog--logo-container {
margin-right: 28px;
}
.ide-updater-dialog--logo {
background: url('./ide-logo.png') round;
width: 52px;
height: 52px;
}
.dialogContent.ide-updater-dialog
.ide-updater-dialog--content
.ide-updater-dialog--new-version-text.dialogSection {
margin-top: 0;
}
.ide-updater-dialog .changelog-container {
background: white;
border: 1px solid #dae3e3;
border-radius: 2px;
font-size: 12px;
height: 180px;
overflow: auto;
padding: 0 12px;
cursor: text;
}
.ide-updater-dialog .changelog-container a {
color: #018184;
}
.ide-updater-dialog .changelog-container a:hover {
text-decoration: underline;
cursor: pointer;
}
.ide-updater-dialog .changelog-container code {
background: #ecf1f1;
border-radius: 2px;
padding: 0 2px;
}
.ide-updater-dialog .changelog-container a code {
color: #018184;
}
.ide-updater-dialog .buttons-container {
display: flex;
justify-content: flex-end;
margin-top: 28px;
}
.ide-updater-dialog .buttons-container .push {
margin-right: auto;
}

View File

@ -9,6 +9,7 @@
@import './editor.css'; @import './editor.css';
@import './settings-dialog.css'; @import './settings-dialog.css';
@import './firmware-uploader-dialog.css'; @import './firmware-uploader-dialog.css';
@import './ide-updater-dialog.css';
@import './certificate-uploader-dialog.css'; @import './certificate-uploader-dialog.css';
@import './user-fields-dialog.css'; @import './user-fields-dialog.css';
@import './debug.css'; @import './debug.css';
@ -16,6 +17,7 @@
@import './cloud-sketchbook.css'; @import './cloud-sketchbook.css';
@import './fonts.css'; @import './fonts.css';
@import './custom-codicon.css'; @import './custom-codicon.css';
@import './progress-bar.css';
.theia-input.warning:focus { .theia-input.warning:focus {
outline-width: 1px; outline-width: 1px;

View File

@ -0,0 +1,32 @@
.progress-bar {
margin-top: 20px;
}
.progress-bar--outer {
background: #e5e5e5;
border-radius: 11px;
height: 6px;
position: relative;
overflow: hidden;
}
.progress-bar--inner {
transition: width 1s;
height: 100%;
background: #008184;
border-radius: 11px;
}
.progress-bar--percentage {
align-items: flex-end;
display: flex;
height: 40px;
justify-content: center;
margin-top: 10px;
width: 100%;
}
.progress-bar--percentage-text {
font-size: 14px;
line-height: 24px;
}

View File

@ -0,0 +1,71 @@
import { JsonRpcServer } from '@theia/core/lib/common/messaging/proxy-factory';
import { Event } from '@theia/core/lib/common/event';
import { UpdateChannel } from '../../browser/arduino-preferences';
export interface ProgressInfo {
total: number;
delta: number;
transferred: number;
percent: number;
bytesPerSecond: number;
}
export interface ReleaseNoteInfo {
readonly version: string;
readonly note: string | null;
}
export interface BlockMapDataHolder {
size?: number;
blockMapSize?: number;
readonly sha512: string;
readonly isAdminRightsRequired?: boolean;
}
export interface UpdateFileInfo extends BlockMapDataHolder {
url: string;
}
export type UpdateInfo = {
readonly version: string;
readonly files: Array<UpdateFileInfo>;
releaseName?: string | null;
releaseNotes?: string | Array<ReleaseNoteInfo> | null;
releaseDate: string;
readonly stagingPercentage?: number;
};
export interface ProgressInfo {
total: number;
delta: number;
transferred: number;
percent: number;
bytesPerSecond: number;
}
export const IDEUpdaterPath = '/services/ide-updater';
export const IDEUpdater = Symbol('IDEUpdater');
export interface IDEUpdater extends JsonRpcServer<IDEUpdaterClient> {
init(channel: UpdateChannel): void;
checkForUpdates(): Promise<UpdateInfo | void>;
downloadUpdate(): Promise<void>;
quitAndInstall(): void;
stopDownload(): void;
disconnectClient(client: IDEUpdaterClient): void;
}
export const IDEUpdaterClient = Symbol('IDEUpdaterClient');
export interface IDEUpdaterClient {
onError: Event<Error>;
onCheckingForUpdate: Event<void>;
onUpdateAvailable: Event<UpdateInfo>;
onUpdateNotAvailable: Event<UpdateInfo>;
onDownloadProgressChanged: Event<ProgressInfo>;
onDownloadFinished: Event<UpdateInfo>;
notifyError(message: Error): void;
notifyCheckingForUpdate(message: void): void;
notifyUpdateAvailable(message: UpdateInfo): void;
notifyUpdateNotAvailable(message: UpdateInfo): void;
notifyDownloadProgressChanged(message: ProgressInfo): void;
notifyDownloadFinished(message: UpdateInfo): void;
}

View File

@ -2,7 +2,10 @@ import { ContainerModule } from 'inversify';
import { JsonRpcConnectionHandler } from '@theia/core/lib/common/messaging/proxy-factory'; import { JsonRpcConnectionHandler } from '@theia/core/lib/common/messaging/proxy-factory';
import { ElectronConnectionHandler } from '@theia/core/lib/electron-common/messaging/electron-connection-handler'; import { ElectronConnectionHandler } from '@theia/core/lib/electron-common/messaging/electron-connection-handler';
import { ElectronMainWindowService } from '@theia/core/lib/electron-common/electron-main-window-service'; import { ElectronMainWindowService } from '@theia/core/lib/electron-common/electron-main-window-service';
import { ElectronMainApplication as TheiaElectronMainApplication } from '@theia/core/lib/electron-main/electron-main-application'; import {
ElectronMainApplication as TheiaElectronMainApplication,
ElectronMainApplicationContribution,
} from '@theia/core/lib/electron-main/electron-main-application';
import { import {
SplashService, SplashService,
splashServicePath, splashServicePath,
@ -10,6 +13,12 @@ import {
import { SplashServiceImpl } from './splash/splash-service-impl'; import { SplashServiceImpl } from './splash/splash-service-impl';
import { ElectronMainApplication } from './theia/electron-main-application'; import { ElectronMainApplication } from './theia/electron-main-application';
import { ElectronMainWindowServiceImpl } from './theia/electron-main-window-service'; import { ElectronMainWindowServiceImpl } from './theia/electron-main-window-service';
import {
IDEUpdater,
IDEUpdaterClient,
IDEUpdaterPath,
} from '../common/protocol/ide-updater';
import { IDEUpdaterImpl } from '../node/ide-updater/ide-updater-impl';
export default new ContainerModule((bind, unbind, isBound, rebind) => { export default new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ElectronMainApplication).toSelf().inSingletonScope(); bind(ElectronMainApplication).toSelf().inSingletonScope();
@ -28,4 +37,23 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
) )
) )
.inSingletonScope(); .inSingletonScope();
// IDE updater bindings
bind(IDEUpdaterImpl).toSelf().inSingletonScope();
bind(IDEUpdater).toService(IDEUpdaterImpl);
bind(ElectronMainApplicationContribution).toService(IDEUpdater);
bind(ElectronConnectionHandler)
.toDynamicValue(
(context) =>
new JsonRpcConnectionHandler<IDEUpdaterClient>(
IDEUpdaterPath,
(client) => {
const server = context.container.get<IDEUpdater>(IDEUpdater);
server.setClient(client);
client.onDidCloseConnection(() => server.disconnectClient(client));
return server;
}
)
)
.inSingletonScope();
}); });

View File

@ -70,11 +70,11 @@ export abstract class GrpcClientProvider<C> {
protected abstract close(client: C): void; protected abstract close(client: C): void;
protected get channelOptions(): Record<string, unknown> { protected get channelOptions(): Record<string, unknown> {
const pjson = require('../../package.json') || { "version": "0.0.0" } const pjson = require('../../package.json') || { version: '0.0.0' };
return { return {
'grpc.max_send_message_length': 512 * 1024 * 1024, 'grpc.max_send_message_length': 512 * 1024 * 1024,
'grpc.max_receive_message_length': 512 * 1024 * 1024, 'grpc.max_receive_message_length': 512 * 1024 * 1024,
'grpc.primary_user_agent': `arduino-ide/${pjson.version}` 'grpc.primary_user_agent': `arduino-ide/${pjson.version}`,
}; };
} }
} }

View File

@ -0,0 +1,128 @@
import { injectable } from '@theia/core/shared/inversify';
import { UpdateInfo, CancellationToken, autoUpdater } from 'electron-updater';
import fetch, { Response } from 'node-fetch';
import { UpdateChannel } from '../../browser/arduino-preferences';
import {
IDEUpdater,
IDEUpdaterClient,
} from '../../common/protocol/ide-updater';
const CHANGELOG_BASE_URL = 'https://downloads.arduino.cc/arduino-ide/changelog';
const IDE_DOWNLOAD_BASE_URL = 'https://downloads.arduino.cc/arduino-ide';
@injectable()
export class IDEUpdaterImpl implements IDEUpdater {
private updater = autoUpdater;
private cancellationToken?: CancellationToken;
protected theiaFEClient?: IDEUpdaterClient;
protected clients: Array<IDEUpdaterClient> = [];
init(channel: UpdateChannel) {
this.updater.channel = channel;
this.updater.setFeedURL({
provider: 'generic',
url: `${IDE_DOWNLOAD_BASE_URL}/${
channel === UpdateChannel.Nightly ? 'nightly' : ''
}`,
channel,
});
this.updater.on('checking-for-update', (e) =>
this.clients.forEach((c) => c.notifyCheckingForUpdate(e))
);
this.updater.on('update-available', (e) =>
this.clients.forEach((c) => c.notifyUpdateAvailable(e))
);
this.updater.on('update-not-available', (e) =>
this.clients.forEach((c) => c.notifyUpdateNotAvailable(e))
);
this.updater.on('download-progress', (e) =>
this.clients.forEach((c) => c.notifyDownloadProgressChanged(e))
);
this.updater.on('update-downloaded', (e) =>
this.clients.forEach((c) => c.notifyDownloadFinished(e))
);
this.updater.on('error', (e) =>
this.clients.forEach((c) => c.notifyError(e))
);
}
setClient(client: IDEUpdaterClient | undefined): void {
if (client) this.clients.push(client);
}
async checkForUpdates(): Promise<UpdateInfo | void> {
const {
updateInfo,
cancellationToken,
} = await this.updater.checkForUpdates();
this.cancellationToken = cancellationToken;
if (
this.updater.currentVersion.compare(updateInfo.version) === -1 ||
true
) {
/*
'latest.txt' points to the latest changelog that has been generated by the CI,
so we need to make a first GET request to get the filename of the changelog
and a second GET to the actual changelog file
*/
try {
let response: Response | null = await fetch(
`${CHANGELOG_BASE_URL}/latest.txt`
);
const latestChangelogFileName = response.ok
? await response.text()
: null;
response = latestChangelogFileName
? await fetch(`${CHANGELOG_BASE_URL}/${latestChangelogFileName}`)
: null;
const changelog = response?.ok ? await response?.text() : null;
// We only want to see the release notes of newer versions
const currentVersionIndex = changelog?.indexOf(
`\r\n\r\n---\r\n\r\n## ${this.updater.currentVersion}\r\n\r\n`
);
const newChangelog =
currentVersionIndex && currentVersionIndex > 0
? changelog?.slice(0, currentVersionIndex)
: changelog;
updateInfo.releaseNotes = newChangelog;
} catch {
/*
if the request for the changelog fails, we'll just avoid to show it
to the user, but we will still show the update info
*/
}
return updateInfo;
}
}
async downloadUpdate(): Promise<void> {
try {
await this.updater.downloadUpdate(this.cancellationToken);
} catch (e) {
if (e.message === 'cancelled') return;
throw e;
}
}
stopDownload(): void {
this.cancellationToken?.cancel();
}
quitAndInstall(): void {
this.updater.quitAndInstall();
}
disconnectClient(client: IDEUpdaterClient): void {
const index = this.clients.indexOf(client);
if (index !== -1) {
this.clients.splice(index, 1);
}
}
dispose(): void {
this.clients.forEach(this.disconnectClient.bind(this));
}
}

View File

@ -54,6 +54,8 @@
"build": { "build": {
"productName": "Arduino IDE", "productName": "Arduino IDE",
"asar": false, "asar": false,
"detectUpdateChannel": false,
"generateUpdatesFilesForAllChannels": true,
"npmRebuild": false, "npmRebuild": false,
"directories": { "directories": {
"buildResources": "resources" "buildResources": "resources"
@ -91,13 +93,17 @@
"entitlements": "resources/entitlements.mac.plist", "entitlements": "resources/entitlements.mac.plist",
"entitlementsInherit": "resources/entitlements.mac.plist", "entitlementsInherit": "resources/entitlements.mac.plist",
"target": [ "target": [
"dmg" "dmg",
"zip"
] ]
}, },
"linux": { "linux": {
"target": [ "target": [
{ {
"target": "zip" "target": "zip"
},
{
"target": "AppImage"
} }
], ],
"category": "Development", "category": "Development",

View File

@ -13,7 +13,7 @@ function artifactName() {
if (isRelease) { if (isRelease) {
return getVersion(); return getVersion();
} else if (isNightly) { } else if (isNightly) {
return `nightly-${timestamp()}` return `nightly-${timestamp()}`;
} else { } else {
return getVersion(); return getVersion();
} }
@ -45,7 +45,8 @@ function artifactName() {
} }
} }
} }
default: throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`); default:
throw new Error(`Unsupported platform, arch: ${platform}, ${arch}`);
} }
} }
@ -60,15 +61,28 @@ function electronPlatform() {
case 'linux': { case 'linux': {
return 'linux'; return 'linux';
} }
default: throw new Error(`Unsupported platform: ${process.platform}.`); default:
throw new Error(`Unsupported platform: ${process.platform}.`);
} }
} }
function getVersion() { function getVersion() {
const repositoryRootPath = git('rev-parse --show-toplevel'); const repositoryRootPath = git('rev-parse --show-toplevel');
let version = JSON.parse(fs.readFileSync(path.join(repositoryRootPath, 'package.json'), { encoding: 'utf8' })).version; let version = JSON.parse(
fs.readFileSync(path.join(repositoryRootPath, 'package.json'), {
encoding: 'utf8',
})
).version;
if (!semver.valid(version)) { if (!semver.valid(version)) {
throw new Error(`Could not read version from root package.json. Version was: '${version}'.`); throw new Error(
`Could not read version from root package.json. Version was: '${version}'.`
);
}
if (!isRelease) {
if (isNightly) {
version = `${version}-nightly.${timestamp()}`;
} else {
version = `${version}-snapshot.${currentCommitish()}`;
} }
if (!isRelease) { if (!isRelease) {
if (isNightly) { if (isNightly) {
@ -80,9 +94,21 @@ function getVersion() {
throw new Error(`Invalid patched version: '${version}'.`); throw new Error(`Invalid patched version: '${version}'.`);
} }
} }
}
return version; return version;
} }
function getChannel() {
if (isRelease) {
return 'stable';
}
if (isNightly) {
return 'nightly';
}
return 'none';
}
function timestamp() { function timestamp() {
return dateFormat(new Date(), 'yyyymmdd'); return dateFormat(new Date(), 'yyyymmdd');
} }
@ -101,20 +127,30 @@ function generateTemplate(buildDate) {
const version = getVersion(); const version = getVersion();
const productName = 'Arduino IDE'; const productName = 'Arduino IDE';
const name = 'arduino-ide'; const name = 'arduino-ide';
const updateChannel = getChannel();
let customizations = { let customizations = {
name, name,
description: productName, description: productName,
version, version,
theia: {
frontend: {
config: {
'arduino.ide.updateChannel': updateChannel,
},
},
},
build: { build: {
productName, productName,
appId: 'arduino.ProIDE', appId: 'cc.arduino.IDE2',
[electronPlatform()]: { [electronPlatform()]: {
artifactName: artifactName() artifactName: artifactName(),
} },
} },
}; };
if (buildDate) { if (buildDate) {
customizations = merge(customizations, { theia: { frontend: { config: { buildDate } } } }); customizations = merge(customizations, {
theia: { frontend: { config: { buildDate } } },
});
} }
const template = require('../build/template-package.json'); const template = require('../build/template-package.json');
return merge(template, customizations); return merge(template, customizations);

View File

@ -13,7 +13,7 @@
const template = require('./config').generateTemplate(new Date().toISOString()); const template = require('./config').generateTemplate(new Date().toISOString());
const utils = require('./utils'); const utils = require('./utils');
const merge = require('deepmerge'); const merge = require('deepmerge');
const { isRelease, isElectronPublish } = utils; const { isRelease, isElectronPublish, getChannelFile } = utils;
const { version } = template; const { version } = template;
const { productName } = template.build; const { productName } = template.build;
@ -277,6 +277,13 @@ ${fs.readFileSync(path('..', 'build', 'package.json')).toString()}
const targetFolder = path('..', 'build', 'dist', 'build-artifacts'); const targetFolder = path('..', 'build', 'dist', 'build-artifacts');
mkdir('-p', targetFolder); mkdir('-p', targetFolder);
const filesToCopy = []; const filesToCopy = [];
const channelFile = getChannelFile(platform);
// Channel file might be an empty string if we're not building a
// nightly or a full release. This can happen when building a package
// locally or a tester build when creating a new PR on GH.
if (channelFile) {
filesToCopy.push(channelFile)
}
switch (platform) { switch (platform) {
case 'linux': { case 'linux': {
filesToCopy.push(...glob.sync('**/arduino-ide*.{zip,AppImage}', { cwd }).map(p => join(cwd, p))); filesToCopy.push(...glob.sync('**/arduino-ide*.{zip,AppImage}', { cwd }).map(p => join(cwd, p)));

View File

@ -12,35 +12,42 @@ const fromFile = require('file-type').fromFile;
* Resolves to an array of `npm` package names that are declared in the `package.json` but **not** used by the project. * Resolves to an array of `npm` package names that are declared in the `package.json` but **not** used by the project.
*/ */
function collectUnusedDependencies(pathToProject = process.cwd()) { function collectUnusedDependencies(pathToProject = process.cwd()) {
const p = path.isAbsolute(pathToProject) ? pathToProject : path.resolve(process.cwd(), pathToProject); const p = path.isAbsolute(pathToProject)
? pathToProject
: path.resolve(process.cwd(), pathToProject);
console.log(`⏱️ >>> Collecting unused backend dependencies for ${p}...`); console.log(`⏱️ >>> Collecting unused backend dependencies for ${p}...`);
return new Promise(resolve => { return new Promise((resolve) => {
depcheck(p, { depcheck(
ignoreDirs: [ p,
'frontend' {
], ignoreDirs: ['frontend'],
parsers: { parsers: {
'*.js': depcheck.parser.es6, '*.js': depcheck.parser.es6,
'*.jsx': depcheck.parser.jsx '*.jsx': depcheck.parser.jsx,
}, },
detectors: [ detectors: [
depcheck.detector.requireCallExpression, depcheck.detector.requireCallExpression,
depcheck.detector.importDeclaration depcheck.detector.importDeclaration,
], ],
specials: [ specials: [depcheck.special.eslint, depcheck.special.webpack],
depcheck.special.eslint, },
depcheck.special.webpack (unused) => {
] const { dependencies } = unused;
}, unused => {
const { dependencies } = unused
if (dependencies && dependencies.length > 0) { if (dependencies && dependencies.length > 0) {
console.log(`👌 <<< The following unused dependencies have been found: ${JSON.stringify(dependencies, null, 2)}`); console.log(
`👌 <<< The following unused dependencies have been found: ${JSON.stringify(
dependencies,
null,
2
)}`
);
} else { } else {
console.log('👌 <<< No unused dependencies have been found.'); console.log('👌 <<< No unused dependencies have been found.');
} }
resolve(dependencies); resolve(dependencies);
}
);
}); });
})
} }
/** /**
@ -51,7 +58,7 @@ function collectUnusedDependencies(pathToProject = process.cwd()) {
*/ */
function adjustArchiveStructure(pathToZip, targetFolderName, noCleanup) { function adjustArchiveStructure(pathToZip, targetFolderName, noCleanup) {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
if (!await isZip(pathToZip)) { if (!(await isZip(pathToZip))) {
reject(new Error(`Expected a ZIP file.`)); reject(new Error(`Expected a ZIP file.`));
return; return;
} }
@ -67,10 +74,16 @@ function adjustArchiveStructure(pathToZip, targetFolderName, noCleanup) {
const root = basename(pathToZip); const root = basename(pathToZip);
const resources = await list(pathToZip); const resources = await list(pathToZip);
const hasBaseFolder = resources.find(name => name === root); const hasBaseFolder = resources.find((name) => name === root);
if (hasBaseFolder) { if (hasBaseFolder) {
if (resources.filter(name => name.indexOf(path.sep) === -1).length > 1) { if (
console.warn(`${pathToZip} ZIP has the desired root folder ${root}, however the ZIP contains other entries too: ${JSON.stringify(resources)}`); resources.filter((name) => name.indexOf(path.sep) === -1).length > 1
) {
console.warn(
`${pathToZip} ZIP has the desired root folder ${root}, however the ZIP contains other entries too: ${JSON.stringify(
resources
)}`
);
} }
console.log(`👌 <<< The ZIP already has the desired ${root} folder.`); console.log(`👌 <<< The ZIP already has the desired ${root} folder.`);
resolve(pathToZip); resolve(pathToZip);
@ -84,7 +97,11 @@ function adjustArchiveStructure(pathToZip, targetFolderName, noCleanup) {
await unpack(pathToZip, unzipOut); await unpack(pathToZip, unzipOut);
const adjustedZip = path.join(targetFolderName, path.basename(pathToZip)); const adjustedZip = path.join(targetFolderName, path.basename(pathToZip));
await pack(unzipOut, adjustedZip); await pack(unzipOut, adjustedZip);
console.log(`👌 <<< Adjusted the ZIP structure. Moved the modified ${basename(pathToZip)} to the ${targetFolderName} folder.`); console.log(
`👌 <<< Adjusted the ZIP structure. Moved the modified ${basename(
pathToZip
)} to the ${targetFolderName} folder.`
);
resolve(adjustedZip); resolve(adjustedZip);
} finally { } finally {
if (!noCleanup) { if (!noCleanup) {
@ -105,25 +122,25 @@ function basename(pathToFile) {
function unpack(what, where) { function unpack(what, where) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
zip.unpack(what, where, error => { zip.unpack(what, where, (error) => {
if (error) { if (error) {
reject(error); reject(error);
return; return;
} }
resolve(); resolve();
}) });
}); });
} }
function pack(what, where) { function pack(what, where) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
zip.pack(what, where, error => { zip.pack(what, where, (error) => {
if (error) { if (error) {
reject(error); reject(error);
return; return;
} }
resolve(); resolve();
}) });
}); });
} }
@ -135,7 +152,7 @@ function list(what) {
return; return;
} }
resolve(result.map(({ name }) => name)); resolve(result.map(({ name }) => name));
}) });
}); });
} }
@ -158,7 +175,9 @@ function git(command) {
if (error) { if (error) {
throw new Error(error); throw new Error(error);
} }
const { stderr, stdout } = shell.exec(`"${gitPath}" ${command}`, { silent: true }); const { stderr, stdout } = shell.exec(`"${gitPath}" ${command}`, {
silent: true,
});
if (stderr) { if (stderr) {
throw new Error(stderr.toString().trim()); throw new Error(stderr.toString().trim());
} }
@ -168,4 +187,44 @@ function git(command) {
} }
} }
module.exports = { collectUnusedDependencies, adjustArchiveStructure, isZip, unpack, isNightly, isRelease, isElectronPublish, git }; // getChannelFile returns the name of the channel file to be released
// together with the IDE file.
// The channel file depends on the platform and whether we're creating
// a nightly build or a full release.
// In all other cases, like when building a tester build for a PR,
// an empty string is returned since we don't need a channel file.
// The channel files are necessary for updates check with electron-updater
// to work correctly.
// For more information: https://www.electron.build/auto-update
function getChannelFile(platform) {
let currentChannel = '';
if (isNightly) {
currentChannel = 'nightly';
} else if (isRelease) {
currentChannel = 'stable';
} else {
// We're not creating a nightly build nor releasing
// a new version, no need for a channel file.
return '';
}
return (
currentChannel +
{
linux: '-linux.yml',
win32: '.yml',
darwin: '-mac.yml',
}[platform]
);
}
module.exports = {
collectUnusedDependencies,
adjustArchiveStructure,
isZip,
unpack,
isNightly,
isRelease,
isElectronPublish,
git,
getChannelFile,
};

View File

@ -31,7 +31,7 @@
"upload.verbose": "True for verbose upload output. False by default.", "upload.verbose": "True for verbose upload output. False by default.",
"window.autoScale": "True if the user interface automatically scales with the font size.", "window.autoScale": "True if the user interface automatically scales with the font size.",
"window.zoomLevel": "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity.", "window.zoomLevel": "Adjust the zoom level of the window. The original size is 0 and each increment above (e.g. 1) or below (e.g. -1) represents zooming 20% larger or smaller. You can also enter decimals to adjust the zoom level with a finer granularity.",
"ide.autoUpdate": "True to enable automatic update checks. The IDE will check for updates automatically and periodically.", "ide.updateChannel": "Release channel to get updated from. 'stable' is the stable release, 'nightly' is the latest development build.",
"board.certificates": "List of certificates that can be uploaded to boards", "board.certificates": "List of certificates that can be uploaded to boards",
"sketchbook.showAllFiles": "True to show all sketch files inside the sketch. It is false by default.", "sketchbook.showAllFiles": "True to show all sketch files inside the sketch. It is false by default.",
"cloud.enabled": "True if the sketch sync functions are enabled. Defaults to true.", "cloud.enabled": "True if the sketch sync functions are enabled. Defaults to true.",
@ -55,7 +55,6 @@
"compile": "compile", "compile": "compile",
"upload": "upload", "upload": "upload",
"verifyAfterUpload": "Verify code after upload", "verifyAfterUpload": "Verify code after upload",
"checkForUpdates": "Check for updates on startup",
"editorQuickSuggestions": "Editor Quick Suggestions", "editorQuickSuggestions": "Editor Quick Suggestions",
"additionalManagerURLs": "Additional Boards Manager URLs", "additionalManagerURLs": "Additional Boards Manager URLs",
"noProxy": "No proxy", "noProxy": "No proxy",
@ -256,6 +255,20 @@
"dialog": { "dialog": {
"dontAskAgain": "Don't ask again" "dontAskAgain": "Don't ask again"
}, },
"ide-updater": {
"notNowButton": "Not now",
"versionDownloaded": "Arduino IDE {0} has been downloaded.",
"closeToInstallNotice": "Close the software and install the update on your machine.",
"closeAndInstallButton": "Close and Install",
"downloadingNotice": "Downloading the latest version of the Arduino IDE.",
"updateAvailable": "Update Available",
"newVersionAvailable": "A new version of Arduino IDE ({0}) is available for download.",
"skipVersionButton": "Skip Version",
"downloadButton": "Download"
},
"updater": {
"ideUpdaterDialog": "Software Update"
},
"userFields": { "userFields": {
"cancel": "Cancel", "cancel": "Cancel",
"upload": "Upload" "upload": "Upload"

598
yarn.lock
View File

@ -2912,6 +2912,13 @@
resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc" resolved "https://registry.yarnpkg.com/@types/dateformat/-/dateformat-3.0.1.tgz#98d747a2e5e9a56070c6bf14e27bff56204e34cc"
integrity sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g== integrity sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g==
"@types/debug@^4.0.0":
version "4.1.7"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82"
integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==
dependencies:
"@types/ms" "*"
"@types/deepmerge@^2.2.0": "@types/deepmerge@^2.2.0":
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/@types/deepmerge/-/deepmerge-2.2.0.tgz#6f63896c217f3164782f52d858d9f3a927139f64" resolved "https://registry.yarnpkg.com/@types/deepmerge/-/deepmerge-2.2.0.tgz#6f63896c217f3164782f52d858d9f3a927139f64"
@ -3015,6 +3022,13 @@
resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.7.4.tgz#1621c50ceaf5aefa699851da8e0ea606a2943a39" resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.7.4.tgz#1621c50ceaf5aefa699851da8e0ea606a2943a39"
integrity sha512-6PjMFKl13cgB4kRdYtvyjKl8VVa0PXS2IdVxHhQ8GEKbxBkyJtSbaIeK1eZGjDKN7dvUh4vkOvU9FMwYNv4GQQ== integrity sha512-6PjMFKl13cgB4kRdYtvyjKl8VVa0PXS2IdVxHhQ8GEKbxBkyJtSbaIeK1eZGjDKN7dvUh4vkOvU9FMwYNv4GQQ==
"@types/hast@^2.0.0":
version "2.3.4"
resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc"
integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==
dependencies:
"@types/unist" "*"
"@types/js-yaml@^3.12.2": "@types/js-yaml@^3.12.2":
version "3.12.6" version "3.12.6"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.6.tgz#7f10c926aa41e189a2755c4c7fcf8e4573bd7ac1" resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.6.tgz#7f10c926aa41e189a2755c4c7fcf8e4573bd7ac1"
@ -3091,7 +3105,14 @@
"@types/linkify-it" "*" "@types/linkify-it" "*"
"@types/mdurl" "*" "@types/mdurl" "*"
"@types/mdurl@*": "@types/mdast@^3.0.0":
version "3.0.10"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af"
integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==
dependencies:
"@types/unist" "*"
"@types/mdurl@*", "@types/mdurl@^1.0.0":
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==
@ -3140,6 +3161,11 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea"
integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==
"@types/ms@*":
version "0.7.31"
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
"@types/multer@^1.4.7": "@types/multer@^1.4.7":
version "1.4.7" version "1.4.7"
resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e" resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.7.tgz#89cf03547c28c7bbcc726f029e2a76a7232cc79e"
@ -3337,7 +3363,7 @@
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
"@types/semver@^7.3.8": "@types/semver@^7.3.6", "@types/semver@^7.3.8":
version "7.3.9" version "7.3.9"
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc"
integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ== integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==
@ -3410,6 +3436,11 @@
resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.0.tgz#aee6e868fcef74f2b8c71614b6df81a601a42f17" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.0.tgz#aee6e868fcef74f2b8c71614b6df81a601a42f17"
integrity sha512-I8MnZqNXsOLHsU111oHbn3khtvKMi5Bn4qVFsIWSJcCP1KKDiXX5AEw8UPk0nSopeC+Hvxt6yAy1/a5PailFqg== integrity sha512-I8MnZqNXsOLHsU111oHbn3khtvKMi5Bn4qVFsIWSJcCP1KKDiXX5AEw8UPk0nSopeC+Hvxt6yAy1/a5PailFqg==
"@types/unist@*", "@types/unist@^2.0.0":
version "2.0.6"
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
"@types/uuid@^7.0.3": "@types/uuid@^7.0.3":
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-7.0.4.tgz#00a5749810b4ad80bff73a61f9cc9d0d521feb3c" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-7.0.4.tgz#00a5749810b4ad80bff73a61f9cc9d0d521feb3c"
@ -4473,6 +4504,11 @@ back@~0.1.5:
resolved "https://registry.yarnpkg.com/back/-/back-0.1.5.tgz#342b96b804657b03ec9a31f248a11f200608dcc2" resolved "https://registry.yarnpkg.com/back/-/back-0.1.5.tgz#342b96b804657b03ec9a31f248a11f200608dcc2"
integrity sha1-NCuWuARlewPsmjHySKEfIAYI3MI= integrity sha1-NCuWuARlewPsmjHySKEfIAYI3MI=
bail@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d"
integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
@ -4721,6 +4757,14 @@ buffers@~0.1.1:
resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s= integrity sha1-skV5w77U1tOWru5tmorn9Ugqt7s=
builder-util-runtime@8.9.2:
version "8.9.2"
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz#a9669ae5b5dcabfe411ded26678e7ae997246c28"
integrity sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==
dependencies:
debug "^4.3.2"
sax "^1.2.4"
builtins@^1.0.3: builtins@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
@ -4988,6 +5032,11 @@ changes-stream@^2.2.0:
http-https "~1.0.0" http-https "~1.0.0"
readable-stream "1.0.x" readable-stream "1.0.x"
character-entities@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.1.tgz#98724833e1e27990dee0bd0f2b8a859c3476aac7"
integrity sha512-OzmutCf2Kmc+6DrFrrPS8/tDh2+DpnrfzdICHWhcVC9eOd0N1PXmQEE1a8iM4IziIAG+8tmTq3K+oo0ubH6RRQ==
chardet@^0.7.0: chardet@^0.7.0:
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@ -5252,6 +5301,11 @@ combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
comma-separated-tokens@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98"
integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==
commander@^2.20.0, commander@^2.8.1: commander@^2.20.0, commander@^2.8.1:
version "2.20.3" version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@ -5767,6 +5821,13 @@ debug@^3.1.0, debug@^3.2.6:
dependencies: dependencies:
ms "^2.1.1" ms "^2.1.1"
debug@^4.0.0, debug@^4.3.2:
version "4.3.3"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
dependencies:
ms "2.1.2"
debug@~0.8.0: debug@~0.8.0:
version "0.8.1" version "0.8.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-0.8.1.tgz#20ff4d26f5e422cb68a1bacbbb61039ad8c1c130" resolved "https://registry.yarnpkg.com/debug/-/debug-0.8.1.tgz#20ff4d26f5e422cb68a1bacbbb61039ad8c1c130"
@ -5790,6 +5851,13 @@ decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
decode-named-character-reference@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.1.tgz#57b2bd9112659cacbc449d3577d7dadb8e1f3d1b"
integrity sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w==
dependencies:
character-entities "^2.0.0"
decode-uri-component@^0.2.0: decode-uri-component@^0.2.0:
version "0.2.0" version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
@ -5977,6 +6045,11 @@ deprecation@^2.0.0, deprecation@^2.3.1:
resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==
dequal@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d"
integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==
destroy@~1.0.4: destroy@~1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
@ -6210,6 +6283,20 @@ electron-to-chromium@^1.3.649:
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.695.tgz#955f419cf99137226180cc4cca2e59015a4e248d" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.695.tgz#955f419cf99137226180cc4cca2e59015a4e248d"
integrity sha512-lz66RliUqLHU1Ojxx1A4QUxKydjiQ79Y4dZyPobs2Dmxj5aVL2TM3KoQ2Gs7HS703Bfny+ukI3KOxwAB0xceHQ== integrity sha512-lz66RliUqLHU1Ojxx1A4QUxKydjiQ79Y4dZyPobs2Dmxj5aVL2TM3KoQ2Gs7HS703Bfny+ukI3KOxwAB0xceHQ==
electron-updater@^4.6.5:
version "4.6.5"
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.5.tgz#e9a75458bbfd6bb41a58a829839e150ad2eb2d3d"
integrity sha512-kdTly8O9mSZfm9fslc1mnCY+mYOeaYRy7ERa2Fed240u01BKll3aiupzkd07qKw69KvhBSzuHroIW3mF0D8DWA==
dependencies:
"@types/semver" "^7.3.6"
builder-util-runtime "8.9.2"
fs-extra "^10.0.0"
js-yaml "^4.1.0"
lazy-val "^1.0.5"
lodash.escaperegexp "^4.1.2"
lodash.isequal "^4.5.0"
semver "^7.3.5"
electron@^15.3.5: electron@^15.3.5:
version "15.3.6" version "15.3.6"
resolved "https://registry.yarnpkg.com/electron/-/electron-15.3.6.tgz#19b9aee1e063b1983b3d7f535567d90e0e1b4d04" resolved "https://registry.yarnpkg.com/electron/-/electron-15.3.6.tgz#19b9aee1e063b1983b3d7f535567d90e0e1b4d04"
@ -6760,7 +6847,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2:
assign-symbols "^1.0.0" assign-symbols "^1.0.0"
is-extendable "^1.0.1" is-extendable "^1.0.1"
extend@^3.0.2, extend@~3.0.2: extend@^3.0.0, extend@^3.0.2, extend@~3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
@ -7200,6 +7287,15 @@ fs-exists-sync@^0.1.0:
resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add"
integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=
fs-extra@^10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1"
integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^6.0.1"
universalify "^2.0.0"
fs-extra@^4.0.2: fs-extra@^4.0.2:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
@ -7893,6 +7989,11 @@ hash.js@^1.1.7:
inherits "^2.0.3" inherits "^2.0.3"
minimalistic-assert "^1.0.1" minimalistic-assert "^1.0.1"
hast-util-whitespace@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c"
integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==
he@1.2.0: he@1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
@ -8242,6 +8343,11 @@ init-package-json@^1.10.3:
validate-npm-package-license "^3.0.1" validate-npm-package-license "^3.0.1"
validate-npm-package-name "^3.0.0" validate-npm-package-name "^3.0.0"
inline-style-parser@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1"
integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==
inquirer@^6.2.0: inquirer@^6.2.0:
version "6.5.2" version "6.5.2"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca"
@ -8356,7 +8462,7 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-buffer@~2.0.3: is-buffer@^2.0.0, is-buffer@~2.0.3:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191"
integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
@ -8582,6 +8688,11 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1.0:
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
is-plain-obj@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.0.0.tgz#06c0999fd7574edf5a906ba5644ad0feb3a84d22"
integrity sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw==
is-plain-object@^2.0.3, is-plain-object@^2.0.4: is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4" version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@ -8787,6 +8898,13 @@ js-yaml@^3.13.1:
argparse "^1.0.7" argparse "^1.0.7"
esprima "^4.0.0" esprima "^4.0.0"
js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
jsbn@^1.1.0: jsbn@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
@ -8915,6 +9033,15 @@ jsonfile@^4.0.0:
optionalDependencies: optionalDependencies:
graceful-fs "^4.1.6" graceful-fs "^4.1.6"
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
dependencies:
universalify "^2.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
jsonparse@^1.2.0: jsonparse@^1.2.0:
version "1.3.1" version "1.3.1"
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
@ -9002,6 +9129,11 @@ kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3:
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
kleur@^4.0.3:
version "4.1.4"
resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d"
integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==
lazy-cache@^2.0.1, lazy-cache@^2.0.2: lazy-cache@^2.0.1, lazy-cache@^2.0.2:
version "2.0.2" version "2.0.2"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264"
@ -9009,6 +9141,11 @@ lazy-cache@^2.0.1, lazy-cache@^2.0.2:
dependencies: dependencies:
set-getter "^0.1.0" set-getter "^0.1.0"
lazy-val@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.5.tgz#6cf3b9f5bc31cee7ee3e369c0832b7583dcd923d"
integrity sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==
lcid@^1.0.0: lcid@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
@ -9250,11 +9387,21 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.escaperegexp@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
lodash.get@^4.4.2: lodash.get@^4.4.2:
version "4.4.2" version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.ismatch@^4.4.0: lodash.ismatch@^4.4.0:
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
@ -9534,7 +9681,55 @@ matcher@^3.0.0:
dependencies: dependencies:
escape-string-regexp "^4.0.0" escape-string-regexp "^4.0.0"
mdurl@^1.0.1: mdast-util-definitions@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.0.tgz#b6d10ef00a3c4cf191e8d9a5fa58d7f4a366f817"
integrity sha512-5hcR7FL2EuZ4q6lLMUK5w4lHT2H3vqL9quPvYZ/Ku5iifrirfMHiGdhxdXMUbUkDmz5I+TYMd7nbaxUhbQkfpQ==
dependencies:
"@types/mdast" "^3.0.0"
"@types/unist" "^2.0.0"
unist-util-visit "^3.0.0"
mdast-util-from-markdown@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz#84df2924ccc6c995dec1e2368b2b208ad0a76268"
integrity sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==
dependencies:
"@types/mdast" "^3.0.0"
"@types/unist" "^2.0.0"
decode-named-character-reference "^1.0.0"
mdast-util-to-string "^3.1.0"
micromark "^3.0.0"
micromark-util-decode-numeric-character-reference "^1.0.0"
micromark-util-decode-string "^1.0.0"
micromark-util-normalize-identifier "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
unist-util-stringify-position "^3.0.0"
uvu "^0.5.0"
mdast-util-to-hast@^12.1.0:
version "12.1.1"
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.1.1.tgz#89a2bb405eaf3b05eb8bf45157678f35eef5dbca"
integrity sha512-qE09zD6ylVP14jV4mjLIhDBOrpFdShHZcEsYvvKGABlr9mGbV7mTlRWdoFxL/EYSTNDiC9GZXy7y8Shgb9Dtzw==
dependencies:
"@types/hast" "^2.0.0"
"@types/mdast" "^3.0.0"
"@types/mdurl" "^1.0.0"
mdast-util-definitions "^5.0.0"
mdurl "^1.0.0"
micromark-util-sanitize-uri "^1.0.0"
unist-builder "^3.0.0"
unist-util-generated "^2.0.0"
unist-util-position "^4.0.0"
unist-util-visit "^4.0.0"
mdast-util-to-string@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9"
integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==
mdurl@^1.0.0, mdurl@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
@ -9631,6 +9826,201 @@ methods@^1.1.2, methods@~1.1.2:
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
micromark-core-commonmark@^1.0.1:
version "1.0.6"
resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad"
integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==
dependencies:
decode-named-character-reference "^1.0.0"
micromark-factory-destination "^1.0.0"
micromark-factory-label "^1.0.0"
micromark-factory-space "^1.0.0"
micromark-factory-title "^1.0.0"
micromark-factory-whitespace "^1.0.0"
micromark-util-character "^1.0.0"
micromark-util-chunked "^1.0.0"
micromark-util-classify-character "^1.0.0"
micromark-util-html-tag-name "^1.0.0"
micromark-util-normalize-identifier "^1.0.0"
micromark-util-resolve-all "^1.0.0"
micromark-util-subtokenize "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.1"
uvu "^0.5.0"
micromark-factory-destination@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e"
integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==
dependencies:
micromark-util-character "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
micromark-factory-label@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137"
integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg==
dependencies:
micromark-util-character "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
uvu "^0.5.0"
micromark-factory-space@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633"
integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==
dependencies:
micromark-util-character "^1.0.0"
micromark-util-types "^1.0.0"
micromark-factory-title@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f"
integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A==
dependencies:
micromark-factory-space "^1.0.0"
micromark-util-character "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
uvu "^0.5.0"
micromark-factory-whitespace@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c"
integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==
dependencies:
micromark-factory-space "^1.0.0"
micromark-util-character "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
micromark-util-character@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86"
integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==
dependencies:
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
micromark-util-chunked@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06"
integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==
dependencies:
micromark-util-symbol "^1.0.0"
micromark-util-classify-character@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20"
integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==
dependencies:
micromark-util-character "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
micromark-util-combine-extensions@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5"
integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==
dependencies:
micromark-util-chunked "^1.0.0"
micromark-util-types "^1.0.0"
micromark-util-decode-numeric-character-reference@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946"
integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==
dependencies:
micromark-util-symbol "^1.0.0"
micromark-util-decode-string@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02"
integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q==
dependencies:
decode-named-character-reference "^1.0.0"
micromark-util-character "^1.0.0"
micromark-util-decode-numeric-character-reference "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-encode@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383"
integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==
micromark-util-html-tag-name@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.0.0.tgz#75737e92fef50af0c6212bd309bc5cb8dbd489ed"
integrity sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g==
micromark-util-normalize-identifier@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828"
integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==
dependencies:
micromark-util-symbol "^1.0.0"
micromark-util-resolve-all@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88"
integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==
dependencies:
micromark-util-types "^1.0.0"
micromark-util-sanitize-uri@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz#27dc875397cd15102274c6c6da5585d34d4f12b2"
integrity sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==
dependencies:
micromark-util-character "^1.0.0"
micromark-util-encode "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-subtokenize@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105"
integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA==
dependencies:
micromark-util-chunked "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.0"
uvu "^0.5.0"
micromark-util-symbol@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e"
integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ==
micromark-util-types@^1.0.0, micromark-util-types@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20"
integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w==
micromark@^3.0.0:
version "3.0.10"
resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.0.10.tgz#1eac156f0399d42736458a14b0ca2d86190b457c"
integrity sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==
dependencies:
"@types/debug" "^4.0.0"
debug "^4.0.0"
decode-named-character-reference "^1.0.0"
micromark-core-commonmark "^1.0.1"
micromark-factory-space "^1.0.0"
micromark-util-character "^1.0.0"
micromark-util-chunked "^1.0.0"
micromark-util-combine-extensions "^1.0.0"
micromark-util-decode-numeric-character-reference "^1.0.0"
micromark-util-encode "^1.0.0"
micromark-util-normalize-identifier "^1.0.0"
micromark-util-resolve-all "^1.0.0"
micromark-util-sanitize-uri "^1.0.0"
micromark-util-subtokenize "^1.0.0"
micromark-util-symbol "^1.0.0"
micromark-util-types "^1.0.1"
uvu "^0.5.0"
micromatch@^3.1.10, micromatch@^3.1.4: micromatch@^3.1.10, micromatch@^3.1.4:
version "3.1.10" version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
@ -9914,6 +10304,11 @@ move-file@^1.1.0:
make-dir "^3.0.0" make-dir "^3.0.0"
path-exists "^3.0.0" path-exists "^3.0.0"
mri@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==
ms@2.0.0: ms@2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@ -11210,6 +11605,15 @@ promzard@^0.3.0:
dependencies: dependencies:
read "1" read "1"
prop-types@^15.0.0:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
dependencies:
loose-envify "^1.4.0"
object-assign "^4.1.1"
react-is "^16.13.1"
prop-types@^15.5.0, prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: prop-types@^15.5.0, prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
@ -11219,6 +11623,11 @@ prop-types@^15.5.0, prop-types@^15.5.6, prop-types@^15.5.8, prop-types@^15.6.0,
object-assign "^4.1.1" object-assign "^4.1.1"
react-is "^16.8.1" react-is "^16.8.1"
property-information@^6.0.0:
version "6.1.1"
resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22"
integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==
proto-list@~1.2.1: proto-list@~1.2.1:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
@ -11497,16 +11906,41 @@ react-input-autosize@^3.0.0:
dependencies: dependencies:
prop-types "^15.5.8" prop-types "^15.5.8"
react-is@^16.8.1: react-is@^16.13.1, react-is@^16.8.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^17.0.0:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
react-lifecycles-compat@^3.0.4: react-lifecycles-compat@^3.0.4:
version "3.0.4" version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
react-markdown@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.0.tgz#3243296a59ddb0f451d262cc2e11123674b416c2"
integrity sha512-qbrWpLny6Ef2xHqnYqtot948LXP+4FtC+MWIuaN1kvSnowM+r1qEeEHpSaU0TDBOisQuj+Qe6eFY15cNL3gLAw==
dependencies:
"@types/hast" "^2.0.0"
"@types/unist" "^2.0.0"
comma-separated-tokens "^2.0.0"
hast-util-whitespace "^2.0.0"
prop-types "^15.0.0"
property-information "^6.0.0"
react-is "^17.0.0"
remark-parse "^10.0.0"
remark-rehype "^10.0.0"
space-separated-tokens "^2.0.0"
style-to-object "^0.3.0"
unified "^10.0.0"
unist-util-visit "^4.0.0"
vfile "^5.0.0"
react-perfect-scrollbar@^1.5.3: react-perfect-scrollbar@^1.5.3:
version "1.5.8" version "1.5.8"
resolved "https://registry.yarnpkg.com/react-perfect-scrollbar/-/react-perfect-scrollbar-1.5.8.tgz#380959387a325c5c9d0268afc08b3f73ed5b3078" resolved "https://registry.yarnpkg.com/react-perfect-scrollbar/-/react-perfect-scrollbar-1.5.8.tgz#380959387a325c5c9d0268afc08b3f73ed5b3078"
@ -11863,6 +12297,25 @@ relative@^3.0.2:
dependencies: dependencies:
isobject "^2.0.0" isobject "^2.0.0"
remark-parse@^10.0.0:
version "10.0.1"
resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775"
integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==
dependencies:
"@types/mdast" "^3.0.0"
mdast-util-from-markdown "^1.0.0"
unified "^10.0.0"
remark-rehype@^10.0.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279"
integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==
dependencies:
"@types/hast" "^2.0.0"
"@types/mdast" "^3.0.0"
mdast-util-to-hast "^12.1.0"
unified "^10.0.0"
remarkable@^1.6.2, remarkable@^1.7.1: remarkable@^1.6.2, remarkable@^1.7.1:
version "1.7.4" version "1.7.4"
resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.4.tgz#19073cb960398c87a7d6546eaa5e50d2022fcd00" resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.4.tgz#19073cb960398c87a7d6546eaa5e50d2022fcd00"
@ -12128,6 +12581,13 @@ rxjs@^6.6.7:
dependencies: dependencies:
tslib "^1.9.0" tslib "^1.9.0"
sade@^1.7.3:
version "1.8.1"
resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701"
integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==
dependencies:
mri "^1.1.0"
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@ -12576,6 +13036,11 @@ source-map@~0.7.2:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
space-separated-tokens@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b"
integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==
spawn-rx@^3.0.0: spawn-rx@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/spawn-rx/-/spawn-rx-3.0.0.tgz#1d33511e13ec26337da51d78630e08beb57a6767" resolved "https://registry.yarnpkg.com/spawn-rx/-/spawn-rx-3.0.0.tgz#1d33511e13ec26337da51d78630e08beb57a6767"
@ -12959,6 +13424,13 @@ style-loader@^2.0.0:
loader-utils "^2.0.0" loader-utils "^2.0.0"
schema-utils "^3.0.0" schema-utils "^3.0.0"
style-to-object@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46"
integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==
dependencies:
inline-style-parser "0.1.1"
success-symbol@^0.1.0: success-symbol@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897" resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897"
@ -13358,6 +13830,11 @@ trim-repeated@^1.0.0:
dependencies: dependencies:
escape-string-regexp "^1.0.2" escape-string-regexp "^1.0.2"
trough@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/trough/-/trough-2.0.2.tgz#94a3aa9d5ce379fc561f6244905b3f36b7458d96"
integrity sha512-FnHq5sTMxC0sk957wHDzRnemFnNBvt/gSY99HzK8F7UP5WAbvP70yX5bd7CjEQkN+TjdxwI7g7lJ6podqrG2/w==
ts-md5@^1.2.2: ts-md5@^1.2.2:
version "1.2.7" version "1.2.7"
resolved "https://registry.yarnpkg.com/ts-md5/-/ts-md5-1.2.7.tgz#b76471fc2fd38f0502441f6c3b9494ed04537401" resolved "https://registry.yarnpkg.com/ts-md5/-/ts-md5-1.2.7.tgz#b76471fc2fd38f0502441f6c3b9494ed04537401"
@ -13585,6 +14062,19 @@ unicode-property-aliases-ecmascript@^1.0.4:
resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4"
integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==
unified@^10.0.0:
version "10.1.1"
resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.1.tgz#345e349e3ab353ab612878338eb9d57b4dea1d46"
integrity sha512-v4ky1+6BN9X3pQrOdkFIPWAaeDsHPE1svRDxq7YpTc2plkIqFMwukfqM+l0ewpP9EfwARlt9pPFAeWYhHm8X9w==
dependencies:
"@types/unist" "^2.0.0"
bail "^2.0.0"
extend "^3.0.0"
is-buffer "^2.0.0"
is-plain-obj "^4.0.0"
trough "^2.0.0"
vfile "^5.0.0"
union-value@^1.0.0: union-value@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
@ -13609,6 +14099,69 @@ unique-slug@^2.0.0:
dependencies: dependencies:
imurmurhash "^0.1.4" imurmurhash "^0.1.4"
unist-builder@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04"
integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==
dependencies:
"@types/unist" "^2.0.0"
unist-util-generated@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113"
integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==
unist-util-is@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236"
integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==
unist-util-position@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.1.tgz#f8484b2da19a897a0180556d160c28633070dbb9"
integrity sha512-mgy/zI9fQ2HlbOtTdr2w9lhVaiFUHWQnZrFF2EUoVOqtAUdzqMtNiD99qA5a1IcjWVR8O6aVYE9u7Z2z1v0SQA==
unist-util-stringify-position@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.0.tgz#d517d2883d74d0daa0b565adc3d10a02b4a8cde9"
integrity sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA==
dependencies:
"@types/unist" "^2.0.0"
unist-util-visit-parents@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz#e83559a4ad7e6048a46b1bdb22614f2f3f4724f2"
integrity sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==
dependencies:
"@types/unist" "^2.0.0"
unist-util-is "^5.0.0"
unist-util-visit-parents@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.0.tgz#44bbc5d25f2411e7dfc5cecff12de43296aa8521"
integrity sha512-y+QVLcY5eR/YVpqDsLf/xh9R3Q2Y4HxkZTp7ViLDU6WtJCEcPmRzW1gpdWDCDIqIlhuPDXOgttqPlykrHYDekg==
dependencies:
"@types/unist" "^2.0.0"
unist-util-is "^5.0.0"
unist-util-visit@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-3.1.0.tgz#9420d285e1aee938c7d9acbafc8e160186dbaf7b"
integrity sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==
dependencies:
"@types/unist" "^2.0.0"
unist-util-is "^5.0.0"
unist-util-visit-parents "^4.0.0"
unist-util-visit@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.0.tgz#f41e407a9e94da31594e6b1c9811c51ab0b3d8f5"
integrity sha512-n7lyhFKJfVZ9MnKtqbsqkQEk5P1KShj0+//V7mAcoI6bpbUjh3C/OG8HVD+pBihfh6Ovl01m8dkcv9HNqYajmQ==
dependencies:
"@types/unist" "^2.0.0"
unist-util-is "^5.0.0"
unist-util-visit-parents "^5.0.0"
universal-user-agent@^4.0.0: universal-user-agent@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557"
@ -13626,6 +14179,11 @@ universalify@^0.1.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
unpipe@1.0.0, unpipe@~1.0.0: unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@ -13769,6 +14327,16 @@ uuid@^8.0.0, uuid@^8.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
uvu@^0.5.0:
version "0.5.3"
resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.3.tgz#3d83c5bc1230f153451877bfc7f4aea2392219ae"
integrity sha512-brFwqA3FXzilmtnIyJ+CxdkInkY/i4ErvP7uV0DnUVxQcQ55reuHphorpF+tZoVHK2MniZ/VJzI7zJQoc9T9Yw==
dependencies:
dequal "^2.0.0"
diff "^5.0.0"
kleur "^4.0.3"
sade "^1.7.3"
v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0: v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0:
version "2.3.0" version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
@ -13815,6 +14383,24 @@ verror@1.10.0:
core-util-is "1.0.2" core-util-is "1.0.2"
extsprintf "^1.2.0" extsprintf "^1.2.0"
vfile-message@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.0.tgz#5437035aa43185ff4b9210d32fada6c640e59143"
integrity sha512-4QJbBk+DkPEhBXq3f260xSaWtjE4gPKOfulzfMFF8ZNwaPZieWsg3iVlcmF04+eebzpcpeXOOFMfrYzJHVYg+g==
dependencies:
"@types/unist" "^2.0.0"
unist-util-stringify-position "^3.0.0"
vfile@^5.0.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.0.tgz#4990c78cb3157005590ee8c930b71cd7fa6a006e"
integrity sha512-Tj44nY/48OQvarrE4FAjUfrv7GZOYzPbl5OD65HxVKwLJKMPU7zmfV8cCgCnzKWnSfYG2f3pxu+ALqs7j22xQQ==
dependencies:
"@types/unist" "^2.0.0"
is-buffer "^2.0.0"
unist-util-stringify-position "^3.0.0"
vfile-message "^3.0.0"
vhost@^3.0.2: vhost@^3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5"