Compare commits

..

3 Commits

Author SHA1 Message Date
undergroundwires
c7054521a7 win: improve output/user feedback capabilities
- Improve error handling.
- Provide more detailed user feedback with meaningful messages.
- Check if capability exists before performing operations.
- Inform system restart is needed.
2023-08-04 17:50:07 +01:00
undergroundwires
ff84f5676e Transition to eslint-config-airbnb-with-typescript
- Migrate to newer `eslint-config-airbnb-with-typescript` from
  `eslint-config-airbnb`.
- Add also `rushstack/eslint-patch` as per instructed by
  `eslint-config-airbnb-with-typescript` docs.
- Update codebase to align with new linting standards.
- Add script to configure VS Code for effective linting for project
  developers, move it to `scripts` directory along with clean npm
  install script for better organization.
2023-08-04 16:39:36 +02:00
undergroundwires-bot
4d0ce12c96 ⬆️ bump everywhere to 0.12.0 2023-08-03 18:22:36 +00:00
41 changed files with 2465 additions and 701 deletions

View File

@@ -1,4 +1,4 @@
[*.{js,jsx,ts,tsx,vue}] [*.{js,jsx,ts,tsx,vue,sh}]
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
end_of_line = lf end_of_line = lf

View File

@@ -1,10 +1,6 @@
const { rules: baseBestPracticesRules } = require('eslint-config-airbnb-base/rules/best-practices');
const { rules: baseErrorsRules } = require('eslint-config-airbnb-base/rules/errors');
const { rules: baseES6Rules } = require('eslint-config-airbnb-base/rules/es6');
const { rules: baseImportsRules } = require('eslint-config-airbnb-base/rules/imports');
const { rules: baseStyleRules } = require('eslint-config-airbnb-base/rules/style'); const { rules: baseStyleRules } = require('eslint-config-airbnb-base/rules/style');
const { rules: baseVariablesRules } = require('eslint-config-airbnb-base/rules/variables');
const tsconfigJson = require('./tsconfig.json'); const tsconfigJson = require('./tsconfig.json');
require('@rushstack/eslint-patch/modern-module-resolution');
module.exports = { module.exports = {
root: true, root: true,
@@ -17,9 +13,7 @@ module.exports = {
'plugin:vue/essential', 'plugin:vue/essential',
// Extends eslint-config-airbnb // Extends eslint-config-airbnb
// Added by Vue CLI '@vue/eslint-config-airbnb-with-typescript',
// Here until https://github.com/vuejs/eslint-config-airbnb/issues/23 is done
'@vue/airbnb',
// Extends @typescript-eslint/recommended // Extends @typescript-eslint/recommended
// Uses the recommended rules from the @typescript-eslint/eslint-plugin // Uses the recommended rules from the @typescript-eslint/eslint-plugin
@@ -52,18 +46,6 @@ module.exports = {
mocha: true, mocha: true,
}, },
}, },
{
files: ['**/*.ts?(x)', '**/*.d.ts'],
parserOptions: {
// Setting project is required for some rules such as @typescript-eslint/dot-notation,
// @typescript-eslint/return-await and @typescript-eslint/no-throw-literal.
// If this property is missing they fail due to missing parser.
project: ['./tsconfig.json'],
},
rules: {
...getTypeScriptOverrides(),
},
},
{ {
files: ['**/tests/**/*.{j,t}s?(x)'], files: ['**/tests/**/*.{j,t}s?(x)'],
rules: { rules: {
@@ -115,6 +97,7 @@ function getOpinionatedRuleOverrides() {
return { return {
// https://erkinekici.com/articles/linting-trap#no-use-before-define // https://erkinekici.com/articles/linting-trap#no-use-before-define
'no-use-before-define': 'off', 'no-use-before-define': 'off',
'@typescript-eslint/no-use-before-define': 'off',
// https://erkinekici.com/articles/linting-trap#arrow-body-style // https://erkinekici.com/articles/linting-trap#arrow-body-style
'arrow-body-style': 'off', 'arrow-body-style': 'off',
// https://erkinekici.com/articles/linting-trap#no-plusplus // https://erkinekici.com/articles/linting-trap#no-plusplus
@@ -134,164 +117,6 @@ function getOpinionatedRuleOverrides() {
}; };
} }
function getTypeScriptOverrides() {
/*
Here until Vue supports AirBnb Typescript overrides (vuejs/eslint-config-airbnb#23).
Based on `eslint-config-airbnb-typescript`.
Source: https://github.com/iamturns/eslint-config-airbnb-typescript/blob/v16.1.0/lib/shared.js
It cannot be used directly due to compilation errors.
*/
return {
'brace-style': 'off',
'@typescript-eslint/brace-style': baseStyleRules['brace-style'],
camelcase: 'off',
'@typescript-eslint/naming-convention': [
'error',
{ selector: 'variable', format: ['camelCase', 'PascalCase', 'UPPER_CASE'] },
{ selector: 'function', format: ['camelCase', 'PascalCase'] },
{ selector: 'typeLike', format: ['PascalCase'] },
],
'comma-dangle': 'off',
'@typescript-eslint/comma-dangle': [
baseStyleRules['comma-dangle'][0],
{
...baseStyleRules['comma-dangle'][1],
enums: baseStyleRules['comma-dangle'][1].arrays,
generics: baseStyleRules['comma-dangle'][1].arrays,
tuples: baseStyleRules['comma-dangle'][1].arrays,
},
],
'comma-spacing': 'off',
'@typescript-eslint/comma-spacing': baseStyleRules['comma-spacing'],
'default-param-last': 'off',
'@typescript-eslint/default-param-last': baseBestPracticesRules['default-param-last'],
'dot-notation': 'off',
'@typescript-eslint/dot-notation': baseBestPracticesRules['dot-notation'],
'func-call-spacing': 'off',
'@typescript-eslint/func-call-spacing': baseStyleRules['func-call-spacing'],
// ❌ Broken for some cases, but still useful.
// Here until Prettifier is used.
indent: 'off',
'@typescript-eslint/indent': baseStyleRules.indent,
'keyword-spacing': 'off',
'@typescript-eslint/keyword-spacing': baseStyleRules['keyword-spacing'],
'lines-between-class-members': 'off',
'@typescript-eslint/lines-between-class-members': baseStyleRules['lines-between-class-members'],
'no-array-constructor': 'off',
'@typescript-eslint/no-array-constructor': baseStyleRules['no-array-constructor'],
'no-dupe-class-members': 'off',
'@typescript-eslint/no-dupe-class-members': baseES6Rules['no-dupe-class-members'],
'no-empty-function': 'off',
'@typescript-eslint/no-empty-function': baseBestPracticesRules['no-empty-function'],
'no-extra-parens': 'off',
'@typescript-eslint/no-extra-parens': baseErrorsRules['no-extra-parens'],
'no-extra-semi': 'off',
'@typescript-eslint/no-extra-semi': baseErrorsRules['no-extra-semi'],
// ❌ Fails due to missing parser
// 'no-implied-eval': 'off',
// 'no-new-func': 'off',
// '@typescript-eslint/no-implied-eval': baseBestPracticesRules['no-implied-eval'],
'no-loss-of-precision': 'off',
'@typescript-eslint/no-loss-of-precision': baseErrorsRules['no-loss-of-precision'],
'no-loop-func': 'off',
'@typescript-eslint/no-loop-func': baseBestPracticesRules['no-loop-func'],
'no-magic-numbers': 'off',
'@typescript-eslint/no-magic-numbers': baseBestPracticesRules['no-magic-numbers'],
'no-redeclare': 'off',
'@typescript-eslint/no-redeclare': baseBestPracticesRules['no-redeclare'],
// ESLint variant does not work with TypeScript enums.
'no-shadow': 'off',
'@typescript-eslint/no-shadow': baseVariablesRules['no-shadow'],
'no-throw-literal': 'off',
'@typescript-eslint/no-throw-literal': baseBestPracticesRules['no-throw-literal'],
'no-unused-expressions': 'off',
'@typescript-eslint/no-unused-expressions': baseBestPracticesRules['no-unused-expressions'],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': baseVariablesRules['no-unused-vars'],
// https://erkinekici.com/articles/linting-trap#no-use-before-define
// 'no-use-before-define': 'off',
// '@typescript-eslint/no-use-before-define': baseVariablesRules['no-use-before-define'],
// ESLint variant does not understand TypeScript constructors.
// eslint/eslint/#14118, typescript-eslint/typescript-eslint#873
'no-useless-constructor': 'off',
'@typescript-eslint/no-useless-constructor': baseES6Rules['no-useless-constructor'],
quotes: 'off',
'@typescript-eslint/quotes': baseStyleRules.quotes,
semi: 'off',
'@typescript-eslint/semi': baseStyleRules.semi,
'space-before-function-paren': 'off',
'@typescript-eslint/space-before-function-paren': baseStyleRules['space-before-function-paren'],
'require-await': 'off',
'@typescript-eslint/require-await': baseBestPracticesRules['require-await'],
'no-return-await': 'off',
'@typescript-eslint/return-await': baseBestPracticesRules['no-return-await'],
'space-infix-ops': 'off',
'@typescript-eslint/space-infix-ops': baseStyleRules['space-infix-ops'],
'object-curly-spacing': 'off',
'@typescript-eslint/object-curly-spacing': baseStyleRules['object-curly-spacing'],
'import/extensions': [
baseImportsRules['import/extensions'][0],
baseImportsRules['import/extensions'][1],
{
...baseImportsRules['import/extensions'][2],
ts: 'never',
tsx: 'never',
},
],
// Changes required is not yet implemented:
// 'import/no-extraneous-dependencies': [
// baseImportsRules['import/no-extraneous-dependencies'][0],
// {
// ...baseImportsRules['import/no-extraneous-dependencies'][1],
// devDependencies: baseImportsRules[
// 'import/no-extraneous-dependencies'
// ][1].devDependencies.reduce((result, devDep) => {
// const toAppend = [devDep];
// const devDepWithTs = devDep.replace(/\bjs(x?)\b/g, 'ts$1');
// if (devDepWithTs !== devDep) {
// toAppend.push(devDepWithTs);
// }
// return [...result, ...toAppend];
// }, []),
// },
// ],
};
}
function getAliasesFromTsConfig() { function getAliasesFromTsConfig() {
return Object.keys(tsconfigJson.compilerOptions.paths) return Object.keys(tsconfigJson.compilerOptions.paths)
.map((path) => `${path}*`); .map((path) => `${path}*`);

View File

@@ -1,5 +1,37 @@
# Changelog # Changelog
## 0.12.0 (2023-08-03)
* Improve script/category name validation | [b210aad](https://github.com/undergroundwires/privacy.sexy/commit/b210aaddf26629179f77fe19f62f65d8a0ca2b87)
* Improve touch like hover on devices without mouse | [99e24b4](https://github.com/undergroundwires/privacy.sexy/commit/99e24b4134c461c336f6d08f49d193d853325d31)
* Improve click/touch without unintended interaction | [3233d9b](https://github.com/undergroundwires/privacy.sexy/commit/3233d9b8024dd59600edddef6d017e0089f59a9d)
* Align card icons vertically in cards view | [8608072](https://github.com/undergroundwires/privacy.sexy/commit/8608072bfb52d10a843a86d3d89b14e8b9776779)
* Fix broken npm installation and builds | [924b326](https://github.com/undergroundwires/privacy.sexy/commit/924b326244a175428175e0df3a50685ee5ac2ec6)
* Improve documentation support with markdown | [6067bdb](https://github.com/undergroundwires/privacy.sexy/commit/6067bdb24e6729d2249c9685f4f1c514c3167d91)
* win: add more Visual Studio scripts, support 2022 | [df533ad](https://github.com/undergroundwires/privacy.sexy/commit/df533ad3b19cebdf3454895aa2182bd4184e0360)
* win: add script to remove Widgets | [bbc6156](https://github.com/undergroundwires/privacy.sexy/commit/bbc6156281fb3fd4b66c63dec3f765780fafa855)
* Use line endings based on script language #88 | [6b3f465](https://github.com/undergroundwires/privacy.sexy/commit/6b3f4659df0afe1c99a8af6598df44a33c1f863a)
* win: improve OneDrive removal | [58ed7b4](https://github.com/undergroundwires/privacy.sexy/commit/58ed7b456b3cf11774c83c8c1c04db37ef3058c2)
* Use lowercase in script names and search text | [430537f](https://github.com/undergroundwires/privacy.sexy/commit/430537f70411756bbcaae837964c0223f78581e8)
* Improve manual execution instructions | [7d3670c](https://github.com/undergroundwires/privacy.sexy/commit/7d3670c26d0151ddc43303e8ed5e47715f0e0f00)
* Add multiline support for with expression | [e8d06e0](https://github.com/undergroundwires/privacy.sexy/commit/e8d06e0f3e178a69861e0197f9d1cce9af3958f1)
* Break line in inline codes in documentation | [c1c2f29](https://github.com/undergroundwires/privacy.sexy/commit/c1c2f2925fe88ec1f56bf7655b6b9a10aa3ea024)
* win: add script to increase RSA key exchange #165 | [a2e0921](https://github.com/undergroundwires/privacy.sexy/commit/a2e092190d8eb0fc9ceb8533572f04fff52f097b)
* win: add scripts to downloaded file handling #153 | [e7b816d](https://github.com/undergroundwires/privacy.sexy/commit/e7b816d1564afa98c63291f9d7fd6f3fee92f4ec)
* Drop support for dead browsers | [bf0c55f](https://github.com/undergroundwires/privacy.sexy/commit/bf0c55fa60bf2be070678ba27db14baf13fec511)
* Add support for nested templates | [68a5d69](https://github.com/undergroundwires/privacy.sexy/commit/68a5d698a2ce644ce25754016fb9e9bb642e41a7)
* mac: add scripts to configure Parallels Desktop | [64cca1d](https://github.com/undergroundwires/privacy.sexy/commit/64cca1d9b8946b92e21e86deb6db5612570befb1)
* Rework icon with higher quality and new color | [f4a7ca7](https://github.com/undergroundwires/privacy.sexy/commit/f4a7ca76b885b8346d8a9c32e6269eabc2d8139f)
* Relax and improve code validation | [e819993](https://github.com/undergroundwires/privacy.sexy/commit/e8199932b462380741d9f2d8b6b55485ab16af02)
* Add initial Linux support #150 | [c404dfe](https://github.com/undergroundwires/privacy.sexy/commit/c404dfebe2908bb165279f8279f3f5e805b647d7)
* mac: add script to disable personalized ads | [8b374a3](https://github.com/undergroundwires/privacy.sexy/commit/8b374a37b401699d5056bfd6b735b6a26c395ae0)
* Update dependencies and add npm setup script | [5721796](https://github.com/undergroundwires/privacy.sexy/commit/57217963787a8ab0c71d681c6b1673c484c88226)
* Fix macOS desktop build failure in CI | [5901dc5](https://github.com/undergroundwires/privacy.sexy/commit/5901dc5f11dd29be14c2616fc0ceb45196a43224)
* Change subtitle heading to new slogan | [1e80ee1](https://github.com/undergroundwires/privacy.sexy/commit/1e80ee1fb0208d92943619468dc427853cbe8de7)
* win: add new scripts to disable more telemetry | [298b058](https://github.com/undergroundwires/privacy.sexy/commit/298b058e5c89397db6f759b275442ba05499ac8c)
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.11.4...0.12.0)
## 0.11.4 (2022-03-08) ## 0.11.4 (2022-03-08)
* Improve performance of selecting scripts | [8e96c19](https://github.com/undergroundwires/privacy.sexy/commit/8e96c19126aa4cba6418de5ccaa9e2dcf8faab78) * Improve performance of selecting scripts | [8e96c19](https://github.com/undergroundwires/privacy.sexy/commit/8e96c19126aa4cba6418de5ccaa9e2dcf8faab78)

View File

@@ -47,6 +47,13 @@ You could run other types of tests as well, but they may take longer time and ov
- Build desktop application: `npm run electron:build` - Build desktop application: `npm run electron:build`
- (Re)create icons (see [documentation](../img/README.md)): `npm run create-icons` - (Re)create icons (see [documentation](../img/README.md)): `npm run create-icons`
### Utility Scripts
- Run fresh NPM install: [`./scripts/fresh-npm-install.sh`](../scripts/fresh-npm-install.sh)
- This script provides a clean NPM install, removing existing node modules and optionally the package-lock.json (when run with -n), then installs dependencies and runs unit tests.
- Configure VSCode: [`./scripts/configure-vscode.sh`](../scripts/configure-vscode.sh)
- This script checks and sets the necessary configurations for VSCode in `settings.json` file.
## Recommended extensions ## Recommended extensions
You should use EditorConfig to follow project style. You should use EditorConfig to follow project style.

2499
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "privacy.sexy", "name": "privacy.sexy",
"version": "0.11.4", "version": "0.12.0",
"private": true, "private": true,
"slogan": "Now you have the choice", "slogan": "Now you have the choice",
"description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy 🍑🍆", "description": "Enforce privacy & security best-practices on Windows, macOS and Linux, because privacy is sexy 🍑🍆",
@@ -47,6 +47,7 @@
"vue-property-decorator": "^9.1.2" "vue-property-decorator": "^9.1.2"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.3.2",
"@types/ace": "^0.0.48", "@types/ace": "^0.0.48",
"@types/chai": "^4.3.5", "@types/chai": "^4.3.5",
"@types/file-saver": "^2.0.5", "@types/file-saver": "^2.0.5",
@@ -59,7 +60,7 @@
"@vue/cli-plugin-typescript": "~5.0.8", "@vue/cli-plugin-typescript": "~5.0.8",
"@vue/cli-plugin-unit-mocha": "~5.0.8", "@vue/cli-plugin-unit-mocha": "~5.0.8",
"@vue/cli-service": "~5.0.8", "@vue/cli-service": "~5.0.8",
"@vue/eslint-config-airbnb": "^6.0.0", "@vue/eslint-config-airbnb-with-typescript": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.3", "@vue/eslint-config-typescript": "^11.0.3",
"chai": "^4.3.7", "chai": "^4.3.7",
"cypress": "^12.17.2", "cypress": "^12.17.2",
@@ -86,7 +87,8 @@
"ts-loader": "^9.4.4", "ts-loader": "^9.4.4",
"typescript": "~4.6.2", "typescript": "~4.6.2",
"vue-cli-plugin-electron-builder": "^3.0.0-alpha.4", "vue-cli-plugin-electron-builder": "^3.0.0-alpha.4",
"yaml-lint": "^1.7.0" "yaml-lint": "^1.7.0",
"tslib": "~2.4.0"
}, },
"overrides": { "overrides": {
"vue-cli-plugin-electron-builder": { "vue-cli-plugin-electron-builder": {

74
scripts/configure-vscode.sh Executable file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env bash
# This script ensures that the '.vscode/settings.json' file exists and is configured correctly for ESLint validation on Vue and JavaScript files.
# See https://web.archive.org/web/20230801024405/https://eslint.vuejs.org/user-guide/#visual-studio-code
declare -r SETTINGS_FILE='.vscode/settings.json'
declare -ra CONFIG_KEYS=('vue' 'javascript' 'typescript')
declare -r TEMP_FILE="tmp.$$.json"
main() {
ensure_vscode_directory_exists
create_or_update_settings
}
ensure_vscode_directory_exists() {
local dir_name
dir_name=$(dirname "${SETTINGS_FILE}")
if [[ ! -d ${dir_name} ]]; then
mkdir -p "${dir_name}"
echo "🎉 Created directory: ${dir_name}"
fi
}
create_or_update_settings() {
if [[ ! -f ${SETTINGS_FILE} ]]; then
create_default_settings
else
add_or_update_eslint_validate
fi
}
create_default_settings() {
local default_validate
default_validate=$(printf '%s' "${CONFIG_KEYS[*]}" | jq -R -s -c -M 'split(" ")')
echo "{ \"eslint.validate\": ${default_validate} }" | jq '.' > "${SETTINGS_FILE}"
echo "🎉 Created default ${SETTINGS_FILE}"
}
add_or_update_eslint_validate() {
if ! jq -e '.["eslint.validate"]' "${SETTINGS_FILE}" >/dev/null; then
add_default_eslint_validate
else
update_eslint_validate
fi
}
add_default_eslint_validate() {
jq --argjson keys "$(printf '%s' "${CONFIG_KEYS[*]}" \
| jq -R -s -c 'split(" ")')" '. += {"eslint.validate": $keys}' "${SETTINGS_FILE}" > "${TEMP_FILE}"
replace_and_confirm
echo "🎉 Added default 'eslint.validate' to ${SETTINGS_FILE}"
}
update_eslint_validate() {
local existing_keys
existing_keys=$(jq '.["eslint.validate"]' "${SETTINGS_FILE}")
for key in "${CONFIG_KEYS[@]}"; do
if ! echo "${existing_keys}" | jq 'index("'"${key}"'")' >/dev/null; then
jq '.["eslint.validate"] += ["'"${key}"'"]' "${SETTINGS_FILE}" > "${TEMP_FILE}"
mv "${TEMP_FILE}" "${SETTINGS_FILE}"
echo "🎉 Updated 'eslint.validate' in ${SETTINGS_FILE} for ${key}"
else
echo "⏩️ No updated needed for ${key} ${SETTINGS_FILE}."
fi
done
}
replace_and_confirm() {
if mv "${TEMP_FILE}" "${SETTINGS_FILE}"; then
echo "🎉 Updated ${SETTINGS_FILE}"
fi
}
main

View File

@@ -8,7 +8,7 @@ export class EscapeDoubleQuotes implements IPipe {
return raw; return raw;
} }
return raw.replaceAll('"', '"^""'); return raw.replaceAll('"', '"^""');
/* eslint-disable max-len */ /* eslint-disable vue/max-len */
/* /*
"^"" is the most robust and stable choice. "^"" is the most robust and stable choice.
Other options: Other options:
@@ -28,6 +28,6 @@ export class EscapeDoubleQuotes implements IPipe {
Works when using "^"": `PowerShell -Command ""^""a& c"^"".length"` Works when using "^"": `PowerShell -Command ""^""a& c"^"".length"`
A good explanation: https://stackoverflow.com/a/31413730 A good explanation: https://stackoverflow.com/a/31413730
*/ */
/* eslint-enable max-len */ /* eslint-enable vue/max-len */
} }
} }

View File

@@ -7359,10 +7359,44 @@ functions:
call: call:
function: RunPowerShell function: RunPowerShell
parameters: parameters:
code: Get-WindowsCapability -Online -Name '{{ $capabilityName }}*' | Remove-WindowsCapability -Online code: |-
$capabilityName = '{{ $capabilityName }}'
try {
# Using wildcard for version number handling
$capability = Get-WindowsCapability -Online -Name "$capabilityName*"
if (!$capability) {
Write-Host "Skipping. Capability `"$capabilityName`" is missing."
exit 0
}
if ($capability.State -eq 'NotPresent') {
Write-Host "Skipping. Capability `"$capabilityName`" is missing."
exit 0
}
Write-Host "Removing capability `"$capabilityName`""
Remove-WindowsCapability -Online -Name "$($capability.Name)" -ErrorAction Stop
Write-Host "Successfully removed `"$CapabilityName`""
}
catch {
Write-Error "Failed to remove `"$capabilityName`": $_"
}
revertCode: |- revertCode: |-
$capability = Get-WindowsCapability -Online -Name '{{ $capabilityName }}*' $capabilityName = '{{ $capabilityName }}'
Add-WindowsCapability -Name "$capability.Name" -Online try {
# Using wildcard for version number handling
$capability = Get-WindowsCapability -Online -Name "$capabilityName*"
if (!$capability) {
Write-Error "Failed to find `"$capabilityName`"."
exit 1
}
$result = Add-WindowsCapability -Name $capability.Name -Online -ErrorAction Stop
Write-Host "Successfully added `"$capabilityName`"."
if ($result.RestartNeeded -eq 'Yes') {
Write-Warning "A restart is needed to finish installing `"$capabilityName`"."
}
}
catch {
Write-Error "Failed to add `"$capabilityName`": $_"
}
- -
name: RenameSystemFile name: RenameSystemFile
parameters: parameters:

View File

@@ -1,8 +1,14 @@
<template> <template>
<button class="button" @click="onClicked"> <button
class="button"
type="button"
@click="onClicked"
>
<font-awesome-icon <font-awesome-icon
class="button__icon" class="button__icon"
:icon="[iconPrefix, iconName]" size="2x" /> :icon="[iconPrefix, iconName]"
size="2x"
/>
<div class="button__text">{{text}}</div> <div class="button__text">{{text}}</div>
</button> </button>
</template> </template>

View File

@@ -1,7 +1,7 @@
<template> <template>
<span class="code-wrapper"> <span class="code-wrapper">
<span class="dollar">$</span> <span class="dollar">$</span>
<code><slot></slot></code> <code><slot /></code>
<font-awesome-icon <font-awesome-icon
class="copy-button" class="copy-button"
:icon="['fas', 'copy']" :icon="['fas', 'copy']"

View File

@@ -4,19 +4,21 @@
v-if="this.canRun" v-if="this.canRun"
text="Run" text="Run"
v-on:click="executeCode" v-on:click="executeCode"
icon-prefix="fas" icon-name="play"> icon-prefix="fas"
</IconButton> icon-name="play"
/>
<IconButton <IconButton
:text="this.isDesktopVersion ? 'Save' : 'Download'" :text="this.isDesktopVersion ? 'Save' : 'Download'"
v-on:click="saveCode" v-on:click="saveCode"
icon-prefix="fas" icon-prefix="fas"
:icon-name="this.isDesktopVersion ? 'save' : 'file-download'"> :icon-name="this.isDesktopVersion ? 'save' : 'file-download'"
</IconButton> />
<IconButton <IconButton
text="Copy" text="Copy"
v-on:click="copyCode" v-on:click="copyCode"
icon-prefix="fas" icon-name="copy"> icon-prefix="fas"
</IconButton> icon-name="copy"
/>
<Dialog v-if="this.hasInstructions" ref="instructionsDialog"> <Dialog v-if="this.hasInstructions" ref="instructionsDialog">
<InstructionList :data="this.instructions" /> <InstructionList :data="this.instructions" />
</Dialog> </Dialog>

View File

@@ -5,7 +5,7 @@
<div <div
:id="editorId" :id="editorId"
class="code-area" class="code-area"
></div> />
</Responsive> </Responsive>
</template> </template>

View File

@@ -1,7 +1,10 @@
<template> <template>
<span> <!-- Parent wrapper allows adding content inside with CSS without making it clickable --> <span> <!-- Parent wrapper allows adding content inside with CSS without making it clickable -->
<span <span
v-bind:class="{ 'disabled': !enabled, 'enabled': enabled}" v-bind:class="{
disabled: !enabled,
enabled: enabled,
}"
v-non-collapsing v-non-collapsing
@click="enabled && onClicked()">{{label}}</span> @click="enabled && onClicked()">{{label}}</span>
</span> </span>

View File

@@ -4,32 +4,39 @@
label="None" label="None"
:enabled="this.currentSelection !== SelectionType.None" :enabled="this.currentSelection !== SelectionType.None"
@click="selectType(SelectionType.None)" @click="selectType(SelectionType.None)"
v-tooltip=" 'Deselect all selected scripts.<br/>' + v-tooltip="
'💡 Good start to dive deeper into tweaks and select only what you want.'" 'Deselect all selected scripts.<br/>'
+ '💡 Good start to dive deeper into tweaks and select only what you want.'
"
/> />
<MenuOptionListItem <MenuOptionListItem
label="Standard" label="Standard"
:enabled="this.currentSelection !== SelectionType.Standard" :enabled="this.currentSelection !== SelectionType.Standard"
@click="selectType(SelectionType.Standard)" @click="selectType(SelectionType.Standard)"
v-tooltip=" '🛡️ Balanced for privacy and functionality.<br/>' + v-tooltip="
'OS and applications will function normally.<br/>' + '🛡️ Balanced for privacy and functionality.<br/>'
'💡 Recommended for everyone'" + 'OS and applications will function normally.<br/>'
+ '💡 Recommended for everyone'"
/> />
<MenuOptionListItem <MenuOptionListItem
label="Strict" label="Strict"
:enabled="this.currentSelection !== SelectionType.Strict" :enabled="this.currentSelection !== SelectionType.Strict"
@click="selectType(SelectionType.Strict)" @click="selectType(SelectionType.Strict)"
v-tooltip=" '🚫 Stronger privacy, disables risky functions that may leak your data.<br/>' + v-tooltip="
'🚫 Stronger privacy, disables risky functions that may leak your data.<br/>'
+ '⚠️ Double check to remove scripts where you would trade functionality for privacy<br/>' + '⚠️ Double check to remove scripts where you would trade functionality for privacy<br/>'
+ '💡 Recommended for daily users that prefers more privacy over non-essential functions'" + '💡 Recommended for daily users that prefers more privacy over non-essential functions'
"
/> />
<MenuOptionListItem <MenuOptionListItem
label="All" label="All"
:enabled="this.currentSelection !== SelectionType.All" :enabled="this.currentSelection !== SelectionType.All"
@click="selectType(SelectionType.All)" @click="selectType(SelectionType.All)"
v-tooltip=" '🔒 Strongest privacy, disabling any functionality that may leak your data.<br/>' v-tooltip="
'🔒 Strongest privacy, disabling any functionality that may leak your data.<br/>'
+ '🛑 Not designed for daily users, it will break important functionalities.<br/>' + '🛑 Not designed for daily users, it will break important functionalities.<br/>'
+ '💡 Only recommended for extreme use-cases like crime labs where no leak is acceptable'" + '💡 Only recommended for extreme use-cases like crime labs where no leak is acceptable'
"
/> />
</MenuOptionList> </MenuOptionList>
</template> </template>

View File

@@ -1,7 +1,8 @@
<template> <template>
<MenuOptionList> <MenuOptionList>
<MenuOptionListItem <MenuOptionListItem
v-for="os in this.allOses" :key="os.name" v-for="os in this.allOses"
:key="os.name"
:enabled="currentOs !== os.os" :enabled="currentOs !== os.os"
@click="changeOs(os.os)" @click="changeOs(os.os)"
:label="os.name" :label="os.name"

View File

@@ -3,7 +3,8 @@
label="View" label="View"
class="part"> class="part">
<MenuOptionListItem <MenuOptionListItem
v-for="view in this.viewOptions" :key="view.type" v-for="view in this.viewOptions"
:key="view.type"
:label="view.displayName" :label="view.displayName"
:enabled="currentView !== view.type" :enabled="currentView !== view.type"
@click="setView(view.type)" @click="setView(view.type)"

View File

@@ -1,16 +1,19 @@
<template> <template>
<div class="slider" v-bind:style="{ <div
class="slider"
v-bind:style="{
'--vertical-margin': this.verticalMargin, '--vertical-margin': this.verticalMargin,
'--first-min-width': this.firstMinWidth, '--first-min-width': this.firstMinWidth,
'--first-initial-width': this.firstInitialWidth, '--first-initial-width': this.firstInitialWidth,
'--second-min-width': this.secondMinWidth, '--second-min-width': this.secondMinWidth,
}"> }"
>
<div class="first" ref="firstElement"> <div class="first" ref="firstElement">
<slot name="first"></slot> <slot name="first" />
</div> </div>
<Handle class="handle" @resized="onResize($event)" /> <Handle class="handle" @resized="onResize($event)" />
<div class="second"> <div class="second">
<slot name="second"></slot> <slot name="second" />
</div> </div>
</div> </div>
</template> </template>

View File

@@ -1,9 +1,13 @@
<template> <template>
<div class="scripts"> <div class="scripts">
<TheScriptsMenu v-on:viewChanged="currentView = $event" /> <TheScriptsMenu v-on:viewChanged="currentView = $event" />
<HorizontalResizeSlider class="row" <HorizontalResizeSlider
verticalMargin="15px" firstInitialWidth="55%" class="row"
firstMinWidth="20%" secondMinWidth="20%"> verticalMargin="15px"
firstInitialWidth="55%"
firstMinWidth="20%"
secondMinWidth="20%"
>
<template v-slot:first> <template v-slot:first>
<TheScriptsView :currentView="currentView" /> <TheScriptsView :currentView="currentView" />
</template> </template>

View File

@@ -9,21 +9,24 @@
<span v-if="width >= 750">big</span> <span v-if="width >= 750">big</span>
</div> </div>
--> -->
<div v-if="categoryIds != null && categoryIds.length > 0" class="cards"> <div
v-if="categoryIds != null && categoryIds.length > 0"
class="cards"
>
<CardListItem <CardListItem
class="card" class="card"
v-bind:class="{ v-bind:class="{
'small-screen': width <= 500, 'small-screen': width <= 500,
'medium-screen': width > 500 && width < 750, 'medium-screen': width > 500 && width < 750,
'big-screen': width >= 750 'big-screen': width >= 750,
}" }"
v-for="categoryId of categoryIds" v-for="categoryId of categoryIds"
:data-category="categoryId" :data-category="categoryId"
v-bind:key="categoryId" v-bind:key="categoryId"
:categoryId="categoryId" :categoryId="categoryId"
:activeCategoryId="activeCategoryId" :activeCategoryId="activeCategoryId"
v-on:selected="onSelected(categoryId, $event)"> v-on:selected="onSelected(categoryId, $event)"
</CardListItem> />
</div> </div>
<div v-else class="error">Something went bad 😢</div> <div v-else class="error">Something went bad 😢</div>
</Responsive> </Responsive>

View File

@@ -1,10 +1,11 @@
<template> <template>
<div class="card" <div
class="card"
v-on:click="onSelected(!isExpanded)" v-on:click="onSelected(!isExpanded)"
v-bind:class="{ v-bind:class="{
'is-collapsed': !isExpanded, 'is-collapsed': !isExpanded,
'is-inactive': activeCategoryId && activeCategoryId != categoryId, 'is-inactive': activeCategoryId && activeCategoryId != categoryId,
'is-expanded': isExpanded 'is-expanded': isExpanded,
}" }"
ref="cardElement"> ref="cardElement">
<div class="card__inner"> <div class="card__inner">
@@ -34,10 +35,13 @@
</div> </div>
<div class="card__expander" v-on:click.stop> <div class="card__expander" v-on:click.stop>
<div class="card__expander__content"> <div class="card__expander__content">
<ScriptsTree :categoryId="categoryId"></ScriptsTree> <ScriptsTree :categoryId="categoryId" />
</div> </div>
<div class="card__expander__close-button"> <div class="card__expander__close-button">
<font-awesome-icon :icon="['fas', 'times']" v-on:click="onSelected(false)"/> <font-awesome-icon
:icon="['fas', 'times']"
v-on:click="onSelected(false)"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -82,7 +86,7 @@ export default class CardListItem extends StatefulVue {
} }
@Watch('activeCategoryId') @Watch('activeCategoryId')
public async onActiveCategoryChanged(value: |number) { public async onActiveCategoryChanged(value?: number) {
this.isExpanded = value === this.categoryId; this.isExpanded = value === this.categoryId;
} }
@@ -96,7 +100,7 @@ export default class CardListItem extends StatefulVue {
} }
@Watch('categoryId') @Watch('categoryId')
public async updateState(value: |number) { public async updateState(value?: number) {
const context = await this.getCurrentContext(); const context = await this.getCurrentContext();
const category = !value ? undefined : context.state.collection.findCategory(value); const category = !value ? undefined : context.state.collection.findCategory(value);
this.cardTitle = category ? category.name : undefined; this.cardTitle = category ? category.name : undefined;

View File

@@ -7,8 +7,7 @@
:filterPredicate="filterPredicate" :filterPredicate="filterPredicate"
:filterText="filterText" :filterText="filterText"
v-on:nodeSelected="toggleNodeSelection($event)" v-on:nodeSelected="toggleNodeSelection($event)"
> />
</SelectableTree>
</span> </span>
<span v-else>Nooo 😢</span> <span v-else>Nooo 😢</span>
</span> </span>

View File

@@ -13,10 +13,15 @@
<div <div
v-if="docs && docs.length > 0 && isExpanded" v-if="docs && docs.length > 0 && isExpanded"
class="docs" class="docs"
v-bind:class="{ 'docs-expanded': isExpanded, 'docs-collapsed': !isExpanded }" > v-bind:class="{ 'docs-expanded': isExpanded, 'docs-collapsed': !isExpanded }"
>
<DocumentationText <DocumentationText
:docs="docs" class="text" :docs="docs"
v-bind:class="{ 'expanded': isExpanded, 'collapsed': !isExpanded }" /> class="text"
v-bind:class="{
expanded: isExpanded,
collapsed: !isExpanded,
}" />
</div> </div>
</div> </div>
</template> </template>

View File

@@ -3,8 +3,7 @@
class="documentation-text" class="documentation-text"
v-html="renderedText" v-html="renderedText"
v-on:click.stop v-on:click.stop
> />
</div>
</template> </template>
<script lang="ts"> <script lang="ts">

View File

@@ -1,6 +1,8 @@
<template> <template>
<div class="checkbox-switch" > <div class="checkbox-switch">
<input type="checkbox" class="input-checkbox" <input
type="checkbox"
class="input-checkbox"
v-model="isReverted" v-model="isReverted"
@change="onRevertToggled()" @change="onRevertToggled()"
v-on:click.stop> v-on:click.stop>

View File

@@ -1,13 +1,14 @@
<template> <template>
<span> <span>
<span v-if="initialLiquorTreeNodes != null && initialLiquorTreeNodes.length > 0"> <span v-if="initialLiquorTreeNodes != null && initialLiquorTreeNodes.length > 0">
<tree :options="liquorTreeOptions" <tree
:options="liquorTreeOptions"
:data="initialLiquorTreeNodes" :data="initialLiquorTreeNodes"
v-on:node:checked="nodeSelected($event)" v-on:node:checked="nodeSelected($event)"
v-on:node:unchecked="nodeSelected($event)" v-on:node:unchecked="nodeSelected($event)"
ref="treeElement" ref="treeElement"
> >
<span class="tree-text" slot-scope="{ node }" > <span class="tree-text" slot-scope="{ node }">
<Node :data="convertExistingToNode(node)" /> <Node :data="convertExistingToNode(node)" />
</span> </span>
</tree> </tree>
@@ -86,7 +87,7 @@ export default class SelectableTree extends Vue { // Stateless to make it easier
} }
@Watch('filterText', { immediate: true }) @Watch('filterText', { immediate: true })
public async updateFilterText(filterText: |string) { public async updateFilterText(filterText?: string) {
const api = await this.getLiquorTreeApi(); const api = await this.getLiquorTreeApi();
if (!filterText) { if (!filterText) {
api.clearFilter(); api.clearFilter();
@@ -111,7 +112,7 @@ export default class SelectableTree extends Vue { // Stateless to make it easier
private async getLiquorTreeApi(): Promise<ILiquorTree> { private async getLiquorTreeApi(): Promise<ILiquorTree> {
const accessor = (): ILiquorTree => { const accessor = (): ILiquorTree => {
const uiElement = this.$refs.treeElement; const uiElement = this.$refs.treeElement;
type TreeElement = typeof uiElement & {tree: ILiquorTree}; type TreeElement = typeof uiElement & { tree: ILiquorTree };
return uiElement ? (uiElement as TreeElement).tree : undefined; return uiElement ? (uiElement as TreeElement).tree : undefined;
}; };
const treeElement = await tryUntilDefined(accessor, 5, 20); // Wait for it to render const treeElement = await tryUntilDefined(accessor, 5, 20); // Wait for it to render

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="scripts"> <div class="scripts">
<div v-if="!isSearching"> <div v-if="!isSearching">
<CardList v-if="currentView === ViewType.Cards"/> <CardList v-if="currentView === ViewType.Cards" />
<div class="tree" v-else-if="currentView === ViewType.Tree"> <div class="tree" v-else-if="currentView === ViewType.Tree">
<ScriptsTree /> <ScriptsTree />
</div> </div>
@@ -9,18 +9,18 @@
<div v-else> <!-- Searching --> <div v-else> <!-- Searching -->
<div class="search"> <div class="search">
<div class="search__query"> <div class="search__query">
<div>Searching for "{{this.searchQuery | threeDotsTrim}}"</div> <div>Searching for "{{this.searchQuery | threeDotsTrim }}"</div>
<div class="search__query__close-button"> <div class="search__query__close-button">
<font-awesome-icon <font-awesome-icon
:icon="['fas', 'times']" :icon="['fas', 'times']"
v-on:click="clearSearchQuery()"/> v-on:click="clearSearchQuery()" />
</div> </div>
</div> </div>
<div v-if="!searchHasMatches" class="search-no-matches"> <div v-if="!searchHasMatches" class="search-no-matches">
<div>Sorry, no matches for "{{this.searchQuery | threeDotsTrim}}" 😞</div> <div>Sorry, no matches for "{{this.searchQuery | threeDotsTrim }}" 😞</div>
<div> <div>
Feel free to extend the scripts Feel free to extend the scripts
<a :href="repositoryUrl" target="_blank" class="child github" >here</a> <a :href="repositoryUrl" target="_blank" class="child github">here</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -5,10 +5,13 @@
height="auto"> height="auto">
<div class="dialog"> <div class="dialog">
<div class="dialog__content"> <div class="dialog__content">
<slot></slot> <slot />
</div> </div>
<div class="dialog__close-button"> <div class="dialog__close-button">
<font-awesome-icon :icon="['fas', 'times']" @click="$modal.hide(name)"/> <font-awesome-icon
:icon="['fas', 'times']"
@click="$modal.hide(name)"
/>
</div> </div>
</div> </div>
</modal> </modal>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div ref="containerElement" class="container"> <div ref="containerElement" class="container">
<slot ref="containerElement"></slot> <slot ref="containerElement" />
</div> </div>
</template> </template>

View File

@@ -3,7 +3,7 @@
class="container" class="container"
v-bind:class="{ v-bind:class="{
'container-unsupported': !hasCurrentOsDesktopVersion, 'container-unsupported': !hasCurrentOsDesktopVersion,
'container-supported': hasCurrentOsDesktopVersion 'container-supported': hasCurrentOsDesktopVersion,
}"> }">
<span class="description"> <span class="description">
<font-awesome-icon class="description__icon" :icon="['fas', 'desktop']" /> <font-awesome-icon class="description__icon" :icon="['fas', 'desktop']" />

View File

@@ -1,9 +1,10 @@
<template> <template>
<span class="url"> <span class="url">
<a :href="downloadUrl" <a
:href="downloadUrl"
v-bind:class="{ v-bind:class="{
'url__active': hasCurrentOsDesktopVersion && isCurrentOs, url__active: hasCurrentOsDesktopVersion && isCurrentOs,
'url__inactive': hasCurrentOsDesktopVersion && !isCurrentOs, url__inactive: hasCurrentOsDesktopVersion && !isCurrentOs,
}">{{ operatingSystemName }}</a> }">{{ operatingSystemName }}</a>
</span> </span>
</template> </template>

View File

@@ -17,14 +17,18 @@
</div> </div>
<div class="line"> <div class="line">
<div class="line__emoji">🤖</div> <div class="line__emoji">🤖</div>
<div>All transparent: Deployed automatically from the master branch <div>
of the <a :href="repositoryUrl" target="_blank">source code</a> with no changes.</div> All transparent: Deployed automatically from the master branch
of the <a :href="repositoryUrl" target="_blank">source code</a> with no changes.
</div>
</div> </div>
<div v-if="!isDesktop" class="line"> <div v-if="!isDesktop" class="line">
<div class="line__emoji">📈</div> <div class="line__emoji">📈</div>
<div>Basic <a href="https://aws.amazon.com/cloudfront/reporting/" target="_blank">CDN statistics</a> <div>
Basic <a href="https://aws.amazon.com/cloudfront/reporting/" target="_blank">CDN statistics</a>
are collected by AWS but they cannot be traced to you or your behavior. are collected by AWS but they cannot be traced to you or your behavior.
You can download the offline version if you don't want any CDN data collection.</div> You can download the offline version if you don't want any CDN data collection.
</div>
</div> </div>
<div class="line"> <div class="line">
<div class="line__emoji">🎉</div> <div class="line__emoji">🎉</div>

View File

@@ -1,6 +1,6 @@
<template> <template>
<div id="container"> <div id="container">
<h1 class="child title" >{{ title }}</h1> <h1 class="child title">{{ title }}</h1>
<h2 class="child subtitle">Now you have the choice</h2> <h2 class="child subtitle">Now you have the choice</h2>
</div> </div>
</template> </template>

View File

@@ -1,8 +1,11 @@
<template> <template>
<div class="search" v-non-collapsing> <div class="search" v-non-collapsing>
<input type="search" class="search-term" <input
type="search"
class="search-term"
:placeholder="searchPlaceHolder" :placeholder="searchPlaceHolder"
v-model="searchQuery" > v-model="searchQuery"
>
<div class="icon-wrapper"> <div class="icon-wrapper">
<font-awesome-icon :icon="['fas', 'search']" /> <font-awesome-icon :icon="['fas', 'search']" />
</div> </div>
@@ -26,7 +29,7 @@ export default class TheSearchBar extends StatefulVue {
public searchQuery = ''; public searchQuery = '';
@Watch('searchQuery') @Watch('searchQuery')
public async updateFilter(newFilter: |string) { public async updateFilter(newFilter?: string) {
const context = await this.getCurrentContext(); const context = await this.getCurrentContext();
const { filter } = context.state; const { filter } = context.state;
if (!newFilter) { if (!newFilter) {