This project is using Electron to create an Angular app using Jest instead of Karma, Cypress instead of Protractor, Angular Material and TailwindCSS. Moreover, formatting, style linting, documentation generation and git hooks (for linting) have been added to be more complete. This README explains all modifications made to initial Angular project.
This project is fully inspired by angular-electron by Maxime Gris, but with addition of TailwindCSS, Jest, Material, Stylelint, Compodoc and several tools.
- Node.js v12 (Javascript Engine)
- Yarn v1 (Package Manager)
- Angular v10.1.6 (Single Page Application)
- Electron
Before you begin we recommend you read about the basic building blocks that assemble this application:
- Electron - Electron's official website documentation will explain all the aspects of an app development.
- Angular - Angular's official Website is a great starting point. You can also use Thinkster Popular Guide, and Egghead Videos.
- Node.js - Start by going through node.js Official Website and this StackOverflow Thread, which should get you going with the Node.js platform in no time.
Make sure you have installed all of the following prerequisites on your development machine:
- Git - Download & Install Git. OSX and Linux machines typically have this already installed.
- Node.js 12 - Download & Install Node.js and the npm package manager. If you encounter any problems, you can also use this GitHub Gist to install Node.js.
- Yarn (v1) - You're going to use the Yarn Package Manager to manage your packages and dependencies. Follow these instructions to install Yarn.
- Clone the repo
$ git clone https://github.com/gael-clair/angular-electron.git YOUR_REPO_FOLDER
- Get into repo folder
$ cd YOUR_REPO_FOLDER
- Add your repo as origin
$ git remote remove origin
$ git remote add origin YOUR_REPO_URL
-
Update project name in
package.json
-
Install dependencies
$ npm install
# build application in production mode
$ yarn build
# build angular app
$ yarn ng:tw:build
# build angular app in production mode
$ yarn ng:tw:build:prod
# build electron app
$ yarn electron:build
# build electron app in production mode
$ yarn electron:build:prod
# starts angular development server with live reload and open electron in watch mode
$ yarn start
# starts angular and electron unit tests
$ yarn test
# starts angular and electron unit tests with source/test files watch
$ yarn test:watch
# starts angular and electron unit tests in CI mode with coverage (coverage in coverage folder and reports in reports folder)
$ yarn test:ci
# starts angular unit tests
$ yarn ng:test
# starts angular unit tests with source/test files watch
$ yarn ng:test:watch
# starts angular unit tests with coverage
$ yarn ng:test:cov
# starts angular unit tests in CI mode with coverage (coverage in coverage folder and reports in reports folder)
$ yarn ng:test:ci
# starts electron unit tests
$ yarn electron:test
# starts electron unit tests with source/test files watch
$ yarn electron:test:watch
# starts electron unit tests with coverage
$ yarn electron:test:cov
# starts electron unit tests in CI mode with coverage (coverage in coverage folder and reports in reports folder)
$ yarn electron:test:ci
# starts angular and open cypress
$ yarn ng:e2e
# starts angular and run cypress
$ yarn ng:e2e:ci
# builds angular and electron app and starts jest tests with spectron
$ yarn e2e
# builds angular and electron app and starts jest tests in CI mode with spectron
$ yarn e2e:ci
# lints source and test files
$ yarn lint
# lints source and test files and fixes errors if possible
$ yarn lint:fix
# lints source and test files and generate a report (report at reports/lint.xml)
$ yarn lint:ci
# lints style files
$ yarn lint:style
# lints style files and fixes errors if possible
$ yarn lint:style:fix
# lints style files and generate a report (report at reports/style.xml)
$ yarn lint:style:ci
# formats source and test files
$ yarn format
# generates angular project documentation
$ yarn ng:doc
The repo includes a Github Action configuration for continuous integration (workflow file .github/workflows/checks.yml
) It is also integrated with Coveralls during workflow process.
To let electron-builder publish new release, you have to had to repository secrets a Github token with write:package permission. When token generated go to Repo Settings > Secrets > New secret
add a secret with GH_TOKEN name and token as value.
It will be automatically exposed as en environment variable in the workflow.
- Install (with cache)
- Build
- Lint
- Angular unit tests
- Coveralls upload result of angular unit tests
- Angular integration tests
- Coveralls upload result of angular integration tests
- Electron unit tests
- Coveralls upload result of electron unit tests
- End-to-End tests
- Build release artifacts
- Upload of coverage reports artifact
- Upload of test reports artifact
To be sure to pass checks before merging a Pull Request you should add required checks in Repo Settings > Branches > Branch protection rules > Require status checks to pass before merging
:
- Coveralls - angular-unit-tests
- Coveralls - angular-integration-tests
- Coveralls - electron-unit-tests
- checks (build, lint, test)
- coverage/coveralls
To add a check failure if coverage percentage is under a certain threshold, go to the repository page on Coveralls and go to Settings > PULL REQUESTS ALERTS > COVERAGE THRESHOLD FOR FAILURE
and set minimal value for coverage percentage (for example 80%).
This project is based on Angular. The @angular/cli command used to generate this project is:
$ npx @angular/cli new angular-electron --routing=true --style=scss --minimal=true
-
Rename
tsconfig.json
totsconfig.base.json
. -
Move
tsconfig.app.json
andtsconfig.spec.json
tosrc
folder. -
Update
tsconfig.base.json
with:
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": ".",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"esModuleInterop": true, // add
"allowSyntheticDefaultImports": true, // add
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"module": "es2020",
"lib": ["es2018", "dom"]
}
}
- Update
src/tsconfig.app.json
with:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app"
},
"files": [
"main.ts", // remove src/
"polyfills.ts" // remove src/
],
"include": [
"**/*.d.ts" // remove src/
]
}
- Update
src/tsconfig.spec.json
with:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": ["jasmine"]
},
"files": [
"test.ts", // remove src/
"polyfills.ts" // remove src/
],
"include": [
"**/*.spec.ts", // remove src/
"**/*.d.ts" // remove src/
]
}
- Create
src/tsconfig.json
with:
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"paths": {
"@app/core/*": ["src/app/core/*"],
"@app/core": ["src/app/core"],
"@app/shared/*": ["src/app/shared/*"],
"@app/shared": ["src/app/shared"],
"@app/features/*": ["src/app/features/*"],
"@app/features": ["src/app/features"],
"@app/env": ["src/environments/environment"],
"@app/types": ["src/app/types"],
"@test/utils": ["src/test.utils.ts"]
}
}
}
- Update
angular.json > projects > angular-electron > architect > build > options
with:
{
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "src/dist", // update
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json", // add src/
"aot": true,
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"scripts": []
}
}
}
- Update
angular.json > projects > angular-electron > architect > lint > options > tsConfig
with:
{
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json", // add src/
"src/tsconfig.spec.json" // add src/
],
"exclude": ["**/node_modules/**"]
}
}
}
TailwindCSS is used with Material to provide UI components and utilities.
- Add tailwind dependencies:
$ yarn add -D tailwindcss ng-tailwindcss
- Create file
tailwind.config.js
with:
$ npx tailwind init
- Create file
src/tailwind.css
with:
@tailwind base;
@tailwind components;
@tailwind utilities;
- Create file
ng-tailwind.js
file with:
$ npx ngtw configure
- Update file
ng-tailwind.js
to be compatible with windows and linux:
module.exports = {
// Tailwind Paths
configJS: 'tailwind.config.js',
sourceCSS: 'src/tailwind.css', // if created on windows, replace \\ with /
outputCSS: 'src/styles.css', // if created on windows, replace \\ with /
// Sass
sass: false,
// PurgeCSS Settings
purge: false,
keyframes: false,
fontFace: false,
rejected: false,
whitelist: [],
whitelistPatterns: [],
whitelistPatternsChildren: [],
extensions: ['.ts', '.html', '.js'],
extractors: [],
content: [],
};
- Update
angular.json > projects > angular-electron > architect > build
:
{
"build": {
"options": {
"styles": ["src/styles.scss", "src/styles.css"] // add styles.css file a source file for styles
}
}
}
- To build
src/styles.css
before using app (serving, building or testing) be sure to run:
# build Tailwind CSS
$ ngtw build
# build Tailwind CSS with purge of unused elements
$ ngtw build --purge
- To constantly build
src/styles.css
when source files are modified, use watch mode in parallel to serve mode:
$ ngtw watch
- Add
src/styles.css
to.gitignore
file.
This project is using Material Design with @angular/material installed with:
- Install dependencies:
$ yarn add @angular/cdk hammerjs
- Run schematics to add Material to project:
$ yarn ng add @angular/material
# Theme: Purple/Green
# No global Angular Material typography styles
# With browser animations for Angular Material
- Add selected style file in
angular.json > projects > angular-electron > architect > build > options > styles
:
{
"styles": [
"./node_modules/@angular/material/prebuilt-themes/purple-green.css", // add material style
"src/styles.scss",
"src/styles.css"
]
}
Unit testing is based initially on the use of Karma/Jasmine but this project uses Jest instead. To add Jest:
- Install Jest and related dependencies
$ yarn add -D jest jest-preset-angular jest-junit ts-jest @types/jest jest-html-reporter
- Remove
types
property andtest.ts
fromfiles
property fromtsconfig.spec.json
:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec"
},
"files": ["polyfills.ts"],
"include": ["**/*.spec.ts", "**/*.d.ts"]
}
- Create
src/jest.config.js
with:
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig.json');
module.exports = {
preset: 'jest-preset-angular',
verbose: true,
setupFilesAfterEnv: ['./setupJest.ts'],
coverageDirectory: '../coverage/angular/ut',
collectCoverageFrom: ['app/**/*.ts', '!app/**/*(index|*.module|*.routes|index.d).ts'],
globals: {
'ts-jest': {
tsConfig: 'src/tsconfig.spec.json',
},
},
reporters: [
'default',
[
'jest-junit',
{
suiteName: 'Unit tests',
outputDirectory: 'reports/angular',
outputName: 'ut.xml',
},
],
[
'../node_modules/jest-html-reporter',
{
pageTitle: 'Unit tests Report',
outputPath: 'reports/angular/ut.html',
includeFailureMsg: true,
},
],
],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
prefix: '<rootDir>/..',
}),
};
- Create
src/setupJest.ts
with:
import 'jest-preset-angular';
const mock = () => {
let storage: { [key: string]: string } = {};
return {
getItem: (key: string) => (key in storage ? storage[key] : null),
setItem: (key: string, value: string) => (storage[key] = value || ''),
removeItem: (key: string) => delete storage[key],
clear: () => (storage = {}),
};
};
Object.defineProperty(window, 'localStorage', { value: mock() });
Object.defineProperty(window, 'sessionStorage', { value: mock() });
Object.defineProperty(window, 'CSS', { value: null });
Object.defineProperty(window, 'getComputedStyle', {
value: () => {
return {
display: 'none',
appearance: ['-webkit-appearance'],
};
},
});
Object.defineProperty(document, 'doctype', {
value: '<!DOCTYPE html>',
});
Object.defineProperty(document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true,
};
},
});
-
Remove Angular test target in
angular.json > projects > angular-electron > architect > test
-
If you generated the project without
--minimal=true
:- Some useless files could be deleted:
$ rm karma.conf.js src/test.ts
- Remove Karma dependencies:
$ yarn remove karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter
- Install cypress-schematic and dependencies (for coverage)
$ yarn add -D @briebug/cypress-schematic wait-on
- Add schematics to project
$ yarn ng add @briebug/cypress-schematic --noBuilder
# Remove Protractor
- Update
cypress/tsconfig.json
with:
{
"extends": "../tsconfig.base.json", // refer to base json
"compilerOptions": {
"outDir": "../out-tsc/cypress", // change
"sourceMap": false
},
"include": ["../node_modules/cypress", "**/*.ts"]
}
- Update
angular.json > projects > angular-electron > architect > lint
switching typescript config file for e2e frome2e/tsconfig.json
tocypress/tsconfig.json
:
{
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json", "cypress/tsconfig.json"], // replace e2e/ with cypress/
"exclude": ["**/node_modules/**"]
}
}
}
-
To add coverage to cypress:
- Install dependencies
$ yarn add -D ngx-build-plus istanbul-instrumenter-loader @istanbuljs/nyc-config-typescript source-map-support ts-node @cypress/code-coverage nyc istanbul-lib-coverage
- Create file
cypress/coverage.webpack.js
with:
module.exports = { module: { rules: [ { test: /\.(js|ts)$/, loader: 'istanbul-instrumenter-loader', options: { esModules: true }, enforce: 'post', include: require('path').join(__dirname, '../src/app'), exclude: [/\.(e2e|spec)\.ts$/, /node_modules/, /(ngfactory|ngstyle)\.js/], }, ], }, };
- Update
angular.json > projects > angular-electron > architect > e2e
with:
{ "e2e": { "builder": "ngx-build-plus:dev-server", "options": { "browserTarget": "angular-electron:build", "extraWebpackConfig": "./cypress/coverage.webpack.js" } } }
- Create file
.nycrc.json
with:
{ "extends": "@istanbuljs/nyc-config-typescript", "report-dir": "./coverage/angular/ti" }
- Add to file
cypress/support/index.d.ts
:
import '@cypress/code-coverage/support';
- Update file
cypress/plugins/index.js
with:
const cypressTypeScriptPreprocessor = require('./cy-ts-preprocessor'); const registerCodeCoverageTasks = require('@cypress/code-coverage/task'); module.exports = (on, config) => { on('file:preprocessor', cypressTypeScriptPreprocessor); return registerCodeCoverageTasks(on, config); // activate coverage task };
- To run tests coverage with cypress, after command
yarn e2e
use:
$ cypress run
-
If you generated project without
--minimal=true
you could delete some file and configuration:- Remove Jasmine dependencies:
$ yarn remove jasmine-core jasmine-spec-reporter @types/jasmine @types/jasminewd2
- Remove e2e folder.
- Install TSLint preset for Angular:
$ yarn add -D tslint-angular
- Add tslint-angular preset to extends array in
tslint.json
:
{
"extends": ["tslint:recommended", "tslint-angular"]
}
- Install Prettier and dependencies to deal with Typescript and linters:
$ yarn add -D prettier tslint-config-prettier tslint-plugin-prettier
- Create Prettier configuration file
.prettierrc.json
with:
{
"singleQuote": true,
"trailingComma": "all",
"endOfLine": "lf",
"printWidth": 120,
"tabWidth": 2
}
- To prevent TSLint to use rules that Prettier will take care of, activate prettier in rules and add
tslint-plugin-prettier
to rulesDirectory intslint.json
:
{
"extends": ["tslint:recommended", "tslint-angular", "tslint-config-prettier"],
"rulesDirectory": ["codelyzer", "tslint-plugin-prettier"] // add rules
"rules": {
"prettier": true // apply prettier rules
}
}
- Create file
.prettierignore
with:
/.nyc_output
/coverage
/electron/dist
/reports
/src/styles.css
/src/dist
In order to add linting of style files (css and scss), Stylelint is used with some rules presets.
- Install Stylelint dependencies:
$ yarn add -D stylelint stylelint-config-recommended stylelint-junit-formatter stylelint-no-unsupported-browser-features stylelint-config-prettier stylelint-prettier make-dir
- Create Stylelint configuration
.stylelintrc.json
file with:
{
"extends": ["stylelint-prettier/recommended", "stylelint-config-recommended", "stylelint-config-prettier"],
"plugins": ["stylelint-no-unsupported-browser-features", "stylelint-prettier"],
"rules": {
"prettier/prettier": true,
"at-rule-no-unknown": [
true,
{
"ignoreAtRules": ["tailwind"]
}
],
"plugin/no-unsupported-browser-features": [
true,
{
"severity": "warning"
}
],
"no-empty-source": null
},
"junit-formatter": {
"outputPath": "reports/style.xml"
}
}
One pre-commit git hook is activated with Husky to call Lint-staged to format and lint files to be commited. If one operation fails commit is canceled. One commit-msg git hook is set to let @commitlint/cli lint commit message to ensure that it follows conventional-changelog format.
To configure git hooks you have to:
- Add husky, commitlint and cz-conventional-changelog dependencies:
yarn add -D husky lint-staged @commitlint/cli @commitlint/config-conventional cz-conventional-changelog commitizen
- Create file
.cz.json
with:
{
"path": "cz-conventional-changelog"
}
- Create file
.commitlintrc.json
with:
{
"extends": ["@commitlint/config-conventional"]
}
- Create file
.huskyrc.json
with:
{
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-commit": "lint-staged"
}
}
- Create a file
.lintstagedrc
with JSON configuration:
{
"*.{json,js,ts,tsx,md,html,yml}": "prettier --write",
"*.{scss,css}": "stylelint --fix",
"*.{ts,tsx,js,jsx}": "tslint --fix"
}
Compodoc is used to write documentation.
- Add dependencies
$ yarn add -D @compodoc/compodoc
- Install Electron and its dependencies:
$ yarn add -D electron
-
Create folder
electron/src
. -
Create file
electron/tsconfig.json
with:
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"module": "commonjs"
},
"include": ["src/**/*.ts"],
"exclude": ["src/**/*.spec.ts"]
}
- Create file
electron/main.ts
with:
import { app, BrowserWindow, screen } from 'electron';
import * as path from 'path';
import * as url from 'url';
let win: BrowserWindow = null;
const args = process.argv.slice(1);
const serve = args.some((val) => val === '--serve');
function createWindow(): BrowserWindow {
const size = screen.getPrimaryDisplay().workAreaSize;
// Create the browser window.
win = new BrowserWindow({
center: true,
width: size.width / 2,
height: size.height / 2,
webPreferences: {
nodeIntegration: false, // disabled for security reasons
allowRunningInsecureContent: true, // to serve from localhost
contextIsolation: true, // enabled for security reasons
enableRemoteModule: false, // disabled for security reasons
preload: path.resolve(__dirname, 'preload.js'),
},
});
if (serve) {
win.webContents.openDevTools();
require('electron-reload')(path.join(__dirname), {
electron: path.join(__dirname, '../../node_modules/.bin/electron'),
argv: ['--serve'],
});
win.loadURL('http://localhost:4200');
} else {
win.loadURL(
url.format({
pathname: path.join(__dirname, '../../src/dist/index.html'),
protocol: 'file:',
slashes: true,
}),
);
}
// Emitted when the window is closed.
win.on('closed', () => {
// Dereference the window object, usually you would store window
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null;
});
return win;
}
function main(): void {
try {
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
// Added 400 ms to fix the black background issue while using transparent window.
// More detais at https://github.com/electron/electron/issues/15947
app.on('ready', () => {
setTimeout(createWindow, 400);
});
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow();
}
});
} catch (e) {
// Catch Error
// throw e;
}
}
main();
- For security reasons, context isolation is activated, and node integration and remote deactivated. To let renderer process communicate in a controlled manner we expose utilities functions to propose a secure manner to communicate with main process. Create file
electron/src/preload.ts
with:
import { contextBridge, ipcRenderer } from 'electron';
const IN_EVENTS = [];
const OUT_EVENTS = [];
contextBridge.exposeInMainWorld('eventsApi', {
send: (channel, ...data): void => {
if (IN_EVENTS.includes(channel)) {
ipcRenderer.send(channel, ...data);
}
},
receive: (channel, cb): void => {
if (OUT_EVENTS.includes(channel)) {
ipcRenderer.on(channel, (event, ...args) => cb(...args));
}
},
invoke: async (channel, ...data): Promise<any> => {
if (IN_EVENTS.includes(channel)) {
return await ipcRenderer.invoke(channel, ...data);
}
},
});
- Create file
electron/tsconfig.spec.json
for unit tests with:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/electron/spec"
},
"include": ["**/*.spec.ts"]
}
- Create file
electron/jest.config.js
with:
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig.json');
module.exports = {
verbose: true,
coverageDirectory: '../coverage/electron/ut',
collectCoverageFrom: ['src/**/*.ts', '!src/**/index.d.ts'],
transform: { '\\.ts$': ['ts-jest'] },
globals: {
'ts-jest': {
tsConfig: 'electron/tsconfig.spec.json',
},
},
reporters: [
'default',
[
'jest-junit',
{
suiteName: 'Unit tests',
outputDirectory: 'reports/electron',
outputName: 'ut.xml',
},
[
'../node_modules/jest-html-reporter',
{
pageTitle: 'Unit tests Report',
outputPath: 'reports/electron/ut/ut.html',
includeFailureMsg: true,
},
],
],
],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
prefix: '<rootDir>',
}),
};
- Write your tests in
*.spec.ts
files.
- Install Spectron:
$ yarn add -D spectron
-
Create folder
e2e/src
. -
Create file
e2e/tsconfig.json
with:
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e"
},
"include": ["src/**/*.e2e.ts"]
}
- Create file
e2e/jest.config.js
with:
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig.json');
module.exports = {
verbose: true,
testMatch: ['**/*.e2e.ts'],
transform: { '\\.ts$': ['ts-jest'] },
globals: {
'ts-jest': {
tsConfig: 'e2e/tsconfig.json',
},
},
testEnvironment: 'node',
reporters: [
'default',
[
'jest-junit',
{
suiteName: 'E2E tests',
outputDirectory: 'reports/e2e',
outputName: 'e2e.xml',
},
[
'../node_modules/jest-html-reporter',
{
pageTitle: 'E2E tests Report',
outputPath: 'reports/e2e/e2e.html',
includeFailureMsg: true,
},
],
],
],
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
prefix: '<rootDir>/..',
}),
};
- Install
electron-builder
:
$ yarn add -D electron-builder
- Create file
electron-builder.json
with:
{
"appId": "com.electron.angular-electron",
"productName": "angular-electron",
"directories": {
"output": "release/"
},
"files": ["electron/dist", "src/dist"],
"win": {
"icon": "src/dist/assets/icons/favicon.ico",
"target": ["portable"]
},
"mac": {
"icon": "src/dist/assets/icons/favicon.ico",
"target": ["dmg"]
},
"linux": {
"icon": "src/dist/assets/icons/favicon.256x256.png",
"target": ["AppImage"]
}
}
-
Init
yarn add -D npm-run-all make-dir make-dir-cli
-
Git hooks:
- husky
- @commitlint/cli
- @commitlint/config-conventional
- commitizen
- cz-conventional-changelog
- lint-staged
yarn add -D husky @commitlint/cli @commitlint/config-conventional commitizen cz-conventional-changelog lint-staged
-
UI design:
# Material (added with ng add @angular/material command) $ yarn add @angular/material @angular/cdk hammerjs # TailwindCSS $ yarn add -D tailwindcss ng-tailwindcss
-
Testing:
- jest
- jest-junit
- jest-preset-angular
- jest-html-reporter
- ts-jest
- @types/jest
- istanbul-instrumenter-loader
- ngx-build-plus
- wait-on
- @briebug/cypress-schematic
- @istanbuljs/nyc-config-typescript
- source-map-support
- ts-node
- @cypress/code-coverage
- nyc
- istanbul-lib-coverage
$ yarn add -D jest jest-junit jest-preset-angular ts-jest @types/jest jest-html-reporter ngx-build-plus istanbul-instrumenter-loader @istanbuljs/nyc-config-typescript source-map-support ts-node @cypress/code-coverage nyc istanbul-lib-coverage wait-on @briebug/cypress-schematic
-
Documentation:
$ yarn add -D @compodoc/compodoc
-
Formatting:
$ yarn add -D prettier tslint-config-prettier tslint-plugin-prettier
-
Linting:
- tslint-angular
- stylelint
- stylelint-config-recommended
- stylelint-junit-formatter
- stylelint-no-unsupported-browser-features
- stylelint-config-prettier
- stylelint-prettier
$ yarn add -D tslint-angular stylelint stylelint-config-recommended stylelint-junit-formatter stylelint-no-unsupported-browser-features stylelint-config-prettier stylelint-prettier
-
Electron
$ yarn add -D electron electron-builder spectron
- jasmine-core
- jasmine-spec-reporter
- karma
- karma-chrome-launcher
- karma-coverage-istanbul-reporter
- karma-jasmine
- karma-jasmine-html-reporter
- protractor
- @types/jasmine
- @types/jasminewd2
$ yarn remove jasmine-core jasmine-spec-reporter karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter protractor @types/jasmine @types/jasminewd2