Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd41af466f | ||
|
|
970221b996 | ||
|
|
15004ff1f1 | ||
|
|
65226f3984 | ||
|
|
b0a7d0b53b | ||
|
|
ee43fd92a0 | ||
|
|
cf39e6d254 | ||
|
|
1260eea690 | ||
|
|
45a3669443 | ||
|
|
c9b91f6d8f | ||
|
|
9a6b903b92 | ||
|
|
7661575573 | ||
|
|
f1abd7682f | ||
|
|
575636e6b7 | ||
|
|
daa997b21b | ||
|
|
5934b17283 | ||
|
|
d7de420d5c | ||
|
|
df273f7f63 | ||
|
|
67b2d1c11c | ||
|
|
15353d0e25 | ||
|
|
f1e21babbf | ||
|
|
34b8822ac8 | ||
|
|
73e0520de7 | ||
|
|
fbc3b109b9 | ||
|
|
229c13a195 | ||
|
|
d7f9ef1cbe | ||
|
|
7930bef48c | ||
|
|
8b0e47da38 | ||
|
|
2316e3fb68 | ||
|
|
4015e2ccd8 | ||
|
|
cf907d029a | ||
|
|
79a6c8b2ef | ||
|
|
c318bd301a | ||
|
|
86a2b2fda0 | ||
|
|
8a8b7319d5 | ||
|
|
2428de23ee | ||
|
|
7ec889e759 | ||
|
|
9d009c40dd | ||
|
|
663d63bde0 | ||
|
|
6b83dcbf8f | ||
|
|
72e925fb6f | ||
|
|
c299e95bc6 | ||
|
|
2e40605d59 | ||
|
|
3455a2ca6c | ||
|
|
6fe858d86a | ||
|
|
7cc161c828 | ||
|
|
e14bf2bfa0 | ||
|
|
34672414c3 | ||
|
|
f7557bcc0f | ||
|
|
e4b6cdfb18 | ||
|
|
8cd3352017 | ||
|
|
c4ec6a1445 | ||
|
|
b3117c27f2 | ||
|
|
54ba4dbb0b | ||
|
|
a744415eb2 | ||
|
|
55f936fee9 | ||
|
|
d9e44e2574 | ||
|
|
52d4313156 | ||
|
|
c2b531e968 | ||
|
|
ab7d617886 | ||
|
|
b247b12c3f | ||
|
|
c26bc209eb | ||
|
|
ad1872e7cd | ||
|
|
29c7704e0b | ||
|
|
e41e40c5bf | ||
|
|
31e08d231d | ||
|
|
45b8dd972b | ||
|
|
4e72673373 | ||
|
|
92c3dd9232 | ||
|
|
2c5ab3ea7d | ||
|
|
ffa279f3df | ||
|
|
89dddfbb23 | ||
|
|
cfedcd724c | ||
|
|
fd28eaad06 | ||
|
|
8ce06facbd | ||
|
|
1a9db31c77 | ||
|
|
ac70b063b8 | ||
|
|
d0019c2c9b | ||
|
|
4c68408f1e | ||
|
|
1072505219 | ||
|
|
07fc555324 | ||
|
|
50fb29038a | ||
|
|
3785c623f8 | ||
|
|
14be3017c5 | ||
|
|
978bab0b81 | ||
|
|
d9d7f62d81 | ||
|
|
11e0613165 | ||
|
|
77c3d2bbb8 | ||
|
|
784a67afff | ||
|
|
19a092dd31 | ||
|
|
4c2f74949b | ||
|
|
a3fc3782ef | ||
|
|
cdc93f032a | ||
|
|
7dd15ed064 | ||
|
|
d169434157 | ||
|
|
6efed72bf2 | ||
|
|
15db311801 | ||
|
|
82d509129b | ||
|
|
939d838e35 | ||
|
|
6de4ce58c4 | ||
|
|
ee66196d9a | ||
|
|
3c13a9e837 | ||
|
|
22b23a9ece | ||
|
|
4ae385b7fc | ||
|
|
d9abc7f0b2 | ||
|
|
1f19b2528a | ||
|
|
1f11c39773 | ||
|
|
b6ccb5927a | ||
|
|
1d465ee318 | ||
|
|
3ab48b1cf5 | ||
|
|
de4ac978bd | ||
|
|
8df5faf4ef | ||
|
|
99a2035fdb | ||
|
|
a0d61728ea | ||
|
|
312bf6102c |
36
.github/ISSUE_TEMPLATE/1-bug-report-scripts.md
vendored
Normal file
36
.github/ISSUE_TEMPLATE/1-bug-report-scripts.md
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
---
|
||||||
|
name: Bug report (script bug or unexpected script behavior)
|
||||||
|
about: Create a bug report for generated scripts to help privacy.sexy improve
|
||||||
|
labels: bug
|
||||||
|
title: '[BUG]: '
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Thank you for reporting an issue with generated script(s).
|
||||||
|
Please fill in as much of the template below as you're able.
|
||||||
|
As a small open source project with small community, it can sometimes take a long time for issues to be addressed so please be patient.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Describe the bug
|
||||||
|
|
||||||
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
|
### OS
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Which OS are you using? What version of OS you were using?
|
||||||
|
On Windows you can find it using "Start button" > "Settings" > "System" > "About".
|
||||||
|
On macOS you can find it using "Apple menu (top left corner)" > "About This Mac".
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
|
||||||
|
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||||
|
|
||||||
|
### Scripts
|
||||||
|
|
||||||
|
<!-- Which scripts did you execute? If applicable, please paste the executed scripts or attach the generated privacy.sexy file . -->
|
||||||
|
|
||||||
|
### Additional information
|
||||||
|
|
||||||
|
<!-- Add any other context about the problem here. -->
|
||||||
52
.github/ISSUE_TEMPLATE/2-bug-report-generic.md
vendored
Normal file
52
.github/ISSUE_TEMPLATE/2-bug-report-generic.md
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
---
|
||||||
|
name: Bug report (unrelated to generated scripts)
|
||||||
|
about: Create a bug report that's not related to generated scripts to help privacy.sexy improve
|
||||||
|
labels: bug
|
||||||
|
title: '[BUG]: '
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Thank you for reporting an issue.
|
||||||
|
Please fill in as much of the template below as you're able.
|
||||||
|
As a small open source project with small community, it can sometimes take a long time for issues to be addressed so please be patient.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Describe the bug
|
||||||
|
|
||||||
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
|
### To Reproduce
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Expected behavior
|
||||||
|
|
||||||
|
<!--
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Distribution
|
||||||
|
|
||||||
|
<!--
|
||||||
|
If applicable, mention how you were using privacy.sexy when the bug was encountered:
|
||||||
|
- Web (on Desktop or mobile?)
|
||||||
|
- Or desktop (Windows, macOS or Linux?)
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Add any other context about the problem here.
|
||||||
|
-->
|
||||||
27
.github/ISSUE_TEMPLATE/3-feature_request.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/3-feature_request.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for privacy.sexy
|
||||||
|
labels: enhancement
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Thank you for suggesting an idea to make privacy better. 🤗
|
||||||
|
|
||||||
|
Please fill in as much of the template below as you're able.
|
||||||
|
-->
|
||||||
|
|
||||||
|
### Problem Description
|
||||||
|
|
||||||
|
<!-- Please add a clear and concise description of the problem you are seeking to solve with this feature request. Ex. I'm always frustrated when [...] -->
|
||||||
|
|
||||||
|
### Proposed solution
|
||||||
|
|
||||||
|
<!-- Describe the solution you'd like in a clear and concise manner. -->
|
||||||
|
|
||||||
|
### Alternatives considered
|
||||||
|
|
||||||
|
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||||
|
|
||||||
|
### Additional information
|
||||||
|
|
||||||
|
<!-- Add any other context or screenshots about the feature request here. -->
|
||||||
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: true
|
||||||
2
.github/workflows/deploy-desktop.yaml
vendored
2
.github/workflows/deploy-desktop.yaml
vendored
@@ -10,6 +10,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [macos, ubuntu, windows]
|
os: [macos, ubuntu, windows]
|
||||||
|
fail-fast: false # So publish runs for other OSes if one fails
|
||||||
runs-on: ${{ matrix.os }}-latest
|
runs-on: ${{ matrix.os }}-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@@ -30,3 +31,4 @@ jobs:
|
|||||||
run: npm run electron:build -- -p always # https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/recipes.html#upload-release-to-github
|
run: npm run electron:build -- -p always # https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/recipes.html#upload-release-to-github
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
EP_GH_IGNORE_TIME: true # Otherwise publishing fails if GitHub release is more than 2 hours old https://github.com/electron-userland/electron-builder/issues/2074
|
||||||
2
.github/workflows/deploy-site.yaml
vendored
2
.github/workflows/deploy-site.yaml
vendored
@@ -23,7 +23,7 @@ jobs:
|
|||||||
--secret-access-key ${{secrets.AWS_DEPLOYMENT_USER_SECRET_ACCESS_KEY}} \
|
--secret-access-key ${{secrets.AWS_DEPLOYMENT_USER_SECRET_ACCESS_KEY}} \
|
||||||
--region us-east-1 \
|
--region us-east-1 \
|
||||||
&& \
|
&& \
|
||||||
echo "::set-env name=SESSION_NAME::${{github.actor}}-${{github.event_name}}-$(echo ${{github.sha}} | cut -c1-8)"
|
echo "SESSION_NAME=${{github.actor}}-${{github.event_name}}-$(echo ${{github.sha}} | cut -c1-8)" >> $GITHUB_ENV
|
||||||
working-directory: aws
|
working-directory: aws
|
||||||
-
|
-
|
||||||
name: "Infrastructure: Deploy IAM stack"
|
name: "Infrastructure: Deploy IAM stack"
|
||||||
|
|||||||
2
.github/workflows/quality-checks.yaml
vendored
2
.github/workflows/quality-checks.yaml
vendored
@@ -1,6 +1,6 @@
|
|||||||
name: Quality checks
|
name: Quality checks
|
||||||
|
|
||||||
on: push
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
|
|||||||
2
.github/workflows/security-checks.yaml
vendored
2
.github/workflows/security-checks.yaml
vendored
@@ -2,6 +2,8 @@ name: Security checks
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
pull_request:
|
||||||
|
paths: [ '/package.json', '/package-lock.json' ] # Allow PRs to be green if they do not introduce dependency change
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * 0'
|
- cron: '0 0 * * 0'
|
||||||
|
|
||||||
|
|||||||
7
.github/workflows/test.yaml
vendored
7
.github/workflows/test.yaml
vendored
@@ -1,10 +1,13 @@
|
|||||||
name: Test
|
name: Test
|
||||||
|
|
||||||
on: push
|
on: [ push, pull_request ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
run-tests:
|
run-tests:
|
||||||
runs-on: ubuntu-latest
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [macos, ubuntu, windows]
|
||||||
|
runs-on: ${{ matrix.os }}-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,5 @@
|
|||||||
node_modules
|
node_modules
|
||||||
/dist
|
dist/
|
||||||
.vs
|
.vs
|
||||||
.vscode
|
.vscode
|
||||||
#Electron-builder output
|
#Electron-builder output
|
||||||
|
|||||||
400
CHANGELOG.md
400
CHANGELOG.md
@@ -1,125 +1,279 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.9.2 (2021-02-13)
|
||||||
|
|
||||||
|
* do not compile with unused locals vuejs/vetur#1063 | [73e0520](https://github.com/undergroundwires/privacy.sexy/commit/73e0520de70cdbaf0ecdc6e9be5e85f003fcfb79)
|
||||||
|
* fix wrong path for NvTelemtry file in NVIDIA script | [34b8822](https://github.com/undergroundwires/privacy.sexy/commit/34b8822ac821acb47e483e21b57e380551bcf455)
|
||||||
|
* refactor event handling to consume base class for lifecycling | [f1e21ba](https://github.com/undergroundwires/privacy.sexy/commit/f1e21babbfaac21903594a37e30163bfe3338279)
|
||||||
|
* make compiler throw if a function call includes an unexpected parameter | [15353d0](https://github.com/undergroundwires/privacy.sexy/commit/15353d0e2513c89ee4ffd9d9c5e9e83ef69b96b6)
|
||||||
|
* refactor vscode configuration scripts using functions #41 | [67b2d1c](https://github.com/undergroundwires/privacy.sexy/commit/67b2d1c11cd5b131dff93a4437db79d96ed8b3dc)
|
||||||
|
* refactor state handling to make application available independent of the state | [df273f7](https://github.com/undergroundwires/privacy.sexy/commit/df273f7f635ab156ac51a8dfb3fec66c4979f1c4)
|
||||||
|
* add test to ensure correct shared functions are being parsed | [d7de420](https://github.com/undergroundwires/privacy.sexy/commit/d7de420d5c91bd9ce64880cd4a4391ad3a0a5401)
|
||||||
|
* refactor and add tests for NonCollapsingDirective | [5934b17](https://github.com/undergroundwires/privacy.sexy/commit/5934b1728328c3b2ece1597b74dd87477d162175)
|
||||||
|
* add GitHub issue templates | [daa997b](https://github.com/undergroundwires/privacy.sexy/commit/daa997b21b624d133c6f5e4cd6b70214588f9144)
|
||||||
|
* correct the typo in application.md (#60) | [575636e](https://github.com/undergroundwires/privacy.sexy/commit/575636e6b728a2bdd1a9bd72c57bbf2752f10887)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.9.1...0.9.2)
|
||||||
|
|
||||||
|
## 0.9.1 (2021-01-23)
|
||||||
|
|
||||||
|
* in CI/CD, allow publishing to github if release is more than 2 hours old electron-userland/electron-builder#2074 | [cf907d0](https://github.com/undergroundwires/privacy.sexy/commit/cf907d029a6d80682ba78ec887a9c4fab639db51)
|
||||||
|
* in CI/CD, publish packages for other OSes if single one fails | [4015e2c](https://github.com/undergroundwires/privacy.sexy/commit/4015e2ccd8492e0693365b70fbfe3bd0ac7a6ea2)
|
||||||
|
* specify desktop publish targets as defaults (may) change | [2316e3f](https://github.com/undergroundwires/privacy.sexy/commit/2316e3fb6867e5d765eafcf675b77f88bd2a0f52)
|
||||||
|
* fix selection state indicator on cards not showing up | [8b0e47d](https://github.com/undergroundwires/privacy.sexy/commit/8b0e47da38c49cfe2645d7d25970c448ecd200f8)
|
||||||
|
* transpile using babel for legacy browser support | [7930bef](https://github.com/undergroundwires/privacy.sexy/commit/7930bef48c4e9a4fe0823673958ed8377f5ee533)
|
||||||
|
* fix node APIs no longer working on desktop nklayman/vue-cli-plugin-electron-builder#610, nklayman/vue-cli-plugin-electron-builder#742 | [d7f9ef1](https://github.com/undergroundwires/privacy.sexy/commit/d7f9ef1cbebe911aa19f29be8c5fa9360550793e)
|
||||||
|
* improve explanation for selections | [229c13a](https://github.com/undergroundwires/privacy.sexy/commit/229c13a195dee92e4a31731b7b41c319273a16f1)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.9.0...0.9.1)
|
||||||
|
|
||||||
|
## 0.9.0 (2021-01-15)
|
||||||
|
|
||||||
|
* refactor application.yaml to become an os definition #40 | [f7557bc](https://github.com/undergroundwires/privacy.sexy/commit/f7557bcc0faf44e8395b68c7eb14c5f715f07b92)
|
||||||
|
* refactor folders to move "/state" (IApplicationState) inside "/context" (IApplicationContext) | [3467241](https://github.com/undergroundwires/privacy.sexy/commit/34672414c3e0757173036e351df0a73c1708ded5)
|
||||||
|
* add scripts to prevent family safety monitoring | [e14bf2b](https://github.com/undergroundwires/privacy.sexy/commit/e14bf2bfa03efe28ff39942c9891fca605f13eed)
|
||||||
|
* rework Cortana scripts to remove duplicates, better document and support Windows version 2004/2009 #43 | [7cc161c](https://github.com/undergroundwires/privacy.sexy/commit/7cc161c828a3fa49f6f254e31834a95a502b7aa2)
|
||||||
|
* rename Application to CategoryCollection #40 | [6fe858d](https://github.com/undergroundwires/privacy.sexy/commit/6fe858d86aeb0f8b6d5ae5c2a5e3c25ff32e5f6f)
|
||||||
|
* add script to clean previous windows installation #35 | [3455a2c](https://github.com/undergroundwires/privacy.sexy/commit/3455a2ca6ce13f9b0e866d88532a5c3d6de30d4d)
|
||||||
|
* refactor to allow switching ICategoryCollection context #40 | [2e40605](https://github.com/undergroundwires/privacy.sexy/commit/2e40605d59eb764768457c6af561487e7ff09777)
|
||||||
|
* fix typo causing uninstalling capabilities to fail #51 | [c299e95](https://github.com/undergroundwires/privacy.sexy/commit/c299e95bc6d588317b69a9efcf5752ff5c9c3926)
|
||||||
|
* improve uninstalling apps to show errors and exit if taking ownership fails #51 | [72e925f](https://github.com/undergroundwires/privacy.sexy/commit/72e925fb6f908cd58fb50618f29726b3fb54a7f1)
|
||||||
|
* move application.yaml to collections/windows.yaml #40 | [6b83dcb](https://github.com/undergroundwires/privacy.sexy/commit/6b83dcbf8fa08b4efe9974c7d7a667458f7c595c)
|
||||||
|
* recommend onedrive removal on strict mode | [663d63b](https://github.com/undergroundwires/privacy.sexy/commit/663d63bde08dd1b0d43ec144c758399cec90ec70)
|
||||||
|
* document app connector removal and recommend on strict mode | [9d009c4](https://github.com/undergroundwires/privacy.sexy/commit/9d009c40dd411c73c7ae032a78ec51490ecce024)
|
||||||
|
* recommend removing cortana taskbar icon on standard mode | [7ec889e](https://github.com/undergroundwires/privacy.sexy/commit/7ec889e759df04bba99d3b6c4d0597809bd94058)
|
||||||
|
* fix unintended null file creation #52 | [2428de2](https://github.com/undergroundwires/privacy.sexy/commit/2428de23ee02de987e7e6ec80ebd67be369d9048)
|
||||||
|
* add initial macOS support #40 | [8a8b731](https://github.com/undergroundwires/privacy.sexy/commit/8a8b7319d539b31c1d8ad9eaf541762d64f02493)
|
||||||
|
* add scripts to manage chromium based edge | [86a2b2f](https://github.com/undergroundwires/privacy.sexy/commit/86a2b2fda0b6a2565c550758c7c175fa795926b7)
|
||||||
|
* update screenshot | [c318bd3](https://github.com/undergroundwires/privacy.sexy/commit/c318bd301a2cbebbf5cdba06c0f18ac291aa4788)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.8.2...0.9.0)
|
||||||
|
|
||||||
|
## 0.8.2 (2020-12-26)
|
||||||
|
|
||||||
|
* replace ampersand in "Movies & TV app" with "and" to prevent batch file from misinterpreting it (#45) | [52d4313](https://github.com/undergroundwires/privacy.sexy/commit/52d4313156d2dcbc508b7271e7d9dfd45723d7bc)
|
||||||
|
* update dependencies to latest #46 | [d9e44e2](https://github.com/undergroundwires/privacy.sexy/commit/d9e44e25744e5d0aa01b8fc0f0af74c48027aea3)
|
||||||
|
* fix type assignment error after typescript upgrade | [55f936f](https://github.com/undergroundwires/privacy.sexy/commit/55f936fee9f86757f63fa8952d89711feb247e5b)
|
||||||
|
* correct typos (#48) | [a744415](https://github.com/undergroundwires/privacy.sexy/commit/a744415eb2ab65ee4f519f863fdd6a43953377bb)
|
||||||
|
* in ci/cd, do not run security checks if PRs do not change dependencies #48 | [54ba4db](https://github.com/undergroundwires/privacy.sexy/commit/54ba4dbb0bf8f08f9479f8facb2e12c786c1bc51)
|
||||||
|
* rename app launch tracking tweak to make it more clear #44 | [b3117c2](https://github.com/undergroundwires/privacy.sexy/commit/b3117c27f283c2d5a25fd94021a9f628a272cda6)
|
||||||
|
* refactor capabilities to use a shared function #41 #47 | [c4ec6a1](https://github.com/undergroundwires/privacy.sexy/commit/c4ec6a1445d2fd5eb923c97b54aee01e272e13a8)
|
||||||
|
* rename "disable" to "uninstall" for removing capabilities #47 | [8cd3352](https://github.com/undergroundwires/privacy.sexy/commit/8cd3352017f9dc85f8efcd7b450d90f555d3e92e)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.8.1...0.8.2)
|
||||||
|
|
||||||
|
## 0.8.1 (2020-11-16)
|
||||||
|
|
||||||
|
* refactor removing bloatware to use functions #41 | [ffa279f](https://github.com/undergroundwires/privacy.sexy/commit/ffa279f3dfe51db564f0a3859543eb212170e173)
|
||||||
|
* fix reinstalling store apps by searching appx for all users | [2c5ab3e](https://github.com/undergroundwires/privacy.sexy/commit/2c5ab3ea7da159cfb9fbfbbb7cdd28afbee965ea)
|
||||||
|
* fix clearing jump lists causing os to break and user pin removal #37 | [92c3dd9](https://github.com/undergroundwires/privacy.sexy/commit/92c3dd923257ac940eab6cbab858698ed55a09b7)
|
||||||
|
* fix reinstalling store apps by searching appx for all users | [4e72673](https://github.com/undergroundwires/privacy.sexy/commit/4e7267337301fe4a0480ba0603218fca25c2d096)
|
||||||
|
* refactor unused imports | [45b8dd9](https://github.com/undergroundwires/privacy.sexy/commit/45b8dd972b1edf9e263858c23b27e7a1d2e07077)
|
||||||
|
* fix not being able to uninstall system apps | [31e08d2](https://github.com/undergroundwires/privacy.sexy/commit/31e08d231d52e2a691400468b7c599c142a29448)
|
||||||
|
* fix wrong app names caused by wrong Microsoft docs | [e41e40c](https://github.com/undergroundwires/privacy.sexy/commit/e41e40c5bf01e2971d3054fcd3a48f8465a96622)
|
||||||
|
* unrecommend some system apps and document more | [29c7704](https://github.com/undergroundwires/privacy.sexy/commit/29c7704e0bd38f6e9923cde84accb569b02d2dd6)
|
||||||
|
* fix not being able to rename paths including brackets | [ad1872e](https://github.com/undergroundwires/privacy.sexy/commit/ad1872e7cd4ad7ef9facf33fadfa8c6a55065dd3)
|
||||||
|
* fix errors when file already exists | [c26bc20](https://github.com/undergroundwires/privacy.sexy/commit/c26bc209eb167aa71cad10b7f3ea02d0dedd97b0)
|
||||||
|
* move Microsoft.Appconnector to right category | [b247b12](https://github.com/undergroundwires/privacy.sexy/commit/b247b12c3f009aab4350e33f4779fd193e570050)
|
||||||
|
* replace deprecated github ::set-env command | [ab7d617](https://github.com/undergroundwires/privacy.sexy/commit/ab7d617886a65fe4f3c2daa929168e5678ccae60)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.8.0...0.8.1)
|
||||||
|
|
||||||
|
## 0.8.0 (2020-11-01)
|
||||||
|
|
||||||
|
* add support for different recommendation levels: strict and standard | [14be301](https://github.com/undergroundwires/privacy.sexy/commit/14be3017c55ed5e0d9bdecb63fcc4e1131e79ab0)
|
||||||
|
* Add GroupMe and Spotify removal option (#34) | [3785c62](https://github.com/undergroundwires/privacy.sexy/commit/3785c623f837b182d82fa383dfe7709722a67248)
|
||||||
|
* switch places of download and copy buttons | [50fb290](https://github.com/undergroundwires/privacy.sexy/commit/50fb29038ae19b17ec006093db02cf1e568d53c3)
|
||||||
|
* change "download" button to "save" on desktop | [07fc555](https://github.com/undergroundwires/privacy.sexy/commit/07fc555324d8bf4fa3594a9701daaa124a873153)
|
||||||
|
* show icons on cards during indeterminate and fully selected states | [1072505](https://github.com/undergroundwires/privacy.sexy/commit/1072505219edc47d82a91f148d1f310f32869fea)
|
||||||
|
* add scripts to increase cryptography, enable camera notifications and remove todo app (#36) | [4c68408](https://github.com/undergroundwires/privacy.sexy/commit/4c68408f1ec339dc8d39c7ab044f825a7f7185cb)
|
||||||
|
* update recommendations to be safer and consistent | [d0019c2](https://github.com/undergroundwires/privacy.sexy/commit/d0019c2c9b1eea620e2e8e02b586903ce62b80e3)
|
||||||
|
* rework disabling metadata retrieval | [ac70b06](https://github.com/undergroundwires/privacy.sexy/commit/ac70b063b8a15bc528256185792939685be6b36f)
|
||||||
|
* add all dist folders in gitignore because of files auto-generated by vscode | [1a9db31](https://github.com/undergroundwires/privacy.sexy/commit/1a9db31c7778c3269a71c0bd9665827efda70a02)
|
||||||
|
* add support for shared functions #41 | [8ce06fa](https://github.com/undergroundwires/privacy.sexy/commit/8ce06facbd54184402a4b1af3c7303e64db85b8a)
|
||||||
|
* hide scrollbars on code area when not overflowing | [fd28eaa](https://github.com/undergroundwires/privacy.sexy/commit/fd28eaad061c75ea1aa7e0f0d60ea37a7e52f8c4)
|
||||||
|
* update screenshot | [cfedcd7](https://github.com/undergroundwires/privacy.sexy/commit/cfedcd724cad7708b30c7390a7bca3b6313b6726)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.6...0.8.0)
|
||||||
|
|
||||||
|
## 0.7.6 (2020-10-18)
|
||||||
|
|
||||||
|
* add docs for default0 pointing to github discussion (#30) | [a3fc378](https://github.com/undergroundwires/privacy.sexy/commit/a3fc3782efd346b4c99d2a0b40df2eb0229f5b36)
|
||||||
|
* add robots.txt to explicitly allow indexing | [4c2f749](https://github.com/undergroundwires/privacy.sexy/commit/4c2f74949b0758d33049bdfa4f0124a28958f8ea)
|
||||||
|
* add more reversibility | [19a092d](https://github.com/undergroundwires/privacy.sexy/commit/19a092dd31fb3588277f1ab3120b409d98506752)
|
||||||
|
* refactor to read more from package.json | [784a67a](https://github.com/undergroundwires/privacy.sexy/commit/784a67afff681bc19147d03c947de0e165d97e87)
|
||||||
|
* simplify "why" section | [77c3d2b](https://github.com/undergroundwires/privacy.sexy/commit/77c3d2bbb8d13db86bb82ed0b5cbeaacfdea3db9)
|
||||||
|
* update dependencies to latest | [11e0613](https://github.com/undergroundwires/privacy.sexy/commit/11e06131655398db08faeeacff62062e46e0dddd)
|
||||||
|
* run tests on all operating systems: macos, ubuntu, windows | [d9d7f62](https://github.com/undergroundwires/privacy.sexy/commit/d9d7f62d81d4d8f95104d33211e82641884d711f)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.5...0.7.6)
|
||||||
|
|
||||||
|
## 0.7.5 (2020-09-14)
|
||||||
|
|
||||||
|
* fix reverting (reinstalling) capabilities not working | [939d838](https://github.com/undergroundwires/privacy.sexy/commit/939d838e3535bb1c9b00c8ea9dacb735ae41d700)
|
||||||
|
* fix tests and checks are not running on PRs | [82d5091](https://github.com/undergroundwires/privacy.sexy/commit/82d509129b4e4a5df4b84786a0d6842a7d26e888)
|
||||||
|
* fix the recycling bin option (#32) | [15db311](https://github.com/undergroundwires/privacy.sexy/commit/15db3118012a172a2191a2afad57084a65b34642)
|
||||||
|
* fix rendering issue in older edge/IE | [6efed72](https://github.com/undergroundwires/privacy.sexy/commit/6efed72bf25c2ddf0901caab7f22966ca13cd47a)
|
||||||
|
* fix pasting in search bar after page load showing no results | [d169434](https://github.com/undergroundwires/privacy.sexy/commit/d1694341578288eeaf8b80caf9296a38d76789f0)
|
||||||
|
* fix typo | [7dd15ed](https://github.com/undergroundwires/privacy.sexy/commit/7dd15ed06433e0e6583ab0fa46a683ce6554bbea)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.4...0.7.5)
|
||||||
|
|
||||||
|
## 0.7.4 (2020-09-12)
|
||||||
|
|
||||||
|
* fix checked checkbox has blue border | [4ae385b](https://github.com/undergroundwires/privacy.sexy/commit/4ae385b7fcea9014a68442714b7d99e2ee7df7d0)
|
||||||
|
* fix spectre protection getting single lined #31 | [22b23a9](https://github.com/undergroundwires/privacy.sexy/commit/22b23a9ece446c7f9abd4ede293051eb616ad50a)
|
||||||
|
* fix missing reg value in denying app access to account | [3c13a9e](https://github.com/undergroundwires/privacy.sexy/commit/3c13a9e837e06e097450b31d7eb0c0e6bf20cefb)
|
||||||
|
* fix wrong path in clear all firefox user profile settings | [ee66196](https://github.com/undergroundwires/privacy.sexy/commit/ee66196d9a60f27d17ae7f62d02b4f119a47e6e0)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.3...0.7.4)
|
||||||
|
|
||||||
|
## 0.7.3 (2020-09-12)
|
||||||
|
|
||||||
|
* fix vscode settings file override and add more configs | [a0d6172](https://github.com/undergroundwires/privacy.sexy/commit/a0d61728ead04b4455437f85820121a848db9e00)
|
||||||
|
* fix nvidia tweak error message, categorize and add reversibility | [99a2035](https://github.com/undergroundwires/privacy.sexy/commit/99a2035fdb0766a4dfc2753133eab0d7666516cd)
|
||||||
|
* improve CPU specific tweaks by conditional platform checks and reversibility | [8df5faf](https://github.com/undergroundwires/privacy.sexy/commit/8df5faf4ef05a49da63973bd0fbb5c5d07d5bd93)
|
||||||
|
* fix wrong path to the main telemetry file | [de4ac97](https://github.com/undergroundwires/privacy.sexy/commit/de4ac978bdda79573b36d355697b8a028d2c0beb)
|
||||||
|
* fix naming of firefox cleanup to mention profiles | [3ab48b1](https://github.com/undergroundwires/privacy.sexy/commit/3ab48b1cf5f7f934f07e468ef2318ccee07f530c)
|
||||||
|
* add reversibility and more scripts to denying app access with better structure | [1d465ee](https://github.com/undergroundwires/privacy.sexy/commit/1d465ee3189d0e5a827453b3f0eb4361efe23770)
|
||||||
|
* fix comment lines are being detected as duplicate in validation | [b6ccb59](https://github.com/undergroundwires/privacy.sexy/commit/b6ccb5927a20412976a54fd2215eb645092f98a8)
|
||||||
|
* add more detailed error message | [1f11c39](https://github.com/undergroundwires/privacy.sexy/commit/1f11c39773c12eccfb3efb898b58c2f6f37ab9ca)
|
||||||
|
* fix typo in a test | [1f19b25](https://github.com/undergroundwires/privacy.sexy/commit/1f19b2528a69383e63e579d2885f01cd804abf6c)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.2...0.7.3)
|
||||||
|
|
||||||
|
## 0.7.2 (2020-09-06)
|
||||||
|
|
||||||
|
* update onesync documentation and do not recommend it as it breaks other apps | [f36d8bf](https://github.com/undergroundwires/privacy.sexy/commit/f36d8bfc7848bb65ac0c641e318a689bf3816ccf)
|
||||||
|
* add reversibility for biometric disabling and do not recommend it | [db74531](https://github.com/undergroundwires/privacy.sexy/commit/db74531cd4139615c6d595959217d3651f099019)
|
||||||
|
* fix bad highlighting of selected nodes when using keyboard navigation | [255133a](https://github.com/undergroundwires/privacy.sexy/commit/255133af4dfae40171406648a3e2920f16d71cb3)
|
||||||
|
* add reversibility to removing bloatware | [c7b2a70](https://github.com/undergroundwires/privacy.sexy/commit/c7b2a703128470a05f12c9c6e8002444def37ef8)
|
||||||
|
* fix indeterminate state being lost | [1f266c3](https://github.com/undergroundwires/privacy.sexy/commit/1f266c33535f72b69c65985bf2eff27cd2c5a104)
|
||||||
|
* fix wording in default text in text area | [ca63a09](https://github.com/undergroundwires/privacy.sexy/commit/ca63a0979ef55d07d09d9443e5cea9aa888870a5)
|
||||||
|
* add best practice suggestion to come back | [f4885b6](https://github.com/undergroundwires/privacy.sexy/commit/f4885b6f1c82752f2143934e336d6d1b1af03015)
|
||||||
|
|
||||||
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.1...0.7.2)
|
||||||
|
|
||||||
## 0.7.1 (2020-09-04)
|
## 0.7.1 (2020-09-04)
|
||||||
|
|
||||||
* fix some browsers (including firefox) downloading the script as a text file | [commit](https://github.com/undergroundwires/privacy.sexy/commit/8c17929151f9c4fa5f48564492bbf400ced95eea)
|
* fix some browsers (including firefox) downloading the script as a text file | [8c17929](https://github.com/undergroundwires/privacy.sexy/commit/8c17929151f9c4fa5f48564492bbf400ced95eea)
|
||||||
* rename screenshot image file | [commit](https://github.com/undergroundwires/privacy.sexy/commit/b8682a852a14ed6cf49986695d9510b840ac9d3d)
|
* rename screenshot image file | [b8682a8](https://github.com/undergroundwires/privacy.sexy/commit/b8682a852a14ed6cf49986695d9510b840ac9d3d)
|
||||||
* fix new/changed script higlighting not working on production builds | [commit](https://github.com/undergroundwires/privacy.sexy/commit/8c38dd73d8c7b77d8d341c0389f4d7229f9b97fd)
|
* fix new/changed script higlighting not working on production builds | [8c38dd7](https://github.com/undergroundwires/privacy.sexy/commit/8c38dd73d8c7b77d8d341c0389f4d7229f9b97fd)
|
||||||
* refactor unused imports | [commit](https://github.com/undergroundwires/privacy.sexy/commit/6badfef9daace0c5de3fd33652a82bfe22261b11)
|
* refactor unused imports | [6badfef](https://github.com/undergroundwires/privacy.sexy/commit/6badfef9daace0c5de3fd33652a82bfe22261b11)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.0...0.7.1)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.7.0...0.7.1)
|
||||||
|
|
||||||
## 0.7.0 (2020-09-02)
|
## 0.7.0 (2020-09-02)
|
||||||
|
|
||||||
* [search] better (multilined) message when there are no results | [commit](https://github.com/undergroundwires/privacy.sexy/commit/ec15af01dd020b364c2174fe562fd66227c2320c)
|
* [search] better (multilined) message when there are no results | [ec15af0](https://github.com/undergroundwires/privacy.sexy/commit/ec15af01dd020b364c2174fe562fd66227c2320c)
|
||||||
* [search] added clear/close button | [commit](https://github.com/undergroundwires/privacy.sexy/commit/d6fa9a2a03c0ebe68b94f0b80cc52b4e200c9213)
|
* [search] added clear/close button | [d6fa9a2](https://github.com/undergroundwires/privacy.sexy/commit/d6fa9a2a03c0ebe68b94f0b80cc52b4e200c9213)
|
||||||
* move script generation to /generation | [commit](https://github.com/undergroundwires/privacy.sexy/commit/5df458739d076719e350ba194c4f3f772884fcdb)
|
* move script generation to /generation | [5df4587](https://github.com/undergroundwires/privacy.sexy/commit/5df458739d076719e350ba194c4f3f772884fcdb)
|
||||||
* add auto-highlighting of selected/updated code | [commit](https://github.com/undergroundwires/privacy.sexy/commit/b789250cb89e2130b08e1a927df8181cf945dfeb)
|
* add auto-highlighting of selected/updated code | [b789250](https://github.com/undergroundwires/privacy.sexy/commit/b789250cb89e2130b08e1a927df8181cf945dfeb)
|
||||||
* prompt admin priviliges automatically | [commit](https://github.com/undergroundwires/privacy.sexy/commit/f8ba5c46e4923d9c35f200f8a08aa6437f7c0ecc)
|
* prompt admin priviliges automatically | [f8ba5c4](https://github.com/undergroundwires/privacy.sexy/commit/f8ba5c46e4923d9c35f200f8a08aa6437f7c0ecc)
|
||||||
* add removal of ghost (default0) telemetry user | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c262681011f39b4412669b6cf233476f676ca550)
|
* add removal of ghost (default0) telemetry user | [c262681](https://github.com/undergroundwires/privacy.sexy/commit/c262681011f39b4412669b6cf233476f676ca550)
|
||||||
* add more windows defender tweaks, categorization and reversibility | [commit](https://github.com/undergroundwires/privacy.sexy/commit/1a34c7374ba56bafa0209bbb55c81b233bb419ed)
|
* add more windows defender tweaks, categorization and reversibility | [1a34c73](https://github.com/undergroundwires/privacy.sexy/commit/1a34c7374ba56bafa0209bbb55c81b233bb419ed)
|
||||||
* fix NTP script documentation is on wrong place | [commit](https://github.com/undergroundwires/privacy.sexy/commit/3060ebf79cf242370433495cc3e1878b7581b202)
|
* fix NTP script documentation is on wrong place | [3060ebf](https://github.com/undergroundwires/privacy.sexy/commit/3060ebf79cf242370433495cc3e1878b7581b202)
|
||||||
* updated dependencies to latest and audit fixes (#25) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c628aa9aef8ab7c815661d3c1711e7fbc65c69a2)
|
* updated dependencies to latest and audit fixes (#25) | [c628aa9](https://github.com/undergroundwires/privacy.sexy/commit/c628aa9aef8ab7c815661d3c1711e7fbc65c69a2)
|
||||||
* categorize, fix and extend windows log files cleanup | [commit](https://github.com/undergroundwires/privacy.sexy/commit/594a14d6ca76cbd27a21877b8c373c1930589ca6)
|
* categorize, fix and extend windows log files cleanup | [594a14d](https://github.com/undergroundwires/privacy.sexy/commit/594a14d6ca76cbd27a21877b8c373c1930589ca6)
|
||||||
* add more OneDrive cleanup scripts and categorize them | [commit](https://github.com/undergroundwires/privacy.sexy/commit/978d7d08638dd161082f239ed088b12302f29458)
|
* add more OneDrive cleanup scripts and categorize them | [978d7d0](https://github.com/undergroundwires/privacy.sexy/commit/978d7d08638dd161082f239ed088b12302f29458)
|
||||||
* add disabling firefox telemetry | [commit](https://github.com/undergroundwires/privacy.sexy/commit/f8b8b4c97ab734d5ba7370894b694993924388da)
|
* add disabling firefox telemetry | [f8b8b4c](https://github.com/undergroundwires/privacy.sexy/commit/f8b8b4c97ab734d5ba7370894b694993924388da)
|
||||||
* add disabling ccleaner telemetry | [commit](https://github.com/undergroundwires/privacy.sexy/commit/018b7e270f207aac926cb12f8069ebfcdce193ce)
|
* add disabling ccleaner telemetry | [018b7e2](https://github.com/undergroundwires/privacy.sexy/commit/018b7e270f207aac926cb12f8069ebfcdce193ce)
|
||||||
* Add disabling of PowerShell 7+ telemetry (#29) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/456e40bedf9afcc846f9b13f1ea144cef6115cf6)
|
* Add disabling of PowerShell 7+ telemetry (#29) | [456e40b](https://github.com/undergroundwires/privacy.sexy/commit/456e40bedf9afcc846f9b13f1ea144cef6115cf6)
|
||||||
* categorize, fix, make scripts reversible in "UI for privacy", "security improvements" and "configure browsers" | [commit](https://github.com/undergroundwires/privacy.sexy/commit/532915b95da9fecd6b981d91bf489359e4e53caa)
|
* categorize, fix, make scripts reversible in "UI for privacy", "security improvements" and "configure browsers" | [532915b](https://github.com/undergroundwires/privacy.sexy/commit/532915b95da9fecd6b981d91bf489359e4e53caa)
|
||||||
* fix "Configure Defender" being in wrong category #28 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/f709d6a566ed7846b677b383863deda9680a2a9c)
|
* fix "Configure Defender" being in wrong category #28 | [f709d6a](https://github.com/undergroundwires/privacy.sexy/commit/f709d6a566ed7846b677b383863deda9680a2a9c)
|
||||||
* do not hardcode capability versions and make them reversible | [commit](https://github.com/undergroundwires/privacy.sexy/commit/2afef4ea3d0d3d09aa1fa1eedba8493680bd8f10)
|
* do not hardcode capability versions and make them reversible | [2afef4e](https://github.com/undergroundwires/privacy.sexy/commit/2afef4ea3d0d3d09aa1fa1eedba8493680bd8f10)
|
||||||
* exclude paint, wordpad and notepad from bloatware removal | [commit](https://github.com/undergroundwires/privacy.sexy/commit/d235dee95514a01745aef9479d07f88ffb4b40b8)
|
* exclude paint, wordpad and notepad from bloatware removal | [d235dee](https://github.com/undergroundwires/privacy.sexy/commit/d235dee95514a01745aef9479d07f88ffb4b40b8)
|
||||||
* add reversibility on category level | [commit](https://github.com/undergroundwires/privacy.sexy/commit/f51e8859eeb32c944126d692cfe03a0320c8b568)
|
* add reversibility on category level | [f51e885](https://github.com/undergroundwires/privacy.sexy/commit/f51e8859eeb32c944126d692cfe03a0320c8b568)
|
||||||
* refactor unused imports & variables | [commit](https://github.com/undergroundwires/privacy.sexy/commit/a23d28f2cfa2d64d45460697cf5ee9d6b5920752)
|
* refactor unused imports & variables | [a23d28f](https://github.com/undergroundwires/privacy.sexy/commit/a23d28f2cfa2d64d45460697cf5ee9d6b5920752)
|
||||||
* fix search (got broken in b789250) with tests and refactorings | [commit](https://github.com/undergroundwires/privacy.sexy/commit/8bbe6ebf750f1a1cbab493fb99b5ea91f4e21609)
|
* fix search (got broken in b789250) with tests and refactorings | [8bbe6eb](https://github.com/undergroundwires/privacy.sexy/commit/8bbe6ebf750f1a1cbab493fb99b5ea91f4e21609)
|
||||||
* update the screenshot to show off highlighting | [commit](https://github.com/undergroundwires/privacy.sexy/commit/b4aacea2a3e0bbcf2d8a79ff67f51c0f19e888a6)
|
* update the screenshot to show off highlighting | [b4aacea](https://github.com/undergroundwires/privacy.sexy/commit/b4aacea2a3e0bbcf2d8a79ff67f51c0f19e888a6)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.6.2...0.7.0)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.6.2...0.7.0)
|
||||||
|
|
||||||
## 0.6.2 (2020-08-16)
|
## 0.6.2 (2020-08-16)
|
||||||
|
|
||||||
* 🐛 fixed disabling error reporting for november 2019 update | [commit](https://github.com/undergroundwires/privacy.sexy/commit/5967347b80976a519f6f4eb1972a62f3e600df2b)
|
* 🐛 fixed disabling error reporting for november 2019 update | [5967347](https://github.com/undergroundwires/privacy.sexy/commit/5967347b80976a519f6f4eb1972a62f3e600df2b)
|
||||||
* 🐛 fixed blank screen and icons on mac | [commit](https://github.com/undergroundwires/privacy.sexy/commit/7fac0fe79f252e8f9dda4f6f83cd6fa4ba2b539f)
|
* 🐛 fixed blank screen and icons on mac | [7fac0fe](https://github.com/undergroundwires/privacy.sexy/commit/7fac0fe79f252e8f9dda4f6f83cd6fa4ba2b539f)
|
||||||
* 🐛 fixed removing onedrive does not delete scheduled tasks | [commit](https://github.com/undergroundwires/privacy.sexy/commit/b6bfc2572740c0cd46d3bc0058fa767dd5fa862e)
|
* 🐛 fixed removing onedrive does not delete scheduled tasks | [b6bfc25](https://github.com/undergroundwires/privacy.sexy/commit/b6bfc2572740c0cd46d3bc0058fa767dd5fa862e)
|
||||||
* ⚙️ enhanced tweak to disable for office telemetry | [commit](https://github.com/undergroundwires/privacy.sexy/commit/afc3bfb3b8896f332c9a196973ded3dce8fd21e4)
|
* ⚙️ enhanced tweak to disable for office telemetry | [afc3bfb](https://github.com/undergroundwires/privacy.sexy/commit/afc3bfb3b8896f332c9a196973ded3dce8fd21e4)
|
||||||
* ✨ added script to clear dotnet telemery | [commit](https://github.com/undergroundwires/privacy.sexy/commit/1663bfeac7b6580b1335ca5fcf3587b69c080c72)
|
* ✨ added script to clear dotnet telemery | [1663bfe](https://github.com/undergroundwires/privacy.sexy/commit/1663bfeac7b6580b1335ca5fcf3587b69c080c72)
|
||||||
* 🐛 fixed changing time server not working | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c69998c7cb29ffcf40f0af03b73150736581da69)
|
* 🐛 fixed changing time server not working | [c69998c](https://github.com/undergroundwires/privacy.sexy/commit/c69998c7cb29ffcf40f0af03b73150736581da69)
|
||||||
* 🔥 removed disabling ClickToRun as it breaks office | [commit](https://github.com/undergroundwires/privacy.sexy/commit/3d3380f27ebeea53f17f49974aaa89300ffaf2dd)
|
* 🔥 removed disabling ClickToRun as it breaks office | [3d3380f](https://github.com/undergroundwires/privacy.sexy/commit/3d3380f27ebeea53f17f49974aaa89300ffaf2dd)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.6.1...0.6.2)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.6.1...0.6.2)
|
||||||
|
|
||||||
## 0.6.1 (2020-08-09)
|
## 0.6.1 (2020-08-09)
|
||||||
|
|
||||||
* updated documentation | [commit](https://github.com/undergroundwires/privacy.sexy/commit/5963d2bac551083f9d16cce6b851abf0e8b88ce7)
|
* updated documentation | [5963d2b](https://github.com/undergroundwires/privacy.sexy/commit/5963d2bac551083f9d16cce6b851abf0e8b88ce7)
|
||||||
* fixed typo in footer | [commit](https://github.com/undergroundwires/privacy.sexy/commit/5c15a7a64aaf24578a32713dec491bf494216303)
|
* fixed typo in footer | [5c15a7a](https://github.com/undergroundwires/privacy.sexy/commit/5c15a7a64aaf24578a32713dec491bf494216303)
|
||||||
* more scripts can be reverted | [commit](https://github.com/undergroundwires/privacy.sexy/commit/831c014f977515454ee6dc664d77a8c434495501)
|
* more scripts can be reverted | [831c014](https://github.com/undergroundwires/privacy.sexy/commit/831c014f977515454ee6dc664d77a8c434495501)
|
||||||
* moved windows connect now to security & recommended | [commit](https://github.com/undergroundwires/privacy.sexy/commit/6049a2b834d8d17af741f8d8f8b07cd15153b001)
|
* moved windows connect now to security & recommended | [6049a2b](https://github.com/undergroundwires/privacy.sexy/commit/6049a2b834d8d17af741f8d8f8b07cd15153b001)
|
||||||
* fixed mac / linux download links | [commit](https://github.com/undergroundwires/privacy.sexy/commit/4c8be45e287b5ea009d6f828f7f327f37850569e)
|
* fixed mac / linux download links | [4c8be45](https://github.com/undergroundwires/privacy.sexy/commit/4c8be45e287b5ea009d6f828f7f327f37850569e)
|
||||||
* tweaks to disable webcam, speech and compatibility telemetry | [commit](https://github.com/undergroundwires/privacy.sexy/commit/a5dbe66fc175e39397f296ab2ff703e9b0ab4d7c)
|
* tweaks to disable webcam, speech and compatibility telemetry | [a5dbe66](https://github.com/undergroundwires/privacy.sexy/commit/a5dbe66fc175e39397f296ab2ff703e9b0ab4d7c)
|
||||||
* refactorings | [commit](https://github.com/undergroundwires/privacy.sexy/commit/66d4d39d5bf3db305450514c6b6224654dafbfb2)
|
* refactorings | [66d4d39](https://github.com/undergroundwires/privacy.sexy/commit/66d4d39d5bf3db305450514c6b6224654dafbfb2)
|
||||||
* fixed removing onedrive does not clean start menu / quick access | [commit](https://github.com/undergroundwires/privacy.sexy/commit/1cc12195a3e9a11c590d3ed64d80299b50f74838)
|
* fixed removing onedrive does not clean start menu / quick access | [1cc1219](https://github.com/undergroundwires/privacy.sexy/commit/1cc12195a3e9a11c590d3ed64d80299b50f74838)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.6.0...0.6.1)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.6.0...0.6.1)
|
||||||
|
|
||||||
## 0.6.0 (2020-07-26)
|
## 0.6.0 (2020-07-26)
|
||||||
|
|
||||||
* fixed dead links in documentation | [commit](https://github.com/undergroundwires/privacy.sexy/commit/25ce236a7737decaf2eb9b8c29a4c4f34d43f770)
|
* fixed dead links in documentation | [25ce236](https://github.com/undergroundwires/privacy.sexy/commit/25ce236a7737decaf2eb9b8c29a4c4f34d43f770)
|
||||||
* runs tests on each push on the repository | [commit](https://github.com/undergroundwires/privacy.sexy/commit/73c426844a0330718a9ab7de12b61ca05e853323)
|
* runs tests on each push on the repository | [73c4268](https://github.com/undergroundwires/privacy.sexy/commit/73c426844a0330718a9ab7de12b61ca05e853323)
|
||||||
* code area now shows "how" before "why" | [commit](https://github.com/undergroundwires/privacy.sexy/commit/4ff4b52202b1c5dbfe2b80580bbe7d93132ab05c)
|
* code area now shows "how" before "why" | [4ff4b52](https://github.com/undergroundwires/privacy.sexy/commit/4ff4b52202b1c5dbfe2b80580bbe7d93132ab05c)
|
||||||
* support for desktop versions #20 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/04b9b59e14766ccd251474ad3710baf1f682fd49)
|
* support for desktop versions #20 | [04b9b59](https://github.com/undergroundwires/privacy.sexy/commit/04b9b59e14766ccd251474ad3710baf1f682fd49)
|
||||||
* reworked on footer & removed github icon | [commit](https://github.com/undergroundwires/privacy.sexy/commit/60a5a2aa4026d384bef9e6a203f1b7514a269c33)
|
* reworked on footer & removed github icon | [60a5a2a](https://github.com/undergroundwires/privacy.sexy/commit/60a5a2aa4026d384bef9e6a203f1b7514a269c33)
|
||||||
* updated dependencies to latest | [commit](https://github.com/undergroundwires/privacy.sexy/commit/45816a2bccb3d11a50e3f2bc19c0a6cc2587deaa)
|
* updated dependencies to latest | [45816a2](https://github.com/undergroundwires/privacy.sexy/commit/45816a2bccb3d11a50e3f2bc19c0a6cc2587deaa)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.5.0...0.6.0)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.5.0...0.6.0)
|
||||||
|
|
||||||
## 0.5.0 (2020-07-19)
|
## 0.5.0 (2020-07-19)
|
||||||
|
|
||||||
* added ability to revert (#21) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/9c063d59defa6297c64f50b49403e8bd10620de9)
|
* added ability to revert (#21) | [9c063d5](https://github.com/undergroundwires/privacy.sexy/commit/9c063d59defa6297c64f50b49403e8bd10620de9)
|
||||||
* search placeholder shows total scripts | [commit](https://github.com/undergroundwires/privacy.sexy/commit/1d5225de07186f853f4cf7aedd4998f5d00c107a)
|
* search placeholder shows total scripts | [1d5225d](https://github.com/undergroundwires/privacy.sexy/commit/1d5225de07186f853f4cf7aedd4998f5d00c107a)
|
||||||
* do not collapse card when on "Search" and "Select" | [commit](https://github.com/undergroundwires/privacy.sexy/commit/dd7e1416b4df54bf71b719d4654db88769dc0994)
|
* do not collapse card when on "Search" and "Select" | [dd7e141](https://github.com/undergroundwires/privacy.sexy/commit/dd7e1416b4df54bf71b719d4654db88769dc0994)
|
||||||
* opening a card scrolls to its content div | [commit](https://github.com/undergroundwires/privacy.sexy/commit/31d2067f076c3159483baec49975617dddbd158d)
|
* opening a card scrolls to its content div | [31d2067](https://github.com/undergroundwires/privacy.sexy/commit/31d2067f076c3159483baec49975617dddbd158d)
|
||||||
* all cards in same line now have same height | [commit](https://github.com/undergroundwires/privacy.sexy/commit/a9f9e9044385d9aed3b5551fc6c6823e813fd1e5)
|
* all cards in same line now have same height | [a9f9e90](https://github.com/undergroundwires/privacy.sexy/commit/a9f9e9044385d9aed3b5551fc6c6823e813fd1e5)
|
||||||
* patched loadash vulnerability (#18) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/92a7118d1c5013312772e075b9ee5a79c93710b8)
|
* patched loadash vulnerability (#18) | [92a7118](https://github.com/undergroundwires/privacy.sexy/commit/92a7118d1c5013312772e075b9ee5a79c93710b8)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.10...0.5.0)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.10...0.5.0)
|
||||||
|
|
||||||
## 0.4.10 (2020-07-15)
|
## 0.4.10 (2020-07-15)
|
||||||
|
|
||||||
* fixed script errors & added tests | [commit](https://github.com/undergroundwires/privacy.sexy/commit/9e722ddfb3825fb29d6298025baaaa033120d017)
|
* fixed script errors & added tests | [9e722dd](https://github.com/undergroundwires/privacy.sexy/commit/9e722ddfb3825fb29d6298025baaaa033120d017)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.9...0.4.10)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.9...0.4.10)
|
||||||
|
|
||||||
## 0.4.9 (2020-07-14)
|
## 0.4.9 (2020-07-14)
|
||||||
|
|
||||||
* disable office telemetry Disassembler0/Win10-Initial-Setup-Script#288 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/53cf595e1726ee3de79137fd566978fd512d218f)
|
* disable office telemetry Disassembler0/Win10-Initial-Setup-Script#288 | [53cf595](https://github.com/undergroundwires/privacy.sexy/commit/53cf595e1726ee3de79137fd566978fd512d218f)
|
||||||
* updated to may 2020 update | [commit](https://github.com/undergroundwires/privacy.sexy/commit/909c44d72a4a602ee8f27d06b6ec706c1e432ce1)
|
* updated to may 2020 update | [909c44d](https://github.com/undergroundwires/privacy.sexy/commit/909c44d72a4a602ee8f27d06b6ec706c1e432ce1)
|
||||||
* simplified docker builds | [commit](https://github.com/undergroundwires/privacy.sexy/commit/f27a2871d74e5117fc029be82caef12246e10879)
|
* simplified docker builds | [f27a287](https://github.com/undergroundwires/privacy.sexy/commit/f27a2871d74e5117fc029be82caef12246e10879)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.8...0.4.9)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.8...0.4.9)
|
||||||
|
|
||||||
## 0.4.8 (2020-07-11)
|
## 0.4.8 (2020-07-11)
|
||||||
|
|
||||||
* added more scripts #16 (#17) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/d8552c62ffea13ce62abce836c7dd4980eef6bb9)
|
* added more scripts #16 (#17) | [d8552c6](https://github.com/undergroundwires/privacy.sexy/commit/d8552c62ffea13ce62abce836c7dd4980eef6bb9)
|
||||||
* stopping services before disabling #16 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/628c16eb952495f5b3f6d794161b355f4b08b819)
|
* stopping services before disabling #16 | [628c16e](https://github.com/undergroundwires/privacy.sexy/commit/628c16eb952495f5b3f6d794161b355f4b08b819)
|
||||||
* can disable features, capabilities & remove onedrive #16 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/30efbcc621eb83dd5a9c1e66b8f1f5350eb95006)
|
* can disable features, capabilities & remove onedrive #16 | [30efbcc](https://github.com/undergroundwires/privacy.sexy/commit/30efbcc621eb83dd5a9c1e66b8f1f5350eb95006)
|
||||||
* updated one more typo (#19) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/d7a1325c0b7665ce712dc411965d00fc1d6fa384)
|
* updated one more typo (#19) | [d7a1325](https://github.com/undergroundwires/privacy.sexy/commit/d7a1325c0b7665ce712dc411965d00fc1d6fa384)
|
||||||
* more tweaks #16 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/2c4eb78c3f156cb0d033977cffbe7464697680f5)
|
* more tweaks #16 | [2c4eb78](https://github.com/undergroundwires/privacy.sexy/commit/2c4eb78c3f156cb0d033977cffbe7464697680f5)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.7...0.4.8)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.7...0.4.8)
|
||||||
|
|
||||||
## 0.4.7 (2020-06-30)
|
## 0.4.7 (2020-06-30)
|
||||||
|
|
||||||
* removed HKU tweak as all HKU's are changed #10 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c937af8ee7da9aa95131e56abf7bf24800390fe6)
|
* removed HKU tweak as all HKU's are changed #10 | [c937af8](https://github.com/undergroundwires/privacy.sexy/commit/c937af8ee7da9aa95131e56abf7bf24800390fe6)
|
||||||
* Fixed types + script in "Clear Windows log files" (#15) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/461a4f122b342369db5cc08c5e30961c64e68cdd)
|
* Fixed types + script in "Clear Windows log files" (#15) | [461a4f1](https://github.com/undergroundwires/privacy.sexy/commit/461a4f122b342369db5cc08c5e30961c64e68cdd)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.6...0.4.7)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.6...0.4.7)
|
||||||
|
|
||||||
## 0.4.6 (2020-06-16)
|
## 0.4.6 (2020-06-16)
|
||||||
|
|
||||||
* Fixed Some More Issues (#12) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/52d5713a99422cdf900aba819e49e998abac33cc)
|
* Fixed Some More Issues (#12) | [52d5713](https://github.com/undergroundwires/privacy.sexy/commit/52d5713a99422cdf900aba819e49e998abac33cc)
|
||||||
* removed failing continuous deployment #14 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/583c5660d6ac934b845a044e013357aa91f61c15)
|
* removed failing continuous deployment #14 | [583c566](https://github.com/undergroundwires/privacy.sexy/commit/583c5660d6ac934b845a044e013357aa91f61c15)
|
||||||
* Updated Some Tweaks (#11) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/0fc18459cde57684f00764815062f838f932aed5)
|
* Updated Some Tweaks (#11) | [0fc1845](https://github.com/undergroundwires/privacy.sexy/commit/0fc18459cde57684f00764815062f838f932aed5)
|
||||||
* Updated Some More Tweaks (#13) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/019b838925e963b7ec052ac76c6faf5650b9eb67)
|
* Updated Some More Tweaks (#13) | [019b838](https://github.com/undergroundwires/privacy.sexy/commit/019b838925e963b7ec052ac76c6faf5650b9eb67)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.5...0.4.6)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.5...0.4.6)
|
||||||
|
|
||||||
@@ -129,91 +283,91 @@
|
|||||||
|
|
||||||
## 0.4.4 (2020-05-24)
|
## 0.4.4 (2020-05-24)
|
||||||
|
|
||||||
* fixed close card button not being visible & cleanup | [commit](https://github.com/undergroundwires/privacy.sexy/commit/0d2efe5b05aa965458b78b8fa43754ce2f4fe11b)
|
* fixed close card button not being visible & cleanup | [0d2efe5](https://github.com/undergroundwires/privacy.sexy/commit/0d2efe5b05aa965458b78b8fa43754ce2f4fe11b)
|
||||||
* new footer with privacy policy | [commit](https://github.com/undergroundwires/privacy.sexy/commit/e2ab124fb799f56ada3570fdc911361cb803e889)
|
* new footer with privacy policy | [e2ab124](https://github.com/undergroundwires/privacy.sexy/commit/e2ab124fb799f56ada3570fdc911361cb803e889)
|
||||||
* one command to lint everything "npm run lint" | [commit](https://github.com/undergroundwires/privacy.sexy/commit/bb98d20637cbf1d524ebb2973e308773006e3153)
|
* one command to lint everything "npm run lint" | [bb98d20](https://github.com/undergroundwires/privacy.sexy/commit/bb98d20637cbf1d524ebb2973e308773006e3153)
|
||||||
* fix "group by" overflows on smaller screens | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c668a97950a1cb7c8bf2a7fd8a72d1101e65e8ce)
|
* fix "group by" overflows on smaller screens | [c668a97](https://github.com/undergroundwires/privacy.sexy/commit/c668a97950a1cb7c8bf2a7fd8a72d1101e65e8ce)
|
||||||
* clicking outside of a card closes it | [commit](https://github.com/undergroundwires/privacy.sexy/commit/aab8f21a8d8dbed54798af581e6e1ad9e86a4be1)
|
* clicking outside of a card closes it | [aab8f21](https://github.com/undergroundwires/privacy.sexy/commit/aab8f21a8d8dbed54798af581e6e1ad9e86a4be1)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.3...0.4.4)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.3...0.4.4)
|
||||||
|
|
||||||
## 0.4.3 (2020-05-23)
|
## 0.4.3 (2020-05-23)
|
||||||
|
|
||||||
* removed redundant documentation | [commit](https://github.com/undergroundwires/privacy.sexy/commit/749a140eb8dba09cb67fec2f8dec937e66e3cff5)
|
* removed redundant documentation | [749a140](https://github.com/undergroundwires/privacy.sexy/commit/749a140eb8dba09cb67fec2f8dec937e66e3cff5)
|
||||||
* fixed broke link | [commit](https://github.com/undergroundwires/privacy.sexy/commit/97b7e03233d9718a8df30cb01ce06ca9489a0295)
|
* fixed broke link | [97b7e03](https://github.com/undergroundwires/privacy.sexy/commit/97b7e03233d9718a8df30cb01ce06ca9489a0295)
|
||||||
* simplified heading | [commit](https://github.com/undergroundwires/privacy.sexy/commit/226074c5342f7463c06fcff1457d352ca30295a3)
|
* simplified heading | [226074c](https://github.com/undergroundwires/privacy.sexy/commit/226074c5342f7463c06fcff1457d352ca30295a3)
|
||||||
* reading version from package.json instead of version file #5 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/691f989682179016ddcbf55a05cded29155288c9)
|
* reading version from package.json instead of version file #5 | [691f989](https://github.com/undergroundwires/privacy.sexy/commit/691f989682179016ddcbf55a05cded29155288c9)
|
||||||
* automatically increases patch number #5 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/3e3bc07576f7c7e74e3e11fc7d197cbb9a9fb8c0)
|
* automatically increases patch number #5 | [3e3bc07](https://github.com/undergroundwires/privacy.sexy/commit/3e3bc07576f7c7e74e3e11fc7d197cbb9a9fb8c0)
|
||||||
* using deployment operations from aws-static-site-with-cd | [commit](https://github.com/undergroundwires/privacy.sexy/commit/997be7113f676888892ffa35566d9ebb58a3e9ea)
|
* using deployment operations from aws-static-site-with-cd | [997be71](https://github.com/undergroundwires/privacy.sexy/commit/997be7113f676888892ffa35566d9ebb58a3e9ea)
|
||||||
* automated using bump-everywhere + more quality checks (#8) | [commit](https://github.com/undergroundwires/privacy.sexy/commit/4a91e8ccd8a707bc6bea34ee28cff7fa4f66ee2f)
|
* automated using bump-everywhere + more quality checks (#8) | [4a91e8c](https://github.com/undergroundwires/privacy.sexy/commit/4a91e8ccd8a707bc6bea34ee28cff7fa4f66ee2f)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.2...0.4.3)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.2...0.4.3)
|
||||||
|
|
||||||
## 0.4.2 (2020-02-29)
|
## 0.4.2 (2020-02-29)
|
||||||
|
|
||||||
* added missing semicolon for masking | [commit](https://github.com/undergroundwires/privacy.sexy/commit/e63ac4ae67da68243a525af149ff30e5d485b641)
|
* added missing semicolon for masking | [e63ac4a](https://github.com/undergroundwires/privacy.sexy/commit/e63ac4ae67da68243a525af149ff30e5d485b641)
|
||||||
* set font on input | [commit](https://github.com/undergroundwires/privacy.sexy/commit/0c39a06be5e4b0a2031ad5e9f5220dd669afee53)
|
* set font on input | [0c39a06](https://github.com/undergroundwires/privacy.sexy/commit/0c39a06be5e4b0a2031ad5e9f5220dd669afee53)
|
||||||
* shortened all HKEY paths | [commit](https://github.com/undergroundwires/privacy.sexy/commit/802b36bdd8dcc1f0a2853fe7da2ea2fccd69a88c)
|
* shortened all HKEY paths | [802b36b](https://github.com/undergroundwires/privacy.sexy/commit/802b36bdd8dcc1f0a2853fe7da2ea2fccd69a88c)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.1...0.4.2)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.1...0.4.2)
|
||||||
|
|
||||||
## 0.4.1 (2020-01-11)
|
## 0.4.1 (2020-01-11)
|
||||||
|
|
||||||
* fixed search bug | [commit](https://github.com/undergroundwires/privacy.sexy/commit/31364bdfec503af09ffbb58044a17dfb833fc8d9)
|
* fixed search bug | [31364bd](https://github.com/undergroundwires/privacy.sexy/commit/31364bdfec503af09ffbb58044a17dfb833fc8d9)
|
||||||
* hide grouping while searching | [commit](https://github.com/undergroundwires/privacy.sexy/commit/92f1a36bcb1e1fe7c90efe8ccd3ede55991e9d9c)
|
* hide grouping while searching | [92f1a36](https://github.com/undergroundwires/privacy.sexy/commit/92f1a36bcb1e1fe7c90efe8ccd3ede55991e9d9c)
|
||||||
* 👀🔍 showing search queries | [commit](https://github.com/undergroundwires/privacy.sexy/commit/97a7747933d2b515cc03ab8243e6a8ae702ef16a)
|
* 👀🔍 showing search queries | [97a7747](https://github.com/undergroundwires/privacy.sexy/commit/97a7747933d2b515cc03ab8243e6a8ae702ef16a)
|
||||||
* more efficient queries with single lowercase | [commit](https://github.com/undergroundwires/privacy.sexy/commit/19813b691746d98670823025c460480400e34b6e)
|
* more efficient queries with single lowercase | [19813b6](https://github.com/undergroundwires/privacy.sexy/commit/19813b691746d98670823025c460480400e34b6e)
|
||||||
* using right 🔍 input type | [commit](https://github.com/undergroundwires/privacy.sexy/commit/0ce354ea0956391ad3f37b252daac1127bfc601a)
|
* using right 🔍 input type | [0ce354e](https://github.com/undergroundwires/privacy.sexy/commit/0ce354ea0956391ad3f37b252daac1127bfc601a)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.0...0.4.1)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.4.0...0.4.1)
|
||||||
|
|
||||||
## 0.4.0 (2020-01-11)
|
## 0.4.0 (2020-01-11)
|
||||||
|
|
||||||
* 🔍 support for search | [commit](https://github.com/undergroundwires/privacy.sexy/commit/89862b2775703257b9dc2e19fbebde2c0d0fbda0)
|
* 🔍 support for search | [89862b2](https://github.com/undergroundwires/privacy.sexy/commit/89862b2775703257b9dc2e19fbebde2c0d0fbda0)
|
||||||
* more scripts & better organized | [commit](https://github.com/undergroundwires/privacy.sexy/commit/95baf3175b0d2c7df516f7893a96346b94ac8eca)
|
* more scripts & better organized | [95baf31](https://github.com/undergroundwires/privacy.sexy/commit/95baf3175b0d2c7df516f7893a96346b94ac8eca)
|
||||||
* refactorings | [commit](https://github.com/undergroundwires/privacy.sexy/commit/e3f82e069e305f6d94eab335470c8e7b44295dd6)
|
* refactorings | [e3f82e0](https://github.com/undergroundwires/privacy.sexy/commit/e3f82e069e305f6d94eab335470c8e7b44295dd6)
|
||||||
* more margin for the scripts | [commit](https://github.com/undergroundwires/privacy.sexy/commit/5ea46ecbf52236953d19f09a8eade08b83e6cd34)
|
* more margin for the scripts | [5ea46ec](https://github.com/undergroundwires/privacy.sexy/commit/5ea46ecbf52236953d19f09a8eade08b83e6cd34)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.3.0...0.4.0)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.3.0...0.4.0)
|
||||||
|
|
||||||
## 0.3.0 (2020-01-09)
|
## 0.3.0 (2020-01-09)
|
||||||
|
|
||||||
* added description & more descriptive title | [commit](https://github.com/undergroundwires/privacy.sexy/commit/99576340b648550149871e2c0fe0b0d8c2dd0d7c)
|
* added description & more descriptive title | [9957634](https://github.com/undergroundwires/privacy.sexy/commit/99576340b648550149871e2c0fe0b0d8c2dd0d7c)
|
||||||
* allow robots | [commit](https://github.com/undergroundwires/privacy.sexy/commit/eee0e785ec2c5e6bed53d21b4126a57773e35dba)
|
* allow robots | [eee0e78](https://github.com/undergroundwires/privacy.sexy/commit/eee0e785ec2c5e6bed53d21b4126a57773e35dba)
|
||||||
* removed unused references | [commit](https://github.com/undergroundwires/privacy.sexy/commit/cfd888f3afc5c260a0a4a73f2843b86b9f1df2cd)
|
* removed unused references | [cfd888f](https://github.com/undergroundwires/privacy.sexy/commit/cfd888f3afc5c260a0a4a73f2843b86b9f1df2cd)
|
||||||
* 🚫 disable NVIDIA telemetry | [commit](https://github.com/undergroundwires/privacy.sexy/commit/ab28f4ed8538d51e1777c86302a63a0cd9c3cb2a)
|
* 🚫 disable NVIDIA telemetry | [ab28f4e](https://github.com/undergroundwires/privacy.sexy/commit/ab28f4ed8538d51e1777c86302a63a0cd9c3cb2a)
|
||||||
* backwards compatibility for fonts | [commit](https://github.com/undergroundwires/privacy.sexy/commit/4bc13e11926a6df77079646499e799742153b4ab)
|
* backwards compatibility for fonts | [4bc13e1](https://github.com/undergroundwires/privacy.sexy/commit/4bc13e11926a6df77079646499e799742153b4ab)
|
||||||
* added back meta needed for responsiveness | [commit](https://github.com/undergroundwires/privacy.sexy/commit/ed872ef3d9f6c92afc0ce0d06998c60463a8b4e8)
|
* added back meta needed for responsiveness | [ed872ef](https://github.com/undergroundwires/privacy.sexy/commit/ed872ef3d9f6c92afc0ce0d06998c60463a8b4e8)
|
||||||
* fancy-font is renamed to main and now used | [commit](https://github.com/undergroundwires/privacy.sexy/commit/6825001c61426194dc363b96b57a321241f3ba57)
|
* fancy-font is renamed to main and now used | [6825001](https://github.com/undergroundwires/privacy.sexy/commit/6825001c61426194dc363b96b57a321241f3ba57)
|
||||||
* added support for grouping | [commit](https://github.com/undergroundwires/privacy.sexy/commit/ec6b3c54072a77bb4305da1c234db6c649218b88)
|
* added support for grouping | [ec6b3c5](https://github.com/undergroundwires/privacy.sexy/commit/ec6b3c54072a77bb4305da1c234db6c649218b88)
|
||||||
* less hyphens as it looks better on mobile | [commit](https://github.com/undergroundwires/privacy.sexy/commit/e0b080af69157f46ba12e2c25e794f5384671b51)
|
* less hyphens as it looks better on mobile | [e0b080a](https://github.com/undergroundwires/privacy.sexy/commit/e0b080af69157f46ba12e2c25e794f5384671b51)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.2.0...0.3.0)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.2.0...0.3.0)
|
||||||
|
|
||||||
## 0.2.0 (2020-01-06)
|
## 0.2.0 (2020-01-06)
|
||||||
|
|
||||||
* added GitHub Actions badge for build & deploy | [commit](https://github.com/undergroundwires/privacy.sexy/commit/a229aca68a92bbcd8e8176ac1dd25ce03509e074)
|
* added GitHub Actions badge for build & deploy | [a229aca](https://github.com/undergroundwires/privacy.sexy/commit/a229aca68a92bbcd8e8176ac1dd25ce03509e074)
|
||||||
* more badges 📛🏆📜 | [commit](https://github.com/undergroundwires/privacy.sexy/commit/090e8319091044e53484ba8338510f6fb7c3cb80)
|
* more badges 📛🏆📜 | [090e831](https://github.com/undergroundwires/privacy.sexy/commit/090e8319091044e53484ba8338510f6fb7c3cb80)
|
||||||
* typo fixes + whitespace refactorings | [commit](https://github.com/undergroundwires/privacy.sexy/commit/e99f210c9dcf61a21e445e2a331384b6066f2c98)
|
* typo fixes + whitespace refactorings | [e99f210](https://github.com/undergroundwires/privacy.sexy/commit/e99f210c9dcf61a21e445e2a331384b6066f2c98)
|
||||||
* switched content information to "why" section | [commit](https://github.com/undergroundwires/privacy.sexy/commit/beb3c8339f83a224ca66ad8a911a9265ffe7c9c0)
|
* switched content information to "why" section | [beb3c83](https://github.com/undergroundwires/privacy.sexy/commit/beb3c8339f83a224ca66ad8a911a9265ffe7c9c0)
|
||||||
* fixed contribution URL | [commit](https://github.com/undergroundwires/privacy.sexy/commit/7b4277d7706ccf6ba7e4b7b01aa46f8e3852cfc6)
|
* fixed contribution URL | [7b4277d](https://github.com/undergroundwires/privacy.sexy/commit/7b4277d7706ccf6ba7e4b7b01aa46f8e3852cfc6)
|
||||||
* fixed wrong relation + lighter style | [commit](https://github.com/undergroundwires/privacy.sexy/commit/8d05b03c9f3c9fc015be6615da8c283809712065)
|
* fixed wrong relation + lighter style | [8d05b03](https://github.com/undergroundwires/privacy.sexy/commit/8d05b03c9f3c9fc015be6615da8c283809712065)
|
||||||
* better URL validation | [commit](https://github.com/undergroundwires/privacy.sexy/commit/aff463dd64fecff92a786fcba88621dff6b1cf73)
|
* better URL validation | [aff463d](https://github.com/undergroundwires/privacy.sexy/commit/aff463dd64fecff92a786fcba88621dff6b1cf73)
|
||||||
* refactoring to new function | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c646c102730481c3f4648eb714dc0a84ce35b13c)
|
* refactoring to new function | [c646c10](https://github.com/undergroundwires/privacy.sexy/commit/c646c102730481c3f4648eb714dc0a84ce35b13c)
|
||||||
* optimized find queries & refactorings | [commit](https://github.com/undergroundwires/privacy.sexy/commit/d38f6cd6a8b33e11df854c7abea05974dc04d4ce)
|
* optimized find queries & refactorings | [d38f6cd](https://github.com/undergroundwires/privacy.sexy/commit/d38f6cd6a8b33e11df854c7abea05974dc04d4ce)
|
||||||
* 🎨 styled no JS error | [commit](https://github.com/undergroundwires/privacy.sexy/commit/c359f1d89c6874b3cc94154b993e33f58bd32268)
|
* 🎨 styled no JS error | [c359f1d](https://github.com/undergroundwires/privacy.sexy/commit/c359f1d89c6874b3cc94154b993e33f58bd32268)
|
||||||
* simplified finding duplicates | [commit](https://github.com/undergroundwires/privacy.sexy/commit/57037aaefcc0e80f0f4719cea89568490a731028)
|
* simplified finding duplicates | [57037aa](https://github.com/undergroundwires/privacy.sexy/commit/57037aaefcc0e80f0f4719cea89568490a731028)
|
||||||
* fixed maintainability badge URL | [commit](https://github.com/undergroundwires/privacy.sexy/commit/aaea47e7d15fe41dea26968db0107a0c53d108f3)
|
* fixed maintainability badge URL | [aaea47e](https://github.com/undergroundwires/privacy.sexy/commit/aaea47e7d15fe41dea26968db0107a0c53d108f3)
|
||||||
* fixed wrong line dumps | [commit](https://github.com/undergroundwires/privacy.sexy/commit/5ccc7c59528885ae7729197df3dfa00f924a2b3f)
|
* fixed wrong line dumps | [5ccc7c5](https://github.com/undergroundwires/privacy.sexy/commit/5ccc7c59528885ae7729197df3dfa00f924a2b3f)
|
||||||
* refactorings in parsing | [commit](https://github.com/undergroundwires/privacy.sexy/commit/2aa3742e30646bf1d1f3779419d161c3fb6c4808)
|
* refactorings in parsing | [2aa3742](https://github.com/undergroundwires/privacy.sexy/commit/2aa3742e30646bf1d1f3779419d161c3fb6c4808)
|
||||||
* using free function | [commit](https://github.com/undergroundwires/privacy.sexy/commit/20020af7c1d8de13948d8761fd4e7f0affb2badb)
|
* using free function | [20020af](https://github.com/undergroundwires/privacy.sexy/commit/20020af7c1d8de13948d8761fd4e7f0affb2badb)
|
||||||
* default selection is now none | [commit](https://github.com/undergroundwires/privacy.sexy/commit/3140cc663b86394d543de90228aa53e6a304d8d9)
|
* default selection is now none | [3140cc6](https://github.com/undergroundwires/privacy.sexy/commit/3140cc663b86394d543de90228aa53e6a304d8d9)
|
||||||
* added hyphen lines for longer names | [commit](https://github.com/undergroundwires/privacy.sexy/commit/cced601d686d550f4225018e5311b7433efbb5ae)
|
* added hyphen lines for longer names | [cced601](https://github.com/undergroundwires/privacy.sexy/commit/cced601d686d550f4225018e5311b7433efbb5ae)
|
||||||
* more descriptive subtitle | [commit](https://github.com/undergroundwires/privacy.sexy/commit/2cf9214b14d9720f747a71b3864ba7a28acf0ff4)
|
* more descriptive subtitle | [2cf9214](https://github.com/undergroundwires/privacy.sexy/commit/2cf9214b14d9720f747a71b3864ba7a28acf0ff4)
|
||||||
* added footer with version | [commit](https://github.com/undergroundwires/privacy.sexy/commit/10a34fae2f1a219ec52db0c74edb39b46ebd8abc)
|
* added footer with version | [10a34fa](https://github.com/undergroundwires/privacy.sexy/commit/10a34fae2f1a219ec52db0c74edb39b46ebd8abc)
|
||||||
* using font variables | [commit](https://github.com/undergroundwires/privacy.sexy/commit/60e6348dc8d53f1e81ebdb2ec0e1962aac1e9842)
|
* using font variables | [60e6348](https://github.com/undergroundwires/privacy.sexy/commit/60e6348dc8d53f1e81ebdb2ec0e1962aac1e9842)
|
||||||
* code-gen refactorings | [commit](https://github.com/undergroundwires/privacy.sexy/commit/246e753ddc9dc8bf630e538663584bf3423cc749)
|
* code-gen refactorings | [246e753](https://github.com/undergroundwires/privacy.sexy/commit/246e753ddc9dc8bf630e538663584bf3423cc749)
|
||||||
* added text when nothing is chosen | [commit](https://github.com/undergroundwires/privacy.sexy/commit/a7da75d4428090423b692ce45423f5bd300d8442)
|
* added text when nothing is chosen | [a7da75d](https://github.com/undergroundwires/privacy.sexy/commit/a7da75d4428090423b692ce45423f5bd300d8442)
|
||||||
|
|
||||||
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.1.0...0.2.0)
|
[compare](https://github.com/undergroundwires/privacy.sexy/compare/0.1.0...0.2.0)
|
||||||
|
|
||||||
|
|||||||
@@ -23,23 +23,6 @@
|
|||||||
- ❗ DON'T
|
- ❗ DON'T
|
||||||
- Do not update the versions, current version is only [set by the maintainer](./img/architecture/gitops.png) and updated automatically by [bump-everywhere](https://github.com/undergroundwires/bump-everywhere)
|
- Do not update the versions, current version is only [set by the maintainer](./img/architecture/gitops.png) and updated automatically by [bump-everywhere](https://github.com/undergroundwires/bump-everywhere)
|
||||||
|
|
||||||
## Guidelines
|
|
||||||
|
|
||||||
### Extend scripts
|
|
||||||
|
|
||||||
- Create a [pull request](#Pull-Request-Process) for [application.yaml](./src/application/application.yaml)
|
|
||||||
- 🙏 For any new script, try to add `revertCode` that'll revert the changes caused by the script.
|
|
||||||
- See [typings](./src/application/application.yaml.d.ts) for documentation as code.
|
|
||||||
|
|
||||||
### Handle the state in presentation layer
|
|
||||||
|
|
||||||
- There are two types of components:
|
|
||||||
- **Stateless**, extends `Vue`
|
|
||||||
- **Stateful**, extends [`StatefulVue`](./src/presentation/StatefulVue.ts)
|
|
||||||
- The source of truth for the state lies in application layer (`./src/application/`) and must be updated from the views if they're mutating the state
|
|
||||||
- They mutate or/and reacts to changes in [application state](src/application/State/ApplicationState.ts).
|
|
||||||
- You can react by getting the state and listening to it and update the view accordingly in [`mounted()`](https://vuejs.org/v2/api/#mounted) method.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
By contributing, you agree that your contributions will be licensed under its GNU General Public License v3.0.
|
By contributing, you agree that your contributions will be licensed under its GNU General Public License v3.0.
|
||||||
|
|||||||
48
README.md
48
README.md
@@ -1,6 +1,6 @@
|
|||||||
# privacy.sexy
|
# privacy.sexy
|
||||||
|
|
||||||
> Enforce privacy & security best-practices on Windows, because privacy is sexy 🍑🍆
|
> Enforce privacy & security best-practices on Windows and macOS, because privacy is sexy 🍑🍆
|
||||||
|
|
||||||
[](./CONTRIBUTING.md)
|
[](./CONTRIBUTING.md)
|
||||||
[](https://lgtm.com/projects/g/undergroundwires/privacy.sexy/context:javascript)
|
[](https://lgtm.com/projects/g/undergroundwires/privacy.sexy/context:javascript)
|
||||||
@@ -14,27 +14,31 @@
|
|||||||
|
|
||||||
## Get started
|
## Get started
|
||||||
|
|
||||||
- Online version: [https://privacy.sexy](https://privacy.sexy)
|
- Online version at [https://privacy.sexy](https://privacy.sexy)
|
||||||
- or download latest desktop version for [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.1/privacy.sexy-Setup-0.7.1.exe), [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.1/privacy.sexy-0.7.1.AppImage), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.7.1/privacy.sexy-0.7.1.dmg)
|
- 💡 No need to run any compiled software on your computer.
|
||||||
- 💡 Come back regularly to apply latest version for stronger privacy and security.
|
- Alternatively download offline version for [Windows](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-Setup-0.9.2.exe), [macOS](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-0.9.2.dmg) or [Linux](https://github.com/undergroundwires/privacy.sexy/releases/download/0.9.2/privacy.sexy-0.9.2.AppImage).
|
||||||
|
- 💡 Single click to execute your script.
|
||||||
|
- ❗ Come back regularly to apply latest version for stronger privacy and security.
|
||||||
|
|
||||||
[](https://privacy.sexy)
|
[](https://privacy.sexy)
|
||||||
|
|
||||||
## Why
|
## Why
|
||||||
|
|
||||||
- You don't need to run any compiled software that has access to your system, just run the generated scripts.
|
- Rich tweak pool to harden security & privacy of the OS and other software on it
|
||||||
- Have full visibility into what the tweaks do as you enable them.
|
- Free (both free as in beer and free as in speech)
|
||||||
- Ability to revert applied scripts
|
- No need to run any compiled software that has access to your system, just run the generated scripts
|
||||||
|
- Have full visibility into what the tweaks do as you enable them
|
||||||
|
- Ability to revert (undo) applied scripts
|
||||||
|
- Everything is transparent: both application and its infrastructure are open-source and automated
|
||||||
- Easily extendable
|
- Easily extendable
|
||||||
- Everything is open-sourced including both application and infrastructure
|
|
||||||
- Fully automated CI/CD pipeline using GitHub actions
|
|
||||||
- to AWS for provisioning serverless infrastructure
|
|
||||||
- for building and sharing the desktop applications
|
|
||||||
|
|
||||||
## Extend scripts
|
## Extend scripts
|
||||||
|
|
||||||
- Fork it & add more scripts in [application.yaml](src/application/application.yaml) and send a pull request 👌
|
1. Fork the repository
|
||||||
- 📖 More: [extend scripts | CONTRIBUTING.md](./CONTRIBUTING.md#extend-scripts)
|
2. Add more scripts in respective script collection in [collections](src/application/collections/) folder.
|
||||||
|
- 📖 If you're unsure about the syntax you can refer to the [collection files | documentation](docs/collection-files.md).
|
||||||
|
- 🙏 For any new script, please add `revertCode` and `docs` values if possible.
|
||||||
|
3. Send a pull request 👌
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
@@ -49,25 +53,17 @@
|
|||||||
- Development: `npm run serve` to compile & hot-reload for development.
|
- Development: `npm run serve` to compile & hot-reload for development.
|
||||||
- Production: `npm run build` to prepare files for distribution.
|
- Production: `npm run build` to prepare files for distribution.
|
||||||
- Or run using Docker:
|
- Or run using Docker:
|
||||||
1. Build: `docker build -t undergroundwires/privacy.sexy:0.7.1 .`
|
1. Build: `docker build -t undergroundwires/privacy.sexy:0.9.2 .`
|
||||||
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy-0.7.1 undergroundwires/privacy.sexy:0.7.1`
|
2. Run: `docker run -it -p 8080:80 --rm --name privacy.sexy-0.9.2 undergroundwires/privacy.sexy:0.9.2`
|
||||||
|
|
||||||
## Architecture
|
## Architecture overview
|
||||||
|
|
||||||
### Application
|
### Application
|
||||||
|
|
||||||
- Powered by **TypeScript**, **Vue.js** and **Electron** 💪
|
- Powered by **TypeScript**, **Vue.js** and **Electron** 💪
|
||||||
- and driven by **Domain-driven design**, **Event-driven architecture**, **Data-driven programming** concepts.
|
- and driven by **Domain-driven design**, **Event-driven architecture**, **Data-driven programming** concepts.
|
||||||
- Application uses highly decoupled models & services in different DDD layers.
|
- Application uses highly decoupled models & services in different DDD layers.
|
||||||
- **Domain layer** is where the application is modelled with validation logic.
|
- 📖 Read more on • [Presentation](./docs/presentation.md) • [Application](./docs/application.md)
|
||||||
- **Presentation Layer**
|
|
||||||
- Consists of Vue.js components and other UI-related code.
|
|
||||||
- Desktop application is created using [Electron](https://www.electronjs.org/).
|
|
||||||
- Event driven as in components simply listens to events from the state and act accordingly.
|
|
||||||
- **Application Layer**
|
|
||||||
- Keeps the application state
|
|
||||||
- The [state](src/application/State/ApplicationState.ts) is a mutable singleton & event producer.
|
|
||||||
- The application is defined & controlled in a [single YAML file](src/application/application.yaml) (see [Data-driven programming](https://en.wikipedia.org/wiki/Data-driven_programming))
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
5
babel.config.js
Normal file
5
babel.config.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
'@vue/cli-plugin-babel/preset'
|
||||||
|
]
|
||||||
|
}
|
||||||
22
docs/application.md
Normal file
22
docs/application.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Application
|
||||||
|
|
||||||
|
- It's mainly responsible for
|
||||||
|
- creating and event based [application state](#application-state)
|
||||||
|
- parsing and compiling [application data](#application-data)
|
||||||
|
|
||||||
|
## Application state
|
||||||
|
|
||||||
|
- [ApplicationContext.ts](./../src/application/Context/ApplicationContext.ts) holds the [CategoryCollectionState](./../src/application/Context/State/CategoryCollectionState.ts) for each OS
|
||||||
|
- Uses [state pattern](https://en.wikipedia.org/wiki/State_pattern)
|
||||||
|
- Same instance is shared throughout the application to ensure consistent state
|
||||||
|
- 📖 See [Application State | Presentation layer](./presentation.md#application-state) to read more about how the state should be managed by the presentation layer.
|
||||||
|
- 📖 See [ApplicationContext.ts](./../src/application/Context/ApplicationContext.ts) to start diving into the state code.
|
||||||
|
|
||||||
|
## Application data
|
||||||
|
|
||||||
|
- Compiled to `Application` domain object.
|
||||||
|
- The scripts are defined and controlled in different data files per OS
|
||||||
|
- Enables [data-driven programming](https://en.wikipedia.org/wiki/Data-driven_programming) and easier contributions
|
||||||
|
- Application data is defined in collection files and
|
||||||
|
- 📖 See [Application data | Presentation layer](./presentation.md#application-data) to read how the application data is read by the presentation layer.
|
||||||
|
- 📖 See [collection files documentation](./collection-files.md) to read more about how the data files are structured/defined and see [collection yaml files](./../src/application/collections/) to directly check the code.
|
||||||
186
docs/collection-files.md
Normal file
186
docs/collection-files.md
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
# Collection files
|
||||||
|
|
||||||
|
- privacy.sexy is a data-driven application where it reads the necessary OS-specific logic from yaml files in [`application/collections`](./../src/application/collections/)
|
||||||
|
- 💡 Best practices
|
||||||
|
- If you repeat yourself, try to utilize [YAML-defined functions](#Function)
|
||||||
|
- Always try to add documentation and a way to revert a tweak in [scripts](#Script)
|
||||||
|
- 📖 Types in code: [`collection.yaml.d.ts`](./../src/application/collections/collection.yaml.d.ts)
|
||||||
|
|
||||||
|
## Objects
|
||||||
|
|
||||||
|
### `Collection`
|
||||||
|
|
||||||
|
- A collection simply defines:
|
||||||
|
- different categories and their scripts in a tree structure
|
||||||
|
- OS specific details
|
||||||
|
- Also allows defining common [function](#Function)s to be used throughout the collection if you'd like different scripts to share same code.
|
||||||
|
|
||||||
|
#### `Collection` syntax
|
||||||
|
|
||||||
|
- `os:` *`string`* (**required**)
|
||||||
|
- Operating system that the [Collection](#collection) is written for.
|
||||||
|
- 📖 See [OperatingSystem.ts](./../src/domain/OperatingSystem.ts) enumeration for allowed values.
|
||||||
|
- `actions: [` ***[`Category`](#Category)*** `, ... ]` **(required)**
|
||||||
|
- Each [category](#category) is rendered as different cards in card presentation.
|
||||||
|
- ❗ A [Collection](#collection) must consist of at least one category.
|
||||||
|
- `functions: [` ***[`Function`](#Function)*** `, ... ]`
|
||||||
|
- Functions are optionally defined to re-use the same code throughout different scripts.
|
||||||
|
- `scripting:` ***[`ScriptingDefinition`](#ScriptingDefinition)*** **(required)**
|
||||||
|
- Defines the scripting language that the code of other action uses.
|
||||||
|
|
||||||
|
### `Category`
|
||||||
|
|
||||||
|
- Category has a parent that has tree-like structure where it can have subcategories or subscripts.
|
||||||
|
- It's a logical grouping of different scripts and other categories.
|
||||||
|
|
||||||
|
#### `Category` syntax
|
||||||
|
|
||||||
|
- `category:` *`string`* (**required**)
|
||||||
|
- Name of the category
|
||||||
|
- ❗ Must be unique throughout the [Collection](#collection)
|
||||||
|
- `children: [` ***[`Category`](#Category)*** `|` [***`Script`***](#Script) `, ... ]` (**required**)
|
||||||
|
- ❗ Category must consist of at least one subcategory or script.
|
||||||
|
- Children can be combination of scripts and subcategories.
|
||||||
|
|
||||||
|
### `Script`
|
||||||
|
|
||||||
|
- Script represents a single tweak.
|
||||||
|
- A script must include either:
|
||||||
|
- A `code` and `revertCode`
|
||||||
|
- Or `call` to call YAML-defined functions
|
||||||
|
- 🙏 For any new script, please add `revertCode` and `docs` values if possible.
|
||||||
|
|
||||||
|
#### `Script` syntax
|
||||||
|
|
||||||
|
- `name`: *`string`* (**required**)
|
||||||
|
- Name of the script
|
||||||
|
- ❗ Must be unique throughout the [Collection](#collection)
|
||||||
|
- E.g. `Disable targeted ads`
|
||||||
|
- `code`: *`string`* (may be **required**)
|
||||||
|
- Batch file commands that will be executed
|
||||||
|
- 💡 If defined, best practice to also define `revertCode`
|
||||||
|
- ❗ If not defined `call` must be defined, do not define if `call` is defined.
|
||||||
|
- `revertCode`: `string`
|
||||||
|
- Code that'll undo the change done by `code` property.
|
||||||
|
- E.g. let's say `code` sets an environment variable as `setx POWERSHELL_TELEMETRY_OPTOUT 1`
|
||||||
|
- then `revertCode` should be doing `setx POWERSHELL_TELEMETRY_OPTOUT 0`
|
||||||
|
- ❗ Do not define if `call` is defined.
|
||||||
|
- `call`: ***[`FunctionCall`](#FunctionCall)*** | `[` ***[`FunctionCall`](#FunctionCall)*** `, ... ]` (may be **required**)
|
||||||
|
- A shared function or sequence of functions to call (called in order)
|
||||||
|
- ❗ If not defined `code` must be defined
|
||||||
|
- `docs`: *`string`* | `[`*`string`*`, ... ]`
|
||||||
|
- Single documentation URL or list of URLs for those who wants to learn more about the script
|
||||||
|
- E.g. `https://docs.microsoft.com/en-us/windows-server/`
|
||||||
|
- `recommend`: `"standard"` | `"strict"` | `undefined` (default)
|
||||||
|
- If not defined then the script will not be recommended
|
||||||
|
- If defined it can be either
|
||||||
|
- `standard`: Only non-breaking scripts without limiting OS functionality
|
||||||
|
- `strict`: Scripts that can break certain functionality in favor of privacy and security
|
||||||
|
|
||||||
|
### `FunctionCall`
|
||||||
|
|
||||||
|
- Describes a single call to a function by optionally providing values to its parameters.
|
||||||
|
- 👀 See [parameter substitution](#parameter-substitution) for an example usage
|
||||||
|
|
||||||
|
#### `FunctionCall` syntax
|
||||||
|
|
||||||
|
- `function`: *`string`* (**required**)
|
||||||
|
- Name of the function to call.
|
||||||
|
- ❗ Function with same name must defined in `functions` property of [Collection](#collection)
|
||||||
|
- `parameters`: `[ parameterName:` *`parameterValue`*`, ... ]`
|
||||||
|
- Defines key value dictionary for each parameter and its value
|
||||||
|
- E.g.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
parameters:
|
||||||
|
userDefinedParameterName: parameterValue
|
||||||
|
# ...
|
||||||
|
appName: Microsoft.WindowsFeedbackHub
|
||||||
|
```
|
||||||
|
|
||||||
|
### `Function`
|
||||||
|
|
||||||
|
- Functions allow re-usable code throughout the defined scripts.
|
||||||
|
- Functions are templates compiled by privacy.sexy and uses special [expressions](#expressions).
|
||||||
|
- Functions can call other functions by defining `call` property instead of `code`
|
||||||
|
- 👀 See [parameter substitution](#parameter-substitution) for an example usage
|
||||||
|
|
||||||
|
#### Expressions
|
||||||
|
|
||||||
|
- Expressions are defined inside mustaches (double brackets, `{{` and `}}`)
|
||||||
|
|
||||||
|
##### Parameter substitution
|
||||||
|
|
||||||
|
A simple function example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
function: EchoArgument
|
||||||
|
parameters: [ 'argument' ]
|
||||||
|
code: Hello {{ $argument }} !
|
||||||
|
```
|
||||||
|
|
||||||
|
It would print "Hello world" if it's called in a [script](#script) as following:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
script: Echo script
|
||||||
|
call:
|
||||||
|
function: EchoArgument
|
||||||
|
parameters:
|
||||||
|
argument: World
|
||||||
|
```
|
||||||
|
|
||||||
|
A function can call other functions such as:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
-
|
||||||
|
function: CallerFunction
|
||||||
|
parameters: [ 'value' ]
|
||||||
|
call:
|
||||||
|
function: EchoArgument
|
||||||
|
parameters:
|
||||||
|
argument: {{ $value }}
|
||||||
|
-
|
||||||
|
function: EchoArgument
|
||||||
|
parameters: [ 'argument' ]
|
||||||
|
code: Hello {{ $argument }} !
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `Function` syntax
|
||||||
|
|
||||||
|
- `name`: *`string`* (**required**)
|
||||||
|
- Name of the function that scripts will use.
|
||||||
|
- Convention is to use camelCase, and be verbs.
|
||||||
|
- E.g. `uninstallStoreApp`
|
||||||
|
- ❗ Function names must be unique
|
||||||
|
- `parameters`: `[` *`string`* `, ... ]`
|
||||||
|
- Name of the parameters that the function has.
|
||||||
|
- Parameter values are provided by a [Script](#script) through a [FunctionCall](#FunctionCall)
|
||||||
|
- Parameter names must be defined to be used in [expressions](#expressions)
|
||||||
|
- ❗ Parameter names must be unique
|
||||||
|
`code`: *`string`* (**required** if `call` is undefined)
|
||||||
|
- Batch file commands that will be executed
|
||||||
|
- 💡 If defined, best practice to also define `revertCode`
|
||||||
|
- ❗ If not defined `call` must be defined
|
||||||
|
- `revertCode`: *`string`*
|
||||||
|
- Code that'll undo the change done by `code` property.
|
||||||
|
- E.g. let's say `code` sets an environment variable as `setx POWERSHELL_TELEMETRY_OPTOUT 1`
|
||||||
|
- then `revertCode` should be doing `setx POWERSHELL_TELEMETRY_OPTOUT 0`
|
||||||
|
- `call`: ***[`FunctionCall`](#FunctionCall)*** | `[` ***[`FunctionCall`](#FunctionCall)*** `, ... ]` (may be **required**)
|
||||||
|
- A shared function or sequence of functions to call (called in order)
|
||||||
|
- The parameter values that are sent can use [expressions](#expressions)
|
||||||
|
- ❗ If not defined `code` must be defined
|
||||||
|
|
||||||
|
### `ScriptingDefinition`
|
||||||
|
|
||||||
|
- Defines global properties for scripting that's used throughout its parent [Collection](#collection).
|
||||||
|
|
||||||
|
#### `ScriptingDefinition` syntax
|
||||||
|
|
||||||
|
- `language:` *`string`* (**required**)
|
||||||
|
- 📖 See [ScriptingLanguage.ts](./../src/domain/ScriptingLanguage.ts) enumeration for allowed values.
|
||||||
|
- `startCode:` *`string`* (**required**)
|
||||||
|
- Code that'll be inserted on top of user created script.
|
||||||
|
- Global variables such as `$homepage`, `$version`, `$date` can be used using [parameter substitution](#parameter-substitution) code syntax such as `Welcome to {{ $homepage }}!`
|
||||||
|
- `endCode:` *`string`* (**required**)
|
||||||
|
- Code that'll be inserted at the end of user created script.
|
||||||
|
- Global variables such as `$homepage`, `$version`, `$date` can be used using [parameter substitution](#parameter-substitution) code syntax such as `Welcome to {{ $homepage }}!`
|
||||||
24
docs/presentation.md
Normal file
24
docs/presentation.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Presentation layer
|
||||||
|
|
||||||
|
- Consists of Vue.js components and other UI-related code.
|
||||||
|
- Desktop application is created using [Electron](https://www.electronjs.org/).
|
||||||
|
- Event driven as in components simply listens to events from the state and act accordingly.
|
||||||
|
|
||||||
|
## Application data
|
||||||
|
|
||||||
|
- Components and should use [ApplicationFactory](./../src/application/ApplicationFactory.ts) singleton to reach the application domain.
|
||||||
|
- [Application.ts](../src/domain/Application.ts) domain model is the stateless application representation including
|
||||||
|
- available scripts, collections as defined in [collection files](./collection-files.md)
|
||||||
|
- package information as defined in [`package.json`](./../package.json)
|
||||||
|
- 📖 See [Application data | Application layer](./presentation.md#application-data) where application data is parsed and compiled.
|
||||||
|
|
||||||
|
## Application state
|
||||||
|
|
||||||
|
- Stateful components mutate or/and react to state changes in [ApplicationContext](./../src/application/Context/ApplicationContext.ts).
|
||||||
|
- Stateless components that does not handle state extends `Vue`
|
||||||
|
- Stateful components that depends on the collection state such as user selection, search queries and more extends [`StatefulVue`](./../src/presentation/StatefulVue.ts)
|
||||||
|
- The single source of truth is a singleton of the state created and made available to presentation layer by [`StatefulVue`](./../src/presentation/StatefulVue.ts)
|
||||||
|
- `StatefulVue` includes abstract `handleCollectionState` that is fired once the component is loaded and also each time [collection](./collection-files.md) is changed.
|
||||||
|
- Do not forget to subscribe from events when component is destroyed or if needed [collection](./collection-files.md) is changed.
|
||||||
|
- 💡 `events` in base class [`StatefulVue`](./../src/presentation/StatefulVue.ts) makes lifecycling easier
|
||||||
|
- 📖 See [Application state | Application layer](./presentation.md#application-state) where the state is implemented using using state pattern.
|
||||||
29
docs/tests.md
Normal file
29
docs/tests.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Unit tests
|
||||||
|
|
||||||
|
- Unit tests are defined in [`./tests`](./../tests)
|
||||||
|
- They follow same folder structure as [`./src`](./../src)
|
||||||
|
|
||||||
|
## Naming
|
||||||
|
|
||||||
|
- Each test suite first describe the system under test
|
||||||
|
- E.g. tests for class `Application` is categorized under `Application`
|
||||||
|
- Tests for specific methods are categorized under method name (if applicable)
|
||||||
|
- E.g. test for `run()` is categorized under `run`
|
||||||
|
|
||||||
|
## Act, arrange, assert
|
||||||
|
|
||||||
|
- Tests use act, arrange and assert (AAA) pattern when applicable
|
||||||
|
- **Arrange**
|
||||||
|
- Should set up the test case
|
||||||
|
- Starts with comment line `// arrange`
|
||||||
|
- **Act**
|
||||||
|
- Should cover the main thing to be tested
|
||||||
|
- Starts with comment line `// act`
|
||||||
|
- **Assert**
|
||||||
|
- Should elicit some sort of response
|
||||||
|
- Starts with comment line `// assert`
|
||||||
|
|
||||||
|
## Stubs
|
||||||
|
|
||||||
|
- Stubs are defined in [`./tests/stubs`](./../tests/unit/stubs)
|
||||||
|
- They implement dummy behavior to be functional
|
||||||
@@ -1 +1 @@
|
|||||||
<mxfile host="www.draw.io" modified="2019-12-27T03:04:27.829Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36" etag="O-1eaon4mqUmgvki0auB" version="12.4.3" pages="1"><diagram id="rhL8jzEM8kVVyiS98U7u" name="Page-1">3Zpdk6I4FIZ/jZdakPDlpa3tzlTNbnVVV83OzE1XhACZAUKF2Or8+k0wCBhau1f8GrpayUkC5HlzTg7IAE7T9V8M5fHfNMDJABjBegBnAwA8YIpPadhsDS50t4aIkWBrMmvDM/mNldFQ1iUJcNFqyClNOMnbRp9mGfZ5y4YYo6t2s5Am7bPmKMKa4dlHiW79lwQ8VsOyjdr+CZMors5sGqomRVVjZShiFNBVwwQfB3DKKOXbvXQ9xYlkV3HZ9pu/Ubu7MIYz/p4OD0/efJxMXmZfs6kd/vj2Txp+HlrVxfFNNWIcCACqSBmPaUQzlDzW1gdGl1mA5WENUarbfKE0F0ZTGH9izjdKTbTkVJhiniaqFq8J/ya7j2xV+t6oma3VkcvCpipknG0anWTxe7Ou7laWqn4FZ/QXntKEsnJ8cFxuomY7cjncN4kqU0GXzMcHMFYzE7EI8wPtwE534S+YplhcqejHcII4eW1fB1IzN9q1q8UVO0rfj2gNrqL1TreWarWI96AbPFG3suuEMbRpNMgpyXjROPKTNIgGKnZC5Zsqctp77n24NTDtvQmzPX09fXbjOGFGwatGj0bsMEbAfmf4uONpaF0zfKjjvqJkqc70xHAhxirOTTNtIrRlXsWE4+cclRhWIlNoSxqSJGkwDmzsBVYXfQ8soOPIHjTj1TyrrgwzjteHxdDhqQ6O23Yf5U2res2H1coeN9Z7xzgTbehc07XMlmu907PMtmeBm3AtcCHX+n8RftwO2iZsBe2j7YHrnj/IQ+9eUsSbmlCnpgwnRQ+gxepJnifE7yNUtwKvFrpDW/51ieGUmzpCw77ddiKdFMXtdhTf3Yw1wzjoCOPu2cK4fS/Oc9P3V/AeEiSoOd2Mpoj0mxotzCAIO7mbhgvH+Ayp0XjPqca6UwGrw6nsczmVpYH+nIUMCSJLny8Z7hV46PnY97uALzzbso0zAHf3clGnA7h3ySjmaMDxK1aZzRugzY+DDrHTDTpwxwvD6GeF8PbYujpbtwMtOBdaV0PLcE4Lwqk6+F3jhR0L8EXxenqoeMw44ffIdj8uXB3uWIPLY4ZRQLLoD8B79dBg6ll8Kn9e6TfsLpDvBbALLoCWZQf9wBXJSRuuYelw7ZHZgRecC6+er4ldEhy7R7pVxMA2R+Obg2xrkAuO+KEU7R18e6C15+xm9ZTjiqjOk2X1MbOc47DMrqej52Olp02o+YDDSGhE/NsDZ+pLymXBVWPoBjfaiNFfG9rtMdMXCg1SEaNc7pK0fJ+giUTCEHyTSUKiTNi4fIizs35BC5w8yYRfTlw4W1DOaSoaJLLiAfm/olKAVjokN9GkPNmkyLfvPcg0CFWFkKylZA/qemYx5/KFiYkkAeZ+kFkj4tMsJEJaNvLFGcFcrHxIfEm7iDlz4UK0GKIsGC6Y+JQmW6Ykc+i4L1+X+GfxIpuINMUb5VXG1+t9r60Jb1/yMQPQ16771x1+WPchCugC79QHnvfyjIqiR91NcGPC6yvx/QtvHhV+ka3Ep5B1Lf7FnlgYpFk+3Sp6Uhq4+zkqBCNdbQh1tStb/2rrucT9q20cVTukLMLZsMBU/rI/d8Stwjwn5fPTYkhzTlLyu0wKenR0WN0O7MTXpbc6pLc+LL0o1m/WbX8JrV9PhI//AQ==</diagram></mxfile>
|
<mxfile host="Electron" modified="2021-01-31T12:32:01.751Z" agent="5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.1.8 Chrome/87.0.4280.88 Electron/11.1.1 Safari/537.36" etag="OTbSPW1ZOLwiPL6mt-j9" version="14.1.8" type="device"><diagram id="rhL8jzEM8kVVyiS98U7u" name="Page-1">3VtZd6JKF/01/dhZjA6PREjCXRbGFpM2L70QCYIoLsUI/PpvnwKcMD3cazrJl6wEqfHU3vvsKoz5Infm6e3KWU5ZPPGiL5IwSb/I+hdJUsUmflNBVhQoDaEo8FfBpCgS9wWDIPfKwqrZJph466OGSRxHSbA8LnTjxcJzk6MyZ7WKt8fNnuPoeNal43u1goHrRPXSx2CSTIvSlirsy++8wJ9WM4tCWTN3qsZlwXrqTOLtQZFsfJE7qzhOilfztONFhF2FS9Hv5pXaXWArb5H8Tofr+9ZNO9J+6A+Ljvr89N2aP5tflSq4JKtW7E0AQHkbr5Jp7McLJzL2pdereLOYeDSsgLt9m24cL1EoojD0kiQr2XQ2SYyiaTKPylovDZLv1P1KLe9GBzV6Wo7Mb7LqZpGssoNOdDs6rNt343dVv3WyimdeJ47iFV+f3OZfqKkDWGK6jjcr1/sJapUQnZXvJT9pJxXtCNGDCUp6br147iFSNFh5kZMEL8eSc0rl+rt2e3LxouT3T7iW3oXrHW9HrO1J/IC8yZfmjXfVVisnO2iwjINFsj4Y+Z4K0KD0TrnMzdI51ZP0/nlrSVRPBFNMv5fPbh3/QVHyu7rHgXcIV5L6m/bxeWSofCj7KMd9caJNOdP9yltj8Zg7XtSEcEzzdhok3mDpcFy2OCkcU/ocRNEBxhPVa02Uc+i3pLHcaFCPeJFUOjuzFVbBeqvES38KXlnbaB6nT5lN2/2eL1c7+/Rgv69OMxdHW268Z2qJR6n1m5klHmeW9B6pJb1Xav07h28fm7YoH5n2L9tLzebbm7zc+ixHxPcU1MWPDP/JPaSaV2vLZRS4l7DqI+OtWfezSt/nyGjwr3KEg/Li62ck/b6Lq8cuvnsYO7Rx6YyNN9/MxtXPkjwf6flK/pQHJLmWdHo8d4LLHo3G4mTyfBZ3UWjKbe8Njkbtk6Rq15NKUs4klfpWSaXUgDYXzysHiGzcZLPyLgr4c8v1XPcc4OOWqqjCGwDePDmLNs4A3vqbLtaoAe69eOXJ5hWgxT8H+tlrnAd60myPBeEyO0TrBNtmHdvmGWilt4K2WYN25S3jdZDE5eCfGl75zAb8V+Ft1a3CWCRB8hmxPfWFdwe3XQM3ma48ZxIs/P8DeN/dGsT6KX5Of165rO2OBU/2GufAFbyW0GpdBlwcTo7BFZQ6uOqVeAZe6a3grZ/X8DKY/OoZ6aNCLKniVfvDgazWQF4nTvKzI9qf42vo9H0ZFE9MQKze/XhHCP/K6euSGJ6+mXoORPHcu6lvh2H9mOUcviEiRLEfuJ8HULG+Nf1dQHdr2AOazamXG0eR5xKqH1efHw/N+lZUA289dZb0MpjzTywcQkUrh5QjLQr8BcoSeptoV9p1xl50T48UJHVZH8dJEs/RIKKKa8ed+ZyYowMXfaEJn0xbL4tPVtBBy6lunoOUqLwu49GnSUIfydAICenGnSyUq8CNF88BKF9duZhRusHe6uBC5VDHDZIuXn91FpOv4xV+U5FKh54budH88bDxwvUPaoKDUOtqWZ0pL/pk3aa/UpxyryhXap38fenl6a9vkp+ffvmP6f/qTOKxtxOB1Gr9GDjr9QXpl9TWVVP9PQlI5zUgvZkI6tv85xeB+EsRjBdb/AbFKX7wCtsyFdNbausLsS7LyhHlcuOqVT+QSO0zht9+K7Lr55HPT7bwS7Kf45XvLb6uvZg+TXDTAC83y4C/Z7v+Gi+TYB7k/ER2wZzfvUtSsS/XqK/0cUh9VfZfqH/Y3Hrj5vegr7fv2awhLwLh8cyf5n7J/CWIPS+Z8+Qe8V/RzamUteJWulm/gJzrlM58nfs7S3rKrpXxY7pxcyFw7r4Jrh6/dOWJPMlUmWXqizt3X1iobVmnnU/mbmDeTZZPd9/i+4GZWfYoMG+nkfM4iSe6ELBwKJnBteQ8Psj9eVtBm62paz4v103RCkzMfX/r+k/zaD1Gj/G8vXkamMV9R8wmj2l0P/gnmswfNmPp28wMldZIirKRlEbm7dNyfLttmwHL+uE/N0wwMLtFs6Qs9Om1unt9Z7bN0Mh6HfPlPkwXB33Vb7OH62/hLCjLEnfxsH6yi1i8+UM2zniUd9fTya3vPyFK2zawfkVkuulbubGxwijs2qbUBS7WQBC6oZtbgSBYgSJaobthoZl27SGVSyzQUqujCMweJqhPcfWZrW0se5Z17f6G5SMZ2KDtKLcGGq6mYOpMxb1gzY0MV8nKtOoKPA2fdajdKMOcVC4yiSVWpsiWbSbMZhjbxNgzxDFCHKZIYzEepylYmZAjnhx1PuJRmO6jD9aUz1LiqBsaQq8jpKjLMJZv6RjH9uWubaTd0M+tx3MxaRTTpmcPJawb8/Zlby4kWBvKZqqpu2jLtpbEUo4jxwBz2kOxWLshW4GWsUDJe3bfZ/kM8ZBmGOZkSq+j5bQ+FjJoiWL1wYO76el+jv4y4tiygaaijYR+GBu42po0sk1wxfEtr4hzoG27wIjpmkj4WzraZVgvjU9zow/TXQXrABY+8Qeeh4SJivi2TGcJHz830MYgvMCvoIBrzkcP2Fq8DeFPPDDU9WX0zxnVvcqpkHfDmQAN4DpUvYArdzv6/i02b/ttcyakPYo3NGl9W8xHvFPcWyg+QY5izQblGcadIXcFgc+n+xwP8CsWmhymLBBIu+grEB8CcEW8Ptqwck0zWgv0CDz1IepGGLt/Hs8O8BwoWyuc+Wifs9wKGdeARtio4C4j3Vvh0IfuVHALfg1gPEOsBtbaV0x9RPFluE8pZ4ABrn3oxkQe+FuKE30zWgt+gP1MfY1bU+8Tf9Ay8kDvS6RDi17nlAsjhWvtkdY7pHFIY4h1poInmluxOhrmdIUe8gXYiozj7UNrTCy4nAms0KqAssQKSQt96Jj0MiIfkICpwmwXGoWOwdPrsRJOrgz8ZCt/CLkubZYjZ0n3AmLJMJZq6W5i0Rj5CJgMEYNJmMiESY+0w/EeIUcpTkMs8sYAf8CNuAk06Arj5CbnGXy/ih/4Jx3JRR4b4hkdKtxrMi3t6S7laT7KMa+tCUUu+6RB4lXqwc8QP7h3eU739D7mIe0apPuUUUz6kDREeKo9e5T0qL3OuEYseFGXvIzy5/bVvCFNy/C3jPN2W3ohjYs1kkd0aT2hKUKLaW+gKD3ySfJpvQ//MEhjyG3kAvyD8XgE0qxI8XA/DYeUx7S2DJiCY7STXo0HOsB6uIZd1ZKXCTiBRkzu9z19BLwoj42kyEsT+qdYfLHUYIo4Ea+m0N6CeAXue1inRdjkM65dC+OAb8xtSow8PSM9ukmP+1c/ezVXqd4eCZQnaC+McoPvNSzTuIfhWuwPpF/eZkQ5grWT12jEPfj0aayUv87dpPBt4piwYrTPUR5R/iiv40T+oEHPtA/McuSpCK1k2DtoPInZ/4RYM+FAuSgSLvBZeBe45X7F84G4zfg+m1VtuYbLMu20n1/1IzzIO7G/kW/tvL+o2/Xf9ava0rqrGE777eYF5zx/4Iamfj0lbjAW4uvnZZ7Bi4wyV3gcx/WYAzGU9dcN2+7THqLynON7Vz8d5aSZ4UE8/dN4hAMcgAnXu0px4QwjHuC2679fB28LXWrJHhPe73DMPaaFXgn7Au+BdgbvPTZFjgAdySjXDB/RWbVu0jr5vQLfOq2vtFPUL+Kgmyst9/ZGcDrXM5wcLcxH5wHSqkjnLkv/Fv4Rd3WshDpW7BQr9V9j1flbWGEs7rczn2so9zOce6CxmVLstxo8XeBeWJwrNRWemvL9Jx8mHMP8aQo/ynCu86trNU9RT35J50BXIo/r2eRptNe78B/yf9pvyZ/orGls6ZxSxK3RtYxBK2OqYtCKmIr85vtOEdNTwwxadFLvtBf34fblCUroyniiyRV6hrrMnz8l+Uo9fuNJlurPoY0zz6GNP34Oxe3+v8qKTwHv/zVPNv4H</diagram></mxfile>
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 89 KiB |
4460
package-lock.json
generated
4460
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
66
package.json
66
package.json
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "privacy.sexy",
|
"name": "privacy.sexy",
|
||||||
"version": "0.7.1",
|
"version": "0.9.2",
|
||||||
"author": "undergroundwires",
|
|
||||||
"description": "Enforce privacy & security best-practices on Windows, because privacy is sexy 🍑🍆",
|
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"description": "Enforce privacy & security best-practices on Windows and macOS, because privacy is sexy 🍑🍆",
|
||||||
|
"author": "undergroundwires",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
@@ -21,46 +21,54 @@
|
|||||||
},
|
},
|
||||||
"main": "background.js",
|
"main": "background.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.30",
|
"@fortawesome/fontawesome-svg-core": "^1.2.32",
|
||||||
"@fortawesome/free-brands-svg-icons": "^5.14.0",
|
"@fortawesome/free-brands-svg-icons": "^5.15.1",
|
||||||
"@fortawesome/free-regular-svg-icons": "^5.14.0",
|
"@fortawesome/free-regular-svg-icons": "^5.15.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.14.0",
|
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||||
"@fortawesome/vue-fontawesome": "^0.1.10",
|
"@fortawesome/vue-fontawesome": "^2.0.2",
|
||||||
"ace-builds": "^1.4.12",
|
"ace-builds": "^1.4.12",
|
||||||
"file-saver": "^2.0.2",
|
"core-js": "^3.6.5",
|
||||||
"inversify": "^5.0.1",
|
"file-saver": "^2.0.5",
|
||||||
|
"inversify": "^5.0.5",
|
||||||
"liquor-tree": "^0.2.70",
|
"liquor-tree": "^0.2.70",
|
||||||
|
"resize-observer-polyfill": "^1.5.1",
|
||||||
"v-tooltip": "2.0.2",
|
"v-tooltip": "2.0.2",
|
||||||
"vue": "^2.6.12",
|
"vue": "^2.6.12",
|
||||||
"vue-class-component": "^7.2.5",
|
"vue-class-component": "^7.2.6",
|
||||||
"vue-js-modal": "^2.0.0-rc.6",
|
"vue-js-modal": "^2.0.0-rc.6",
|
||||||
"vue-property-decorator": "^9.0.0"
|
"vue-property-decorator": "^9.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/ace": "0.0.43",
|
"@types/ace": "0.0.44",
|
||||||
"@types/chai": "^4.2.12",
|
"@types/chai": "^4.2.14",
|
||||||
"@types/file-saver": "^2.0.1",
|
"@types/file-saver": "^2.0.1",
|
||||||
"@types/mocha": "^8.0.3",
|
"@types/mocha": "^8.2.0",
|
||||||
"@vue/cli-plugin-typescript": "^4.5.4",
|
"@vue/cli-plugin-babel": "^4.5.10",
|
||||||
"@vue/cli-plugin-unit-mocha": "^4.5.4",
|
"@vue/cli-plugin-typescript": "^4.5.9",
|
||||||
"@vue/cli-service": "^4.5.4",
|
"@vue/cli-plugin-unit-mocha": "^4.5.9",
|
||||||
"@vue/test-utils": "1.0.4",
|
"@vue/cli-service": "^4.5.9",
|
||||||
|
"@vue/test-utils": "1.1.2",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"electron": "^10.1.0",
|
"electron": "^11.1.0",
|
||||||
"electron-devtools-installer": "^3.1.1",
|
"electron-devtools-installer": "^3.1.1",
|
||||||
"electron-log": "^4.2.4",
|
"electron-log": "^4.3.1",
|
||||||
"electron-updater": "^4.3.4",
|
"electron-updater": "^4.3.5",
|
||||||
"js-yaml-loader": "^1.2.2",
|
"js-yaml-loader": "^1.2.2",
|
||||||
"markdownlint-cli": "^0.23.2",
|
"markdownlint-cli": "^0.26.0",
|
||||||
"remark-cli": "^8.0.1",
|
"remark-cli": "^9.0.0",
|
||||||
"remark-lint-no-dead-urls": "^1.1.0",
|
"remark-lint-no-dead-urls": "^1.1.0",
|
||||||
"remark-preset-lint-consistent": "^3.0.1",
|
"remark-preset-lint-consistent": "^4.0.0",
|
||||||
"remark-validate-links": "^10.0.2",
|
"remark-validate-links": "^10.0.2",
|
||||||
"sass": "^1.26.10",
|
"sass": "^1.30.0",
|
||||||
"sass-loader": "^10.0.1",
|
"sass-loader": "^10.1.0",
|
||||||
"typescript": "^4.0.2",
|
"typescript": "^4.1.3",
|
||||||
"vue-cli-plugin-electron-builder": "^2.0.0-rc.4",
|
"vue-cli-plugin-electron-builder": "^2.0.0-rc.5",
|
||||||
"vue-template-compiler": "^2.6.12",
|
"vue-template-compiler": "^2.6.12",
|
||||||
"yaml-lint": "^1.2.4"
|
"yaml-lint": "^1.2.4"
|
||||||
|
},
|
||||||
|
"homepage": "https://privacy.sexy",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/undergroundwires/privacy.sexy.git"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<title>Privacy is sexy 🍑🍆 - Enforce privacy & security on Windows</title>
|
<title>Privacy is sexy 🍑🍆 - Enforce privacy & security on Windows and macOS</title>
|
||||||
<meta name="robots" content="index,follow" />
|
<meta name="robots" content="index,follow" />
|
||||||
<meta name="description" content="Web tool to generate scripts for enforcing privacy & security best-practices such as stopping data collection of Windows and different softwares on it."/>
|
<meta name="description" content="Web tool to generate scripts for enforcing privacy & security best-practices such as stopping data collection of Windows and different softwares on it."/>
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
|||||||
2
public/robots.txt
Normal file
2
public/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow:
|
||||||
27
src/App.vue
27
src/App.vue
@@ -1,12 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<TheHeader class="row" />
|
<TheHeader class="row" />
|
||||||
<TheSearchBar class="row" />
|
<TheSearchBar class="row" />
|
||||||
<TheScripts class="row"/>
|
<TheScriptArea class="row" />
|
||||||
<TheCodeArea class="row" theme="xcode" />
|
<TheCodeButtons class="row code-buttons" />
|
||||||
<TheCodeButtons class="row code-buttons" />
|
<TheFooter />
|
||||||
<TheFooter />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -15,17 +14,15 @@
|
|||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
import TheHeader from '@/presentation/TheHeader.vue';
|
import TheHeader from '@/presentation/TheHeader.vue';
|
||||||
import TheFooter from '@/presentation/TheFooter/TheFooter.vue';
|
import TheFooter from '@/presentation/TheFooter/TheFooter.vue';
|
||||||
import TheCodeArea from '@/presentation/TheCodeArea.vue';
|
import TheCodeButtons from '@/presentation/Code/CodeButtons/TheCodeButtons.vue';
|
||||||
import TheCodeButtons from '@/presentation/TheCodeButtons.vue';
|
import TheScriptArea from '@/presentation/Scripts/TheScriptArea.vue';
|
||||||
import TheSearchBar from '@/presentation/TheSearchBar.vue';
|
import TheSearchBar from '@/presentation/TheSearchBar.vue';
|
||||||
import TheScripts from '@/presentation/Scripts/TheScripts.vue';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
TheHeader,
|
TheHeader,
|
||||||
TheCodeArea,
|
|
||||||
TheCodeButtons,
|
TheCodeButtons,
|
||||||
TheScripts,
|
TheScriptArea,
|
||||||
TheSearchBar,
|
TheSearchBar,
|
||||||
TheFooter,
|
TheFooter,
|
||||||
},
|
},
|
||||||
@@ -38,6 +35,7 @@ export default class App extends Vue {
|
|||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import "@/presentation/styles/colors.scss";
|
@import "@/presentation/styles/colors.scss";
|
||||||
@import "@/presentation/styles/fonts.scss";
|
@import "@/presentation/styles/fonts.scss";
|
||||||
|
@import "@/presentation/styles/media.scss";
|
||||||
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -49,12 +47,10 @@ body {
|
|||||||
color: $slate;
|
color: $slate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
max-width: 1500px;
|
max-width: 1600px;
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
margin: 0% 2% 0% 2%;
|
margin: 0% 2% 0% 2%;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@@ -62,18 +58,15 @@ body {
|
|||||||
padding: 2%;
|
padding: 2%;
|
||||||
display:flex;
|
display:flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.row {
|
.row {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-buttons {
|
.code-buttons {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@import "@/presentation/styles/tooltip.scss";
|
@import "@/presentation/styles/tooltip.scss";
|
||||||
@import "@/presentation/styles/tree.scss";
|
@import "@/presentation/styles/tree.scss";
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
21
src/application/ApplicationFactory.ts
Normal file
21
src/application/ApplicationFactory.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { IApplication } from '@/domain/IApplication';
|
||||||
|
import { AsyncLazy } from '@/infrastructure/Threading/AsyncLazy';
|
||||||
|
import { IApplicationFactory } from './IApplicationFactory';
|
||||||
|
import { parseApplication } from './Parser/ApplicationParser';
|
||||||
|
|
||||||
|
export type ApplicationGetter = () => IApplication;
|
||||||
|
const ApplicationGetter: ApplicationGetter = parseApplication;
|
||||||
|
|
||||||
|
export class ApplicationFactory implements IApplicationFactory {
|
||||||
|
public static readonly Current: IApplicationFactory = new ApplicationFactory(ApplicationGetter);
|
||||||
|
private readonly getter: AsyncLazy<IApplication>;
|
||||||
|
protected constructor(costlyGetter: ApplicationGetter) {
|
||||||
|
if (!costlyGetter) {
|
||||||
|
throw new Error('undefined getter');
|
||||||
|
}
|
||||||
|
this.getter = new AsyncLazy<IApplication>(() => Promise.resolve(costlyGetter()));
|
||||||
|
}
|
||||||
|
public getAppAsync(): Promise<IApplication> {
|
||||||
|
return this.getter.getValueAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/application/Common/Enum.ts
Normal file
43
src/application/Common/Enum.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Because we cannot do "T extends enum" 😞 https://github.com/microsoft/TypeScript/issues/30611
|
||||||
|
type EnumType = number | string;
|
||||||
|
type EnumVariable<T extends EnumType, TEnumValue extends EnumType> = { [key in T]: TEnumValue };
|
||||||
|
|
||||||
|
export interface IEnumParser<TEnum> {
|
||||||
|
parseEnum(value: string, propertyName: string): TEnum;
|
||||||
|
}
|
||||||
|
export function createEnumParser<T extends EnumType, TEnumValue extends EnumType>(
|
||||||
|
enumVariable: EnumVariable<T, TEnumValue>): IEnumParser<TEnumValue> {
|
||||||
|
return {
|
||||||
|
parseEnum: (value, propertyName) => parseEnumValue(value, propertyName, enumVariable),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function parseEnumValue<T extends EnumType, TEnumValue extends EnumType>(
|
||||||
|
value: string,
|
||||||
|
enumName: string,
|
||||||
|
enumVariable: EnumVariable<T, TEnumValue>): TEnumValue {
|
||||||
|
if (!value) {
|
||||||
|
throw new Error(`undefined ${enumName}`);
|
||||||
|
}
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
throw new Error(`unexpected type of ${enumName}: "${typeof value}"`);
|
||||||
|
}
|
||||||
|
const casedValue = getEnumNames(enumVariable)
|
||||||
|
.find((enumValue) => enumValue.toLowerCase() === value.toLowerCase());
|
||||||
|
if (!casedValue) {
|
||||||
|
throw new Error(`unknown ${enumName}: "${value}"`);
|
||||||
|
}
|
||||||
|
return enumVariable[casedValue as keyof typeof enumVariable];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEnumNames<T extends EnumType, TEnumValue extends EnumType>(
|
||||||
|
enumVariable: EnumVariable<T, TEnumValue>): string[] {
|
||||||
|
return Object
|
||||||
|
.values(enumVariable)
|
||||||
|
.filter((enumMember) => typeof enumMember === 'string') as string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEnumValues<T extends EnumType, TEnumValue extends EnumType>(
|
||||||
|
enumVariable: EnumVariable<T, TEnumValue>): TEnumValue[] {
|
||||||
|
return getEnumNames(enumVariable)
|
||||||
|
.map((level) => enumVariable[level]) as TEnumValue[];
|
||||||
|
}
|
||||||
71
src/application/Context/ApplicationContext.ts
Normal file
71
src/application/Context/ApplicationContext.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { IApplicationContext, IApplicationContextChangedEvent } from './IApplicationContext';
|
||||||
|
import { ICategoryCollectionState } from './State/ICategoryCollectionState';
|
||||||
|
import { CategoryCollectionState } from './State/CategoryCollectionState';
|
||||||
|
import { IApplication } from '@/domain/IApplication';
|
||||||
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||||
|
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||||
|
|
||||||
|
type StateMachine = Map<OperatingSystem, ICategoryCollectionState>;
|
||||||
|
|
||||||
|
export class ApplicationContext implements IApplicationContext {
|
||||||
|
public readonly contextChanged = new EventSource<IApplicationContextChangedEvent>();
|
||||||
|
public collection: ICategoryCollection;
|
||||||
|
public currentOs: OperatingSystem;
|
||||||
|
|
||||||
|
public get state(): ICategoryCollectionState {
|
||||||
|
return this.states[this.collection.os];
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly states: StateMachine;
|
||||||
|
public constructor(
|
||||||
|
public readonly app: IApplication,
|
||||||
|
initialContext: OperatingSystem) {
|
||||||
|
validateApp(app);
|
||||||
|
validateOs(initialContext);
|
||||||
|
this.states = initializeStates(app);
|
||||||
|
this.changeContext(initialContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
public changeContext(os: OperatingSystem): void {
|
||||||
|
if (this.currentOs === os) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.collection = this.app.getCollection(os);
|
||||||
|
if (!this.collection) {
|
||||||
|
throw new Error(`os "${OperatingSystem[os]}" is not defined in application`);
|
||||||
|
}
|
||||||
|
const event: IApplicationContextChangedEvent = {
|
||||||
|
newState: this.states[os],
|
||||||
|
oldState: this.states[this.currentOs],
|
||||||
|
};
|
||||||
|
this.contextChanged.notify(event);
|
||||||
|
this.currentOs = os;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateApp(app: IApplication) {
|
||||||
|
if (!app) {
|
||||||
|
throw new Error('undefined app');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateOs(os: OperatingSystem) {
|
||||||
|
if (os === undefined) {
|
||||||
|
throw new Error('undefined os');
|
||||||
|
}
|
||||||
|
if (os === OperatingSystem.Unknown) {
|
||||||
|
throw new Error('unknown os');
|
||||||
|
}
|
||||||
|
if (!(os in OperatingSystem)) {
|
||||||
|
throw new Error(`os "${os}" is out of range`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeStates(app: IApplication): StateMachine {
|
||||||
|
const machine = new Map<OperatingSystem, ICategoryCollectionState>();
|
||||||
|
for (const collection of app.collections) {
|
||||||
|
machine[collection.os] = new CategoryCollectionState(collection);
|
||||||
|
}
|
||||||
|
return machine;
|
||||||
|
}
|
||||||
31
src/application/Context/ApplicationContextFactory.ts
Normal file
31
src/application/Context/ApplicationContextFactory.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { ApplicationContext } from './ApplicationContext';
|
||||||
|
import { IApplicationContext } from '@/application/Context/IApplicationContext';
|
||||||
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
import { Environment } from '../Environment/Environment';
|
||||||
|
import { IApplication } from '@/domain/IApplication';
|
||||||
|
import { IEnvironment } from '../Environment/IEnvironment';
|
||||||
|
import { IApplicationFactory } from '../IApplicationFactory';
|
||||||
|
import { ApplicationFactory } from '../ApplicationFactory';
|
||||||
|
|
||||||
|
export async function buildContextAsync(
|
||||||
|
factory: IApplicationFactory = ApplicationFactory.Current,
|
||||||
|
environment = Environment.CurrentEnvironment): Promise<IApplicationContext> {
|
||||||
|
if (!factory) { throw new Error('undefined factory'); }
|
||||||
|
if (!environment) { throw new Error('undefined environment'); }
|
||||||
|
const app = await factory.getAppAsync();
|
||||||
|
const os = getInitialOs(app, environment);
|
||||||
|
return new ApplicationContext(app, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInitialOs(app: IApplication, environment: IEnvironment): OperatingSystem {
|
||||||
|
const currentOs = environment.os;
|
||||||
|
const supportedOsList = app.getSupportedOsList();
|
||||||
|
if (supportedOsList.includes(currentOs)) {
|
||||||
|
return currentOs;
|
||||||
|
}
|
||||||
|
supportedOsList.sort((os1, os2) => {
|
||||||
|
const getPriority = (os: OperatingSystem) => app.getCollection(os).totalScripts;
|
||||||
|
return getPriority(os2) - getPriority(os1);
|
||||||
|
});
|
||||||
|
return supportedOsList[0];
|
||||||
|
}
|
||||||
16
src/application/Context/IApplicationContext.ts
Normal file
16
src/application/Context/IApplicationContext.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { ICategoryCollectionState } from './State/ICategoryCollectionState';
|
||||||
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||||
|
import { IApplication } from '@/domain/IApplication';
|
||||||
|
|
||||||
|
export interface IApplicationContext {
|
||||||
|
readonly app: IApplication;
|
||||||
|
readonly state: ICategoryCollectionState;
|
||||||
|
readonly contextChanged: IEventSource<IApplicationContextChangedEvent>;
|
||||||
|
changeContext(os: OperatingSystem): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IApplicationContextChangedEvent {
|
||||||
|
readonly newState: ICategoryCollectionState;
|
||||||
|
readonly oldState: ICategoryCollectionState;
|
||||||
|
}
|
||||||
23
src/application/Context/State/CategoryCollectionState.ts
Normal file
23
src/application/Context/State/CategoryCollectionState.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { UserFilter } from './Filter/UserFilter';
|
||||||
|
import { IUserFilter } from './Filter/IUserFilter';
|
||||||
|
import { ApplicationCode } from './Code/ApplicationCode';
|
||||||
|
import { UserSelection } from './Selection/UserSelection';
|
||||||
|
import { IUserSelection } from './Selection/IUserSelection';
|
||||||
|
import { ICategoryCollectionState } from './ICategoryCollectionState';
|
||||||
|
import { IApplicationCode } from './Code/IApplicationCode';
|
||||||
|
import { ICategoryCollection } from '../../../domain/ICategoryCollection';
|
||||||
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
|
||||||
|
export class CategoryCollectionState implements ICategoryCollectionState {
|
||||||
|
public readonly os: OperatingSystem;
|
||||||
|
public readonly code: IApplicationCode;
|
||||||
|
public readonly selection: IUserSelection;
|
||||||
|
public readonly filter: IUserFilter;
|
||||||
|
|
||||||
|
public constructor(readonly collection: ICategoryCollection) {
|
||||||
|
this.selection = new UserSelection(collection, []);
|
||||||
|
this.code = new ApplicationCode(this.selection, collection.scripting);
|
||||||
|
this.filter = new UserFilter(collection);
|
||||||
|
this.os = collection.os;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,26 @@
|
|||||||
import { CodeChangedEvent } from './Event/CodeChangedEvent';
|
import { CodeChangedEvent } from './Event/CodeChangedEvent';
|
||||||
import { CodePosition } from './Position/CodePosition';
|
import { CodePosition } from './Position/CodePosition';
|
||||||
import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
||||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript';
|
||||||
import { IUserSelection } from '@/application/State/Selection/IUserSelection';
|
import { IUserSelection } from '@/application/Context/State/Selection/IUserSelection';
|
||||||
import { UserScriptGenerator } from './Generation/UserScriptGenerator';
|
import { UserScriptGenerator } from './Generation/UserScriptGenerator';
|
||||||
import { Signal } from '@/infrastructure/Events/Signal';
|
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||||
import { IApplicationCode } from './IApplicationCode';
|
import { IApplicationCode } from './IApplicationCode';
|
||||||
import { IUserScriptGenerator } from './Generation/IUserScriptGenerator';
|
import { IUserScriptGenerator } from './Generation/IUserScriptGenerator';
|
||||||
|
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||||
|
|
||||||
export class ApplicationCode implements IApplicationCode {
|
export class ApplicationCode implements IApplicationCode {
|
||||||
public readonly changed = new Signal<ICodeChangedEvent>();
|
public readonly changed = new EventSource<ICodeChangedEvent>();
|
||||||
public current: string;
|
public current: string;
|
||||||
|
|
||||||
private scriptPositions = new Map<SelectedScript, CodePosition>();
|
private scriptPositions = new Map<SelectedScript, CodePosition>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
userSelection: IUserSelection,
|
userSelection: IUserSelection,
|
||||||
private readonly version: string,
|
private readonly scriptingDefinition: IScriptingDefinition,
|
||||||
private readonly generator: IUserScriptGenerator = new UserScriptGenerator()) {
|
private readonly generator: IUserScriptGenerator = new UserScriptGenerator()) {
|
||||||
if (!userSelection) { throw new Error('userSelection is null or undefined'); }
|
if (!userSelection) { throw new Error('userSelection is null or undefined'); }
|
||||||
if (!version) { throw new Error('version is null or undefined'); }
|
if (!scriptingDefinition) { throw new Error('scriptingDefinition is null or undefined'); }
|
||||||
if (!generator) { throw new Error('generator is null or undefined'); }
|
if (!generator) { throw new Error('generator is null or undefined'); }
|
||||||
this.setCode(userSelection.selectedScripts);
|
this.setCode(userSelection.selectedScripts);
|
||||||
userSelection.changed.on((scripts) => {
|
userSelection.changed.on((scripts) => {
|
||||||
@@ -29,7 +30,7 @@ export class ApplicationCode implements IApplicationCode {
|
|||||||
|
|
||||||
private setCode(scripts: ReadonlyArray<SelectedScript>): void {
|
private setCode(scripts: ReadonlyArray<SelectedScript>): void {
|
||||||
const oldScripts = Array.from(this.scriptPositions.keys());
|
const oldScripts = Array.from(this.scriptPositions.keys());
|
||||||
const code = this.generator.buildCode(scripts, this.version);
|
const code = this.generator.buildCode(scripts, this.scriptingDefinition);
|
||||||
this.current = code.code;
|
this.current = code.code;
|
||||||
this.scriptPositions = code.scriptPositions;
|
this.scriptPositions = code.scriptPositions;
|
||||||
const event = new CodeChangedEvent(code.code, oldScripts, code.scriptPositions);
|
const event = new CodeChangedEvent(code.code, oldScripts, code.scriptPositions);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ICodeChangedEvent } from './ICodeChangedEvent';
|
import { ICodeChangedEvent } from './ICodeChangedEvent';
|
||||||
import { SelectedScript } from '../../Selection/SelectedScript';
|
import { SelectedScript } from '../../Selection/SelectedScript';
|
||||||
import { IScript } from '@/domain/IScript';
|
import { IScript } from '@/domain/IScript';
|
||||||
import { ICodePosition } from '@/application/State/Code/Position/ICodePosition';
|
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||||
|
|
||||||
export class CodeChangedEvent implements ICodeChangedEvent {
|
export class CodeChangedEvent implements ICodeChangedEvent {
|
||||||
public readonly code: string;
|
public readonly code: string;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IScript } from '@/domain/IScript';
|
import { IScript } from '@/domain/IScript';
|
||||||
import { ICodePosition } from '@/application/State/Code/Position/ICodePosition';
|
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||||
|
|
||||||
export interface ICodeChangedEvent {
|
export interface ICodeChangedEvent {
|
||||||
readonly code: string;
|
readonly code: string;
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import { ICodeBuilder } from './ICodeBuilder';
|
||||||
|
|
||||||
const NewLine = '\n';
|
const NewLine = '\n';
|
||||||
const TotalFunctionSeparatorChars = 58;
|
const TotalFunctionSeparatorChars = 58;
|
||||||
|
|
||||||
export class CodeBuilder {
|
export abstract class CodeBuilder implements ICodeBuilder {
|
||||||
private readonly lines = new Array<string>();
|
private readonly lines = new Array<string>();
|
||||||
|
|
||||||
// Returns current line starting from 0 (no lines), or 1 (have single line)
|
// Returns current line starting from 0 (no lines), or 1 (have single line)
|
||||||
@@ -27,7 +29,7 @@ export class CodeBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public appendCommentLine(commentLine?: string): CodeBuilder {
|
public appendCommentLine(commentLine?: string): CodeBuilder {
|
||||||
this.lines.push(`:: ${commentLine}`);
|
this.lines.push(`${this.getCommentDelimiter()} ${commentLine}`);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,9 +37,8 @@ export class CodeBuilder {
|
|||||||
if (!name) { throw new Error('name cannot be empty or null'); }
|
if (!name) { throw new Error('name cannot be empty or null'); }
|
||||||
if (!code) { throw new Error('code cannot be empty or null'); }
|
if (!code) { throw new Error('code cannot be empty or null'); }
|
||||||
return this
|
return this
|
||||||
.appendLine()
|
|
||||||
.appendCommentLineWithHyphensAround(name)
|
.appendCommentLineWithHyphensAround(name)
|
||||||
.appendLine(`echo --- ${name}`)
|
.appendLine(this.writeStandardOut(`--- ${name}`))
|
||||||
.appendLine(code)
|
.appendLine(code)
|
||||||
.appendTrailingHyphensCommentLine();
|
.appendTrailingHyphensCommentLine();
|
||||||
}
|
}
|
||||||
@@ -54,10 +55,13 @@ export class CodeBuilder {
|
|||||||
return this
|
return this
|
||||||
.appendTrailingHyphensCommentLine()
|
.appendTrailingHyphensCommentLine()
|
||||||
.appendCommentLine(firstHyphens + sectionName + secondHyphens)
|
.appendCommentLine(firstHyphens + sectionName + secondHyphens)
|
||||||
.appendTrailingHyphensCommentLine();
|
.appendTrailingHyphensCommentLine(TotalFunctionSeparatorChars);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toString(): string {
|
public toString(): string {
|
||||||
return this.lines.join(NewLine);
|
return this.lines.join(NewLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract getCommentDelimiter(): string;
|
||||||
|
protected abstract writeStandardOut(text: string): string;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||||
|
import { ICodeBuilder } from './ICodeBuilder';
|
||||||
|
import { ICodeBuilderFactory } from './ICodeBuilderFactory';
|
||||||
|
import { BatchBuilder } from './Languages/BatchBuilder';
|
||||||
|
import { ShellBuilder } from './Languages/ShellBuilder';
|
||||||
|
|
||||||
|
export class CodeBuilderFactory implements ICodeBuilderFactory {
|
||||||
|
public create(language: ScriptingLanguage): ICodeBuilder {
|
||||||
|
switch (language) {
|
||||||
|
case ScriptingLanguage.shellscript: return new ShellBuilder();
|
||||||
|
case ScriptingLanguage.batchfile: return new BatchBuilder();
|
||||||
|
default: throw new RangeError(`unknown language: "${ScriptingLanguage[language]}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export interface ICodeBuilder {
|
||||||
|
currentLine: number;
|
||||||
|
appendLine(code?: string): ICodeBuilder;
|
||||||
|
appendTrailingHyphensCommentLine(totalRepeatHyphens: number): ICodeBuilder;
|
||||||
|
appendCommentLine(commentLine?: string): ICodeBuilder;
|
||||||
|
appendCommentLineWithHyphensAround(sectionName: string, totalRepeatHyphens: number): ICodeBuilder;
|
||||||
|
appendFunction(name: string, code: string): ICodeBuilder;
|
||||||
|
toString(): string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||||
|
import { ICodeBuilder } from './ICodeBuilder';
|
||||||
|
|
||||||
|
export interface ICodeBuilderFactory {
|
||||||
|
create(language: ScriptingLanguage): ICodeBuilder;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript';
|
||||||
|
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||||
|
|
||||||
|
export interface IUserScript {
|
||||||
|
code: string;
|
||||||
|
scriptPositions: Map<SelectedScript, ICodePosition>;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript';
|
||||||
|
import { IUserScript } from './IUserScript';
|
||||||
|
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||||
|
|
||||||
|
export interface IUserScriptGenerator {
|
||||||
|
buildCode(
|
||||||
|
selectedScripts: ReadonlyArray<SelectedScript>,
|
||||||
|
scriptingDefinition: IScriptingDefinition): IUserScript;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { CodeBuilder } from '@/application/Context/State/Code/Generation/CodeBuilder';
|
||||||
|
|
||||||
|
export class BatchBuilder extends CodeBuilder {
|
||||||
|
protected getCommentDelimiter(): string {
|
||||||
|
return '::';
|
||||||
|
}
|
||||||
|
protected writeStandardOut(text: string): string {
|
||||||
|
return `echo ${escapeForEcho(text)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeForEcho(text: string) {
|
||||||
|
return text
|
||||||
|
.replace(/&/g, '^&')
|
||||||
|
.replace(/%/g, '%%');
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import { CodeBuilder } from '@/application/Context/State/Code/Generation/CodeBuilder';
|
||||||
|
|
||||||
|
export class ShellBuilder extends CodeBuilder {
|
||||||
|
protected getCommentDelimiter(): string {
|
||||||
|
return '#';
|
||||||
|
}
|
||||||
|
protected writeStandardOut(text: string): string {
|
||||||
|
return `echo '${escapeForEcho(text)}'`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeForEcho(text: string) {
|
||||||
|
return text
|
||||||
|
.replace(/'/g, '\'\\\'\'');
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { SelectedScript } from '@/application/Context/State/Selection/SelectedScript';
|
||||||
|
import { IUserScriptGenerator } from './IUserScriptGenerator';
|
||||||
|
import { ICodePosition } from '@/application/Context/State/Code/Position/ICodePosition';
|
||||||
|
import { CodePosition } from '../Position/CodePosition';
|
||||||
|
import { IUserScript } from './IUserScript';
|
||||||
|
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||||
|
import { ICodeBuilder } from './ICodeBuilder';
|
||||||
|
import { ICodeBuilderFactory } from './ICodeBuilderFactory';
|
||||||
|
import { CodeBuilderFactory } from './CodeBuilderFactory';
|
||||||
|
|
||||||
|
export class UserScriptGenerator implements IUserScriptGenerator {
|
||||||
|
constructor(private readonly codeBuilderFactory: ICodeBuilderFactory = new CodeBuilderFactory()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
public buildCode(
|
||||||
|
selectedScripts: ReadonlyArray<SelectedScript>,
|
||||||
|
scriptingDefinition: IScriptingDefinition): IUserScript {
|
||||||
|
if (!selectedScripts) { throw new Error('undefined scripts'); }
|
||||||
|
if (!scriptingDefinition) { throw new Error('undefined definition'); }
|
||||||
|
let scriptPositions = new Map<SelectedScript, ICodePosition>();
|
||||||
|
if (!selectedScripts.length) {
|
||||||
|
return { code: '', scriptPositions };
|
||||||
|
}
|
||||||
|
let builder = this.codeBuilderFactory.create(scriptingDefinition.language);
|
||||||
|
builder = initializeCode(scriptingDefinition.startCode, builder);
|
||||||
|
for (const selection of selectedScripts) {
|
||||||
|
scriptPositions = appendSelection(selection, scriptPositions, builder);
|
||||||
|
}
|
||||||
|
const code = finalizeCode(builder, scriptingDefinition.endCode);
|
||||||
|
return { code, scriptPositions };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeCode(startCode: string, builder: ICodeBuilder): ICodeBuilder {
|
||||||
|
if (!startCode) {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
return builder
|
||||||
|
.appendLine(startCode)
|
||||||
|
.appendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
function finalizeCode(builder: ICodeBuilder, endCode: string): string {
|
||||||
|
if (!endCode) {
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
return builder.appendLine()
|
||||||
|
.appendLine(endCode)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendSelection(
|
||||||
|
selection: SelectedScript,
|
||||||
|
scriptPositions: Map<SelectedScript, ICodePosition>,
|
||||||
|
builder: ICodeBuilder): Map<SelectedScript, ICodePosition> {
|
||||||
|
const startPosition = builder.currentLine + 1; // Because first line will be empty to separate scripts
|
||||||
|
builder = appendCode(selection, builder);
|
||||||
|
const endPosition = builder.currentLine - 1;
|
||||||
|
builder.appendLine();
|
||||||
|
const position = new CodePosition(startPosition, endPosition);
|
||||||
|
scriptPositions.set(selection, position);
|
||||||
|
return scriptPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendCode(selection: SelectedScript, builder: ICodeBuilder): ICodeBuilder {
|
||||||
|
const name = selection.revert ? `${selection.script.name} (revert)` : selection.script.name;
|
||||||
|
const scriptCode = selection.revert ? selection.script.code.revert : selection.script.code.execute;
|
||||||
|
return builder
|
||||||
|
.appendLine()
|
||||||
|
.appendFunction(name, scriptCode);
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
import { ICodeChangedEvent } from './Event/ICodeChangedEvent';
|
||||||
import { ISignal } from '@/infrastructure/Events/ISignal';
|
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||||
|
|
||||||
export interface IApplicationCode {
|
export interface IApplicationCode {
|
||||||
readonly changed: ISignal<ICodeChangedEvent>;
|
readonly changed: IEventSource<ICodeChangedEvent>;
|
||||||
readonly current: string;
|
readonly current: string;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ICodePosition } from './ICodePosition';
|
import { ICodePosition } from './ICodePosition';
|
||||||
export class CodePosition implements ICodePosition {
|
|
||||||
|
|
||||||
|
export class CodePosition implements ICodePosition {
|
||||||
public get totalLines(): number {
|
public get totalLines(): number {
|
||||||
return this.endLine - this.startLine;
|
return this.endLine - this.startLine;
|
||||||
}
|
}
|
||||||
10
src/application/Context/State/Filter/IUserFilter.ts
Normal file
10
src/application/Context/State/Filter/IUserFilter.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||||
|
import { IFilterResult } from './IFilterResult';
|
||||||
|
|
||||||
|
export interface IUserFilter {
|
||||||
|
readonly currentFilter: IFilterResult | undefined;
|
||||||
|
readonly filtered: IEventSource<IFilterResult>;
|
||||||
|
readonly filterRemoved: IEventSource<void>;
|
||||||
|
setFilter(filter: string): void;
|
||||||
|
removeFilter(): void;
|
||||||
|
}
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
import { IScript } from '@/domain/IScript';
|
import { IScript } from '@/domain/IScript';
|
||||||
import { FilterResult } from './FilterResult';
|
import { FilterResult } from './FilterResult';
|
||||||
import { IFilterResult } from './IFilterResult';
|
import { IFilterResult } from './IFilterResult';
|
||||||
import { IApplication } from '@/domain/IApplication';
|
|
||||||
import { IUserFilter } from './IUserFilter';
|
import { IUserFilter } from './IUserFilter';
|
||||||
import { Signal } from '@/infrastructure/Events/Signal';
|
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||||
|
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||||
|
|
||||||
export class UserFilter implements IUserFilter {
|
export class UserFilter implements IUserFilter {
|
||||||
public readonly filtered = new Signal<IFilterResult>();
|
public readonly filtered = new EventSource<IFilterResult>();
|
||||||
public readonly filterRemoved = new Signal<void>();
|
public readonly filterRemoved = new EventSource<void>();
|
||||||
|
public currentFilter: IFilterResult | undefined;
|
||||||
|
|
||||||
constructor(private application: IApplication) {
|
constructor(private collection: ICategoryCollection) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,21 +19,21 @@ export class UserFilter implements IUserFilter {
|
|||||||
throw new Error('Filter must be defined and not empty. Use removeFilter() to remove the filter');
|
throw new Error('Filter must be defined and not empty. Use removeFilter() to remove the filter');
|
||||||
}
|
}
|
||||||
const filterLowercase = filter.toLocaleLowerCase();
|
const filterLowercase = filter.toLocaleLowerCase();
|
||||||
const filteredScripts = this.application.getAllScripts().filter(
|
const filteredScripts = this.collection.getAllScripts().filter(
|
||||||
(script) => isScriptAMatch(script, filterLowercase));
|
(script) => isScriptAMatch(script, filterLowercase));
|
||||||
const filteredCategories = this.application.getAllCategories().filter(
|
const filteredCategories = this.collection.getAllCategories().filter(
|
||||||
(category) => category.name.toLowerCase().includes(filterLowercase));
|
(category) => category.name.toLowerCase().includes(filterLowercase));
|
||||||
|
|
||||||
const matches = new FilterResult(
|
const matches = new FilterResult(
|
||||||
filteredScripts,
|
filteredScripts,
|
||||||
filteredCategories,
|
filteredCategories,
|
||||||
filter,
|
filter,
|
||||||
);
|
);
|
||||||
|
this.currentFilter = matches;
|
||||||
this.filtered.notify(matches);
|
this.filtered.notify(matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeFilter(): void {
|
public removeFilter(): void {
|
||||||
|
this.currentFilter = undefined;
|
||||||
this.filterRemoved.notify();
|
this.filterRemoved.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,11 +42,11 @@ function isScriptAMatch(script: IScript, filterLowercase: string) {
|
|||||||
if (script.name.toLowerCase().includes(filterLowercase)) {
|
if (script.name.toLowerCase().includes(filterLowercase)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (script.code.toLowerCase().includes(filterLowercase)) {
|
if (script.code.execute.toLowerCase().includes(filterLowercase)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (script.revertCode) {
|
if (script.code.revert) {
|
||||||
return script.revertCode.toLowerCase().includes(filterLowercase);
|
return script.code.revert.toLowerCase().includes(filterLowercase);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
13
src/application/Context/State/ICategoryCollectionState.ts
Normal file
13
src/application/Context/State/ICategoryCollectionState.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { IUserFilter } from './Filter/IUserFilter';
|
||||||
|
import { IUserSelection } from './Selection/IUserSelection';
|
||||||
|
import { IApplicationCode } from './Code/IApplicationCode';
|
||||||
|
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||||
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
|
||||||
|
export interface ICategoryCollectionState {
|
||||||
|
readonly code: IApplicationCode;
|
||||||
|
readonly filter: IUserFilter;
|
||||||
|
readonly selection: IUserSelection;
|
||||||
|
readonly collection: ICategoryCollection;
|
||||||
|
readonly os: OperatingSystem;
|
||||||
|
}
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
import { SelectedScript } from './SelectedScript';
|
import { SelectedScript } from './SelectedScript';
|
||||||
import { ISignal } from '@/infrastructure/Events/Signal';
|
|
||||||
import { IScript } from '@/domain/IScript';
|
import { IScript } from '@/domain/IScript';
|
||||||
|
import { ICategory } from '@/domain/ICategory';
|
||||||
|
import { IEventSource } from '@/infrastructure/Events/IEventSource';
|
||||||
|
|
||||||
export interface IUserSelection {
|
export interface IUserSelection {
|
||||||
readonly changed: ISignal<ReadonlyArray<SelectedScript>>;
|
readonly changed: IEventSource<ReadonlyArray<SelectedScript>>;
|
||||||
readonly selectedScripts: ReadonlyArray<SelectedScript>;
|
readonly selectedScripts: ReadonlyArray<SelectedScript>;
|
||||||
readonly totalSelected: number;
|
readonly totalSelected: number;
|
||||||
|
areAllSelected(category: ICategory): boolean;
|
||||||
|
isAnySelected(category: ICategory): boolean;
|
||||||
removeAllInCategory(categoryId: number): void;
|
removeAllInCategory(categoryId: number): void;
|
||||||
addOrUpdateAllInCategory(categoryId: number, revert: boolean): void;
|
addOrUpdateAllInCategory(categoryId: number, revert: boolean): void;
|
||||||
addSelectedScript(scriptId: string, revert: boolean): void;
|
addSelectedScript(scriptId: string, revert: boolean): void;
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
import { SelectedScript } from './SelectedScript';
|
import { SelectedScript } from './SelectedScript';
|
||||||
import { IApplication } from '@/domain/IApplication';
|
|
||||||
import { IUserSelection } from './IUserSelection';
|
import { IUserSelection } from './IUserSelection';
|
||||||
import { InMemoryRepository } from '@/infrastructure/Repository/InMemoryRepository';
|
import { InMemoryRepository } from '@/infrastructure/Repository/InMemoryRepository';
|
||||||
import { IScript } from '@/domain/IScript';
|
import { IScript } from '@/domain/IScript';
|
||||||
import { Signal } from '@/infrastructure/Events/Signal';
|
import { EventSource } from '@/infrastructure/Events/EventSource';
|
||||||
import { IRepository } from '@/infrastructure/Repository/IRepository';
|
import { IRepository } from '@/infrastructure/Repository/IRepository';
|
||||||
|
import { ICategory } from '@/domain/ICategory';
|
||||||
|
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||||
|
|
||||||
export class UserSelection implements IUserSelection {
|
export class UserSelection implements IUserSelection {
|
||||||
public readonly changed = new Signal<ReadonlyArray<SelectedScript>>();
|
public readonly changed = new EventSource<ReadonlyArray<SelectedScript>>();
|
||||||
private readonly scripts: IRepository<string, SelectedScript>;
|
private readonly scripts: IRepository<string, SelectedScript>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly app: IApplication,
|
private readonly collection: ICategoryCollection,
|
||||||
selectedScripts: ReadonlyArray<SelectedScript>) {
|
selectedScripts: ReadonlyArray<SelectedScript>) {
|
||||||
this.scripts = new InMemoryRepository<string, SelectedScript>();
|
this.scripts = new InMemoryRepository<string, SelectedScript>();
|
||||||
if (selectedScripts && selectedScripts.length > 0) {
|
if (selectedScripts && selectedScripts.length > 0) {
|
||||||
@@ -21,8 +22,26 @@ export class UserSelection implements IUserSelection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public areAllSelected(category: ICategory): boolean {
|
||||||
|
if (this.selectedScripts.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const scripts = category.getAllScriptsRecursively();
|
||||||
|
if (this.selectedScripts.length < scripts.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return scripts.every((script) => this.selectedScripts.some((selected) => selected.id === script.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
public isAnySelected(category: ICategory): boolean {
|
||||||
|
if (this.selectedScripts.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.selectedScripts.some((s) => category.includes(s.script));
|
||||||
|
}
|
||||||
|
|
||||||
public removeAllInCategory(categoryId: number): void {
|
public removeAllInCategory(categoryId: number): void {
|
||||||
const category = this.app.findCategory(categoryId);
|
const category = this.collection.findCategory(categoryId);
|
||||||
const scriptsToRemove = category.getAllScriptsRecursively()
|
const scriptsToRemove = category.getAllScriptsRecursively()
|
||||||
.filter((script) => this.scripts.exists(script.id));
|
.filter((script) => this.scripts.exists(script.id));
|
||||||
if (!scriptsToRemove.length) {
|
if (!scriptsToRemove.length) {
|
||||||
@@ -35,7 +54,7 @@ export class UserSelection implements IUserSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addOrUpdateAllInCategory(categoryId: number, revert: boolean = false): void {
|
public addOrUpdateAllInCategory(categoryId: number, revert: boolean = false): void {
|
||||||
const category = this.app.findCategory(categoryId);
|
const category = this.collection.findCategory(categoryId);
|
||||||
const scriptsToAddOrUpdate = category.getAllScriptsRecursively()
|
const scriptsToAddOrUpdate = category.getAllScriptsRecursively()
|
||||||
.filter((script) =>
|
.filter((script) =>
|
||||||
!this.scripts.exists(script.id)
|
!this.scripts.exists(script.id)
|
||||||
@@ -52,7 +71,7 @@ export class UserSelection implements IUserSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addSelectedScript(scriptId: string, revert: boolean): void {
|
public addSelectedScript(scriptId: string, revert: boolean): void {
|
||||||
const script = this.app.findScript(scriptId);
|
const script = this.collection.findScript(scriptId);
|
||||||
if (!script) {
|
if (!script) {
|
||||||
throw new Error(`Cannot add (id: ${scriptId}) as it is unknown`);
|
throw new Error(`Cannot add (id: ${scriptId}) as it is unknown`);
|
||||||
}
|
}
|
||||||
@@ -62,7 +81,7 @@ export class UserSelection implements IUserSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public addOrUpdateSelectedScript(scriptId: string, revert: boolean): void {
|
public addOrUpdateSelectedScript(scriptId: string, revert: boolean): void {
|
||||||
const script = this.app.findScript(scriptId);
|
const script = this.collection.findScript(scriptId);
|
||||||
const selectedScript = new SelectedScript(script, revert);
|
const selectedScript = new SelectedScript(script, revert);
|
||||||
this.scripts.addOrUpdateItem(selectedScript);
|
this.scripts.addOrUpdateItem(selectedScript);
|
||||||
this.changed.notify(this.scripts.getItems());
|
this.changed.notify(this.scripts.getItems());
|
||||||
@@ -87,7 +106,7 @@ export class UserSelection implements IUserSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public selectAll(): void {
|
public selectAll(): void {
|
||||||
for (const script of this.app.getAllScripts()) {
|
for (const script of this.collection.getAllScripts()) {
|
||||||
if (!this.scripts.exists(script.id)) {
|
if (!this.scripts.exists(script.id)) {
|
||||||
const selection = new SelectedScript(script, false);
|
const selection = new SelectedScript(script, false);
|
||||||
this.scripts.addItem(selection);
|
this.scripts.addItem(selection);
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OperatingSystem } from '../OperatingSystem';
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
import { DetectorBuilder } from './DetectorBuilder';
|
import { DetectorBuilder } from './DetectorBuilder';
|
||||||
import { IBrowserOsDetector } from './IBrowserOsDetector';
|
import { IBrowserOsDetector } from './IBrowserOsDetector';
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { IBrowserOsDetector } from './IBrowserOsDetector';
|
import { IBrowserOsDetector } from './IBrowserOsDetector';
|
||||||
import { OperatingSystem } from '../OperatingSystem';
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
|
||||||
export class DetectorBuilder {
|
export class DetectorBuilder {
|
||||||
private readonly existingPartsInUserAgent = new Array<string>();
|
private readonly existingPartsInUserAgent = new Array<string>();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { OperatingSystem } from '../OperatingSystem';
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
|
||||||
export interface IBrowserOsDetector {
|
export interface IBrowserOsDetector {
|
||||||
detect(userAgent: string): OperatingSystem;
|
detect(userAgent: string): OperatingSystem;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { BrowserOsDetector } from './BrowserOs/BrowserOsDetector';
|
import { BrowserOsDetector } from './BrowserOs/BrowserOsDetector';
|
||||||
import { IBrowserOsDetector } from './BrowserOs/IBrowserOsDetector';
|
import { IBrowserOsDetector } from './BrowserOs/IBrowserOsDetector';
|
||||||
import { IEnvironment } from './IEnvironment';
|
import { IEnvironment } from './IEnvironment';
|
||||||
import { OperatingSystem } from './OperatingSystem';
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
|
||||||
interface IEnvironmentVariables {
|
interface IEnvironmentVariables {
|
||||||
readonly window: Window & typeof globalThis;
|
readonly window: Window & typeof globalThis;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { OperatingSystem } from './OperatingSystem';
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
|
||||||
export interface IEnvironment {
|
export interface IEnvironment {
|
||||||
isDesktop: boolean;
|
readonly isDesktop: boolean;
|
||||||
os: OperatingSystem;
|
readonly os: OperatingSystem;
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/application/IApplicationFactory.ts
Normal file
5
src/application/IApplicationFactory.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { IApplication } from '@/domain/IApplication';
|
||||||
|
|
||||||
|
export interface IApplicationFactory {
|
||||||
|
getAppAsync(): Promise<IApplication>;
|
||||||
|
}
|
||||||
@@ -1,29 +1,38 @@
|
|||||||
import { Category } from '@/domain/Category';
|
|
||||||
import { Application } from '@/domain/Application';
|
|
||||||
import { IApplication } from '@/domain/IApplication';
|
import { IApplication } from '@/domain/IApplication';
|
||||||
import { ApplicationYaml } from 'js-yaml-loader!./../application.yaml';
|
import { IProjectInformation } from '@/domain/IProjectInformation';
|
||||||
import { parseCategory } from './CategoryParser';
|
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||||
|
import { parseCategoryCollection } from './CategoryCollectionParser';
|
||||||
|
import WindowsData from 'js-yaml-loader!@/application/collections/windows.yaml';
|
||||||
|
import MacOsData from 'js-yaml-loader!@/application/collections/macos.yaml';
|
||||||
|
import { CollectionData } from 'js-yaml-loader!@/*';
|
||||||
|
import { parseProjectInformation } from '@/application/Parser/ProjectInformationParser';
|
||||||
|
import { Application } from '@/domain/Application';
|
||||||
|
|
||||||
export function parseApplication(content: ApplicationYaml): IApplication {
|
export function parseApplication(
|
||||||
validate(content);
|
parser = CategoryCollectionParser,
|
||||||
const categories = new Array<Category>();
|
processEnv: NodeJS.ProcessEnv = process.env,
|
||||||
for (const action of content.actions) {
|
collectionsData = PreParsedCollections): IApplication {
|
||||||
const category = parseCategory(action);
|
validateCollectionsData(collectionsData);
|
||||||
categories.push(category);
|
const information = parseProjectInformation(processEnv);
|
||||||
}
|
const collections = collectionsData.map((collection) => parser(collection, information));
|
||||||
const app = new Application(
|
const app = new Application(information, collections);
|
||||||
content.name,
|
|
||||||
content.repositoryUrl,
|
|
||||||
process.env.VUE_APP_VERSION,
|
|
||||||
categories);
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate(content: ApplicationYaml): void {
|
export type CategoryCollectionParserType
|
||||||
if (!content) {
|
= (file: CollectionData, info: IProjectInformation) => ICategoryCollection;
|
||||||
throw new Error('application is null or undefined');
|
|
||||||
|
const CategoryCollectionParser: CategoryCollectionParserType
|
||||||
|
= (file, info) => parseCategoryCollection(file, info);
|
||||||
|
|
||||||
|
const PreParsedCollections: readonly CollectionData []
|
||||||
|
= [ WindowsData, MacOsData ];
|
||||||
|
|
||||||
|
function validateCollectionsData(collections: readonly CollectionData[]) {
|
||||||
|
if (!collections.length) {
|
||||||
|
throw new Error('no collection provided');
|
||||||
}
|
}
|
||||||
if (!content.actions || content.actions.length <= 0) {
|
if (collections.some((collection) => !collection)) {
|
||||||
throw new Error('application does not define any action');
|
throw new Error('undefined collection provided');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
39
src/application/Parser/CategoryCollectionParser.ts
Normal file
39
src/application/Parser/CategoryCollectionParser.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import { Category } from '@/domain/Category';
|
||||||
|
import { CollectionData } from 'js-yaml-loader!@/*';
|
||||||
|
import { parseCategory } from './CategoryParser';
|
||||||
|
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||||
|
import { parseScriptingDefinition } from './ScriptingDefinitionParser';
|
||||||
|
import { createEnumParser } from '../Common/Enum';
|
||||||
|
import { ICategoryCollection } from '@/domain/ICategoryCollection';
|
||||||
|
import { CategoryCollection } from '@/domain/CategoryCollection';
|
||||||
|
import { IProjectInformation } from '@/domain/IProjectInformation';
|
||||||
|
import { CategoryCollectionParseContext } from './Script/CategoryCollectionParseContext';
|
||||||
|
|
||||||
|
export function parseCategoryCollection(
|
||||||
|
content: CollectionData,
|
||||||
|
info: IProjectInformation,
|
||||||
|
osParser = createEnumParser(OperatingSystem)): ICategoryCollection {
|
||||||
|
validate(content);
|
||||||
|
const scripting = parseScriptingDefinition(content.scripting, info);
|
||||||
|
const context = new CategoryCollectionParseContext(content.functions, scripting);
|
||||||
|
const categories = new Array<Category>();
|
||||||
|
for (const action of content.actions) {
|
||||||
|
const category = parseCategory(action, context);
|
||||||
|
categories.push(category);
|
||||||
|
}
|
||||||
|
const os = osParser.parseEnum(content.os, 'os');
|
||||||
|
const collection = new CategoryCollection(
|
||||||
|
os,
|
||||||
|
categories,
|
||||||
|
scripting);
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate(content: CollectionData): void {
|
||||||
|
if (!content) {
|
||||||
|
throw new Error('content is null or undefined');
|
||||||
|
}
|
||||||
|
if (!content.actions || content.actions.length <= 0) {
|
||||||
|
throw new Error('content does not define any action');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { YamlCategory, YamlScript } from 'js-yaml-loader!./application.yaml';
|
import { CategoryData, ScriptData, CategoryOrScriptData } from 'js-yaml-loader!@/*';
|
||||||
import { Script } from '@/domain/Script';
|
import { Script } from '@/domain/Script';
|
||||||
import { Category } from '@/domain/Category';
|
import { Category } from '@/domain/Category';
|
||||||
import { parseDocUrls } from './DocumentationParser';
|
import { parseDocUrls } from './DocumentationParser';
|
||||||
import { parseScript } from './ScriptParser';
|
import { ICategoryCollectionParseContext } from './Script/ICategoryCollectionParseContext';
|
||||||
|
import { parseScript } from './Script/ScriptParser';
|
||||||
|
|
||||||
let categoryIdCounter: number = 0;
|
let categoryIdCounter: number = 0;
|
||||||
|
|
||||||
@@ -11,14 +12,15 @@ interface ICategoryChildren {
|
|||||||
subScripts: Script[];
|
subScripts: Script[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseCategory(category: YamlCategory): Category {
|
export function parseCategory(category: CategoryData, context: ICategoryCollectionParseContext): Category {
|
||||||
|
if (!context) { throw new Error('undefined context'); }
|
||||||
ensureValid(category);
|
ensureValid(category);
|
||||||
const children: ICategoryChildren = {
|
const children: ICategoryChildren = {
|
||||||
subCategories: new Array<Category>(),
|
subCategories: new Array<Category>(),
|
||||||
subScripts: new Array<Script>(),
|
subScripts: new Array<Script>(),
|
||||||
};
|
};
|
||||||
for (const categoryOrScript of category.children) {
|
for (const data of category.children) {
|
||||||
parseCategoryChild(categoryOrScript, children, category);
|
parseCategoryChild(data, children, category, context);
|
||||||
}
|
}
|
||||||
return new Category(
|
return new Category(
|
||||||
/*id*/ categoryIdCounter++,
|
/*id*/ categoryIdCounter++,
|
||||||
@@ -29,12 +31,12 @@ export function parseCategory(category: YamlCategory): Category {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureValid(category: YamlCategory) {
|
function ensureValid(category: CategoryData) {
|
||||||
if (!category) {
|
if (!category) {
|
||||||
throw Error('category is null or undefined');
|
throw Error('category is null or undefined');
|
||||||
}
|
}
|
||||||
if (!category.children || category.children.length === 0) {
|
if (!category.children || category.children.length === 0) {
|
||||||
throw Error('category has no children');
|
throw Error(`category has no children: "${category.category}"`);
|
||||||
}
|
}
|
||||||
if (!category.category || category.category.length === 0) {
|
if (!category.category || category.category.length === 0) {
|
||||||
throw Error('category has no name');
|
throw Error('category has no name');
|
||||||
@@ -42,24 +44,28 @@ function ensureValid(category: YamlCategory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseCategoryChild(
|
function parseCategoryChild(
|
||||||
categoryOrScript: any, children: ICategoryChildren, parent: YamlCategory) {
|
data: CategoryOrScriptData,
|
||||||
if (isCategory(categoryOrScript)) {
|
children: ICategoryChildren,
|
||||||
const subCategory = parseCategory(categoryOrScript as YamlCategory);
|
parent: CategoryData,
|
||||||
|
context: ICategoryCollectionParseContext) {
|
||||||
|
if (isCategory(data)) {
|
||||||
|
const subCategory = parseCategory(data as CategoryData, context);
|
||||||
children.subCategories.push(subCategory);
|
children.subCategories.push(subCategory);
|
||||||
} else if (isScript(categoryOrScript)) {
|
} else if (isScript(data)) {
|
||||||
const yamlScript = categoryOrScript as YamlScript;
|
const scriptData = data as ScriptData;
|
||||||
const script = parseScript(yamlScript);
|
const script = parseScript(scriptData, context);
|
||||||
children.subScripts.push(script);
|
children.subScripts.push(script);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Child element is neither a category or a script.
|
throw new Error(`Child element is neither a category or a script.
|
||||||
Parent: ${parent.category}, element: ${categoryOrScript}`);
|
Parent: ${parent.category}, element: ${JSON.stringify(data)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isScript(categoryOrScript: any): boolean {
|
function isScript(data: any): boolean {
|
||||||
return categoryOrScript.code && categoryOrScript.code.length > 0;
|
return (data.code && data.code.length > 0)
|
||||||
|
|| data.call;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isCategory(categoryOrScript: any): boolean {
|
function isCategory(data: any): boolean {
|
||||||
return categoryOrScript.category && categoryOrScript.category.length > 0;
|
return data.category && data.category.length > 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { YamlDocumentable, DocumentationUrls } from 'js-yaml-loader!./application.yaml';
|
import { DocumentableData, DocumentationUrlsData } from 'js-yaml-loader!@/*';
|
||||||
|
|
||||||
export function parseDocUrls(documentable: YamlDocumentable): ReadonlyArray<string> {
|
export function parseDocUrls(documentable: DocumentableData): ReadonlyArray<string> {
|
||||||
if (!documentable) {
|
if (!documentable) {
|
||||||
throw new Error('documentable is null or undefined');
|
throw new Error('documentable is null or undefined');
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ export function parseDocUrls(documentable: YamlDocumentable): ReadonlyArray<stri
|
|||||||
return result.getAll();
|
return result.getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDocs(docs: DocumentationUrls, urls: DocumentationUrlContainer): DocumentationUrlContainer {
|
function addDocs(docs: DocumentationUrlsData, urls: DocumentationUrlContainer): DocumentationUrlContainer {
|
||||||
if (docs instanceof Array) {
|
if (docs instanceof Array) {
|
||||||
urls.addUrls(docs);
|
urls.addUrls(docs);
|
||||||
} else if (typeof docs === 'string') {
|
} else if (typeof docs === 'string') {
|
||||||
@@ -32,7 +32,7 @@ class DocumentationUrlContainer {
|
|||||||
this.urls.push(url);
|
this.urls.push(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addUrls(urls: any[]) {
|
public addUrls(urls: readonly any[]) {
|
||||||
for (const url of urls) {
|
for (const url of urls) {
|
||||||
if (typeof url !== 'string') {
|
if (typeof url !== 'string') {
|
||||||
throw new Error('Docs field (documentation url) must be an array of strings');
|
throw new Error('Docs field (documentation url) must be an array of strings');
|
||||||
|
|||||||
12
src/application/Parser/ProjectInformationParser.ts
Normal file
12
src/application/Parser/ProjectInformationParser.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { IProjectInformation } from '@/domain/IProjectInformation';
|
||||||
|
import { ProjectInformation } from '@/domain/ProjectInformation';
|
||||||
|
|
||||||
|
export function parseProjectInformation(
|
||||||
|
environment: NodeJS.ProcessEnv): IProjectInformation {
|
||||||
|
return new ProjectInformation(
|
||||||
|
environment.VUE_APP_NAME,
|
||||||
|
environment.VUE_APP_VERSION,
|
||||||
|
environment.VUE_APP_REPOSITORY_URL,
|
||||||
|
environment.VUE_APP_HOMEPAGE_URL,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||||
|
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||||
|
import { FunctionData } from 'js-yaml-loader!*';
|
||||||
|
import { IScriptCompiler } from './Compiler/IScriptCompiler';
|
||||||
|
import { ScriptCompiler } from './Compiler/ScriptCompiler';
|
||||||
|
import { ICategoryCollectionParseContext } from './ICategoryCollectionParseContext';
|
||||||
|
import { SyntaxFactory } from './Syntax/SyntaxFactory';
|
||||||
|
import { ISyntaxFactory } from './Syntax/ISyntaxFactory';
|
||||||
|
|
||||||
|
export class CategoryCollectionParseContext implements ICategoryCollectionParseContext {
|
||||||
|
public readonly compiler: IScriptCompiler;
|
||||||
|
public readonly syntax: ILanguageSyntax;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
functionsData: ReadonlyArray<FunctionData> | undefined,
|
||||||
|
scripting: IScriptingDefinition,
|
||||||
|
syntaxFactory: ISyntaxFactory = new SyntaxFactory()) {
|
||||||
|
if (!scripting) { throw new Error('undefined scripting'); }
|
||||||
|
this.syntax = syntaxFactory.create(scripting.language);
|
||||||
|
this.compiler = new ScriptCompiler(functionsData, this.syntax);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { IExpressionsCompiler, ParameterValueDictionary } from './IExpressionsCompiler';
|
||||||
|
import { generateIlCode, IILCode } from './ILCode';
|
||||||
|
|
||||||
|
export class ExpressionsCompiler implements IExpressionsCompiler {
|
||||||
|
public static readonly instance: IExpressionsCompiler = new ExpressionsCompiler();
|
||||||
|
protected constructor() { }
|
||||||
|
public compileExpressions(code: string, parameters?: ParameterValueDictionary): string {
|
||||||
|
let intermediateCode = generateIlCode(code);
|
||||||
|
intermediateCode = substituteParameters(intermediateCode, parameters);
|
||||||
|
return intermediateCode.compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function substituteParameters(intermediateCode: IILCode, parameters: ParameterValueDictionary): IILCode {
|
||||||
|
const parameterNames = intermediateCode.getUniqueParameterNames();
|
||||||
|
ensureValuesProvided(parameterNames, parameters);
|
||||||
|
for (const parameterName of parameterNames) {
|
||||||
|
const parameterValue = parameters[parameterName];
|
||||||
|
intermediateCode = intermediateCode.substituteParameter(parameterName, parameterValue);
|
||||||
|
}
|
||||||
|
return intermediateCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureValuesProvided(names: string[], nameValues: ParameterValueDictionary) {
|
||||||
|
nameValues = nameValues || {};
|
||||||
|
const notProvidedNames = names.filter((name) => !Boolean(nameValues[name]));
|
||||||
|
if (notProvidedNames.length) {
|
||||||
|
throw new Error(`parameter value(s) not provided for: ${printList(notProvidedNames)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function printList(list: readonly string[]): string {
|
||||||
|
return `"${list.join('", "')}"`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export interface ParameterValueDictionary { [parameterName: string]: string; }
|
||||||
|
|
||||||
|
export interface IExpressionsCompiler {
|
||||||
|
compileExpressions(code: string, parameters?: ParameterValueDictionary): string;
|
||||||
|
}
|
||||||
73
src/application/Parser/Script/Compiler/Expressions/ILCode.ts
Normal file
73
src/application/Parser/Script/Compiler/Expressions/ILCode.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
export interface IILCode {
|
||||||
|
compile(): string;
|
||||||
|
getUniqueParameterNames(): string[];
|
||||||
|
substituteParameter(parameterName: string, parameterValue: string): IILCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateIlCode(rawText: string): IILCode {
|
||||||
|
const ilCode = generateIl(rawText);
|
||||||
|
return new ILCode(ilCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ILCode implements IILCode {
|
||||||
|
private readonly ilCode: string;
|
||||||
|
|
||||||
|
constructor(ilCode: string) {
|
||||||
|
this.ilCode = ilCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public substituteParameter(parameterName: string, parameterValue: string): IILCode {
|
||||||
|
const newCode = substituteParameter(this.ilCode, parameterName, parameterValue);
|
||||||
|
return new ILCode(newCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getUniqueParameterNames(): string[] {
|
||||||
|
return getUniqueParameterNames(this.ilCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public compile(): string {
|
||||||
|
ensureNoExpressionLeft(this.ilCode);
|
||||||
|
return this.ilCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trim each expression and put them inside "{{exp|}}" e.g. "{{ $hello }}" becomes "{{exp|$hello}}"
|
||||||
|
function generateIl(rawText: string): string {
|
||||||
|
return rawText.replace(/\{\{([\s]*[^;\s\{]+[\s]*)\}\}/g, (_, match) => {
|
||||||
|
return `\{\{exp|${match.trim()}\}\}`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// finds all "{{exp|..}} left"
|
||||||
|
function ensureNoExpressionLeft(ilCode: string) {
|
||||||
|
const allSubstitutions = ilCode.matchAll(/\{\{exp\|(.*?)\}\}/g);
|
||||||
|
const allMatches = Array.from(allSubstitutions, (match) => match[1]);
|
||||||
|
const uniqueExpressions = getDistinctValues(allMatches);
|
||||||
|
if (uniqueExpressions.length > 0) {
|
||||||
|
throw new Error(`unknown expression: ${printList(uniqueExpressions)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parses all distinct usages of {{exp|$parameterName}}
|
||||||
|
function getUniqueParameterNames(ilCode: string) {
|
||||||
|
const allSubstitutions = ilCode.matchAll(/\{\{exp\|\$([^;\s\{]+[\s]*)\}\}/g);
|
||||||
|
const allParameters = Array.from(allSubstitutions, (match) => match[1]);
|
||||||
|
const uniqueParameterNames = getDistinctValues(allParameters);
|
||||||
|
return uniqueParameterNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
// substitutes {{exp|$parameterName}} to value of the parameter
|
||||||
|
function substituteParameter(ilCode: string, parameterName: string, parameterValue: string) {
|
||||||
|
const pattern = `{{exp|$${parameterName}}}`;
|
||||||
|
return ilCode.split(pattern).join(parameterValue); // as .replaceAll() is not yet supported by TS
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDistinctValues(values: readonly string[]): string[] {
|
||||||
|
return values.filter((value, index, self) => {
|
||||||
|
return self.indexOf(value) === index;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function printList(list: readonly string[]): string {
|
||||||
|
return `"${list.join('","')}"`;
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
import { FunctionData, InstructionHolder } from 'js-yaml-loader!*';
|
||||||
|
import { SharedFunction } from './SharedFunction';
|
||||||
|
import { SharedFunctionCollection } from './SharedFunctionCollection';
|
||||||
|
import { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||||
|
import { IFunctionCompiler } from './IFunctionCompiler';
|
||||||
|
import { IFunctionCallCompiler } from '../FunctionCall/IFunctionCallCompiler';
|
||||||
|
import { FunctionCallCompiler } from '../FunctionCall/FunctionCallCompiler';
|
||||||
|
|
||||||
|
export class FunctionCompiler implements IFunctionCompiler {
|
||||||
|
public static readonly instance: IFunctionCompiler = new FunctionCompiler();
|
||||||
|
protected constructor(
|
||||||
|
private readonly functionCallCompiler: IFunctionCallCompiler = FunctionCallCompiler.instance) {
|
||||||
|
}
|
||||||
|
public compileFunctions(functions: readonly FunctionData[]): ISharedFunctionCollection {
|
||||||
|
const collection = new SharedFunctionCollection();
|
||||||
|
if (!functions || !functions.length) {
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
ensureValidFunctions(functions);
|
||||||
|
functions
|
||||||
|
.filter((func) => hasCode(func))
|
||||||
|
.forEach((func) => {
|
||||||
|
const shared = new SharedFunction(func.name, func.parameters, func.code, func.revertCode);
|
||||||
|
collection.addFunction(shared);
|
||||||
|
});
|
||||||
|
functions
|
||||||
|
.filter((func) => hasCall(func))
|
||||||
|
.forEach((func) => {
|
||||||
|
const code = this.functionCallCompiler.compileCall(func.call, collection);
|
||||||
|
const shared = new SharedFunction(func.name, func.parameters, code.code, code.revertCode);
|
||||||
|
collection.addFunction(shared);
|
||||||
|
});
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasCode(data: FunctionData): boolean {
|
||||||
|
return Boolean(data.code);
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasCall(data: FunctionData): boolean {
|
||||||
|
return Boolean(data.call);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function ensureValidFunctions(functions: readonly FunctionData[]) {
|
||||||
|
ensureNoUndefinedItem(functions);
|
||||||
|
ensureNoDuplicatesInFunctionNames(functions);
|
||||||
|
ensureNoDuplicatesInParameterNames(functions);
|
||||||
|
ensureNoDuplicateCode(functions);
|
||||||
|
ensureEitherCallOrCodeIsDefined(functions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function printList(list: readonly string[]): string {
|
||||||
|
return `"${list.join('","')}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureEitherCallOrCodeIsDefined(holders: readonly InstructionHolder[]) {
|
||||||
|
// Ensure functions do not define both call and code
|
||||||
|
const withBothCallAndCode = holders.filter((holder) => hasCode(holder) && hasCall(holder));
|
||||||
|
if (withBothCallAndCode.length) {
|
||||||
|
throw new Error(`both "code" and "call" are defined in ${printNames(withBothCallAndCode)}`);
|
||||||
|
}
|
||||||
|
// Ensure functions have either code or call
|
||||||
|
const hasEitherCodeOrCall = holders.filter((holder) => !hasCode(holder) && !hasCall(holder));
|
||||||
|
if (hasEitherCodeOrCall.length) {
|
||||||
|
throw new Error(`neither "code" or "call" is defined in ${printNames(hasEitherCodeOrCall)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function printNames(holders: readonly InstructionHolder[]) {
|
||||||
|
return printList(holders.map((holder) => holder.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureNoDuplicatesInFunctionNames(functions: readonly FunctionData[]) {
|
||||||
|
const duplicateFunctionNames = getDuplicates(functions
|
||||||
|
.map((func) => func.name.toLowerCase()));
|
||||||
|
if (duplicateFunctionNames.length) {
|
||||||
|
throw new Error(`duplicate function name: ${printList(duplicateFunctionNames)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function ensureNoUndefinedItem(functions: readonly FunctionData[]) {
|
||||||
|
if (functions.some((func) => !func)) {
|
||||||
|
throw new Error(`some functions are undefined`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function ensureNoDuplicatesInParameterNames(functions: readonly FunctionData[]) {
|
||||||
|
const functionsWithParameters = functions
|
||||||
|
.filter((func) => func.parameters && func.parameters.length > 0);
|
||||||
|
for (const func of functionsWithParameters) {
|
||||||
|
const duplicateParameterNames = getDuplicates(func.parameters);
|
||||||
|
if (duplicateParameterNames.length) {
|
||||||
|
throw new Error(`"${func.name}": duplicate parameter name: ${printList(duplicateParameterNames)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function ensureNoDuplicateCode(functions: readonly FunctionData[]) {
|
||||||
|
const duplicateCodes = getDuplicates(functions
|
||||||
|
.map((func) => func.code)
|
||||||
|
.filter((code) => code),
|
||||||
|
);
|
||||||
|
if (duplicateCodes.length > 0) {
|
||||||
|
throw new Error(`duplicate "code" in functions: ${printList(duplicateCodes)}`);
|
||||||
|
}
|
||||||
|
const duplicateRevertCodes = getDuplicates(functions
|
||||||
|
.filter((func) => func.revertCode)
|
||||||
|
.map((func) => func.revertCode));
|
||||||
|
if (duplicateRevertCodes.length > 0) {
|
||||||
|
throw new Error(`duplicate "revertCode" in functions: ${printList(duplicateRevertCodes)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDuplicates(texts: readonly string[]): string[] {
|
||||||
|
return texts.filter((item, index) => texts.indexOf(item) !== index);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { FunctionData } from 'js-yaml-loader!*';
|
||||||
|
import { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||||
|
|
||||||
|
export interface IFunctionCompiler {
|
||||||
|
compileFunctions(functions: readonly FunctionData[]): ISharedFunctionCollection;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
export interface ISharedFunction {
|
||||||
|
readonly name: string;
|
||||||
|
readonly parameters?: readonly string[];
|
||||||
|
readonly code: string;
|
||||||
|
readonly revertCode?: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { ISharedFunction } from './ISharedFunction';
|
||||||
|
|
||||||
|
export interface ISharedFunctionCollection {
|
||||||
|
getFunctionByName(name: string): ISharedFunction;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { ISharedFunction } from './ISharedFunction';
|
||||||
|
|
||||||
|
export class SharedFunction implements ISharedFunction {
|
||||||
|
constructor(
|
||||||
|
public readonly name: string,
|
||||||
|
public readonly parameters: readonly string[],
|
||||||
|
public readonly code: string,
|
||||||
|
public readonly revertCode: string,
|
||||||
|
) {
|
||||||
|
if (!name) { throw new Error('undefined function name'); }
|
||||||
|
if (!code) { throw new Error(`undefined function ("${name}") code`); }
|
||||||
|
this.parameters = parameters || [];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ISharedFunction } from './ISharedFunction';
|
||||||
|
import { ISharedFunctionCollection } from './ISharedFunctionCollection';
|
||||||
|
|
||||||
|
export class SharedFunctionCollection implements ISharedFunctionCollection {
|
||||||
|
private readonly functionsByName = new Map<string, ISharedFunction>();
|
||||||
|
|
||||||
|
public addFunction(func: ISharedFunction): void {
|
||||||
|
if (!func) { throw new Error('undefined function'); }
|
||||||
|
if (this.functionsByName.has(func.name)) {
|
||||||
|
throw new Error(`function with name ${func.name} already exists`);
|
||||||
|
}
|
||||||
|
this.functionsByName.set(func.name, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getFunctionByName(name: string): ISharedFunction {
|
||||||
|
if (!name) { throw Error('undefined function name'); }
|
||||||
|
const func = this.functionsByName.get(name);
|
||||||
|
if (!func) {
|
||||||
|
throw new Error(`called function is not defined "${name}"`);
|
||||||
|
}
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import { FunctionCallData, FunctionCallParametersData, FunctionData, ScriptFunctionCallData } from 'js-yaml-loader!*';
|
||||||
|
import { ICompiledCode } from './ICompiledCode';
|
||||||
|
import { ISharedFunctionCollection } from '../Function/ISharedFunctionCollection';
|
||||||
|
import { IFunctionCallCompiler } from './IFunctionCallCompiler';
|
||||||
|
import { IExpressionsCompiler } from '../Expressions/IExpressionsCompiler';
|
||||||
|
import { ExpressionsCompiler } from '../Expressions/ExpressionsCompiler';
|
||||||
|
|
||||||
|
export class FunctionCallCompiler implements IFunctionCallCompiler {
|
||||||
|
public static readonly instance: IFunctionCallCompiler = new FunctionCallCompiler();
|
||||||
|
protected constructor(
|
||||||
|
private readonly expressionsCompiler: IExpressionsCompiler = ExpressionsCompiler.instance) { }
|
||||||
|
public compileCall(
|
||||||
|
call: ScriptFunctionCallData,
|
||||||
|
functions: ISharedFunctionCollection): ICompiledCode {
|
||||||
|
if (!functions) { throw new Error('undefined functions'); }
|
||||||
|
if (!call) { throw new Error('undefined call'); }
|
||||||
|
const compiledCodes = new Array<ICompiledCode>();
|
||||||
|
const calls = getCallSequence(call);
|
||||||
|
calls.forEach((currentCall, currentCallIndex) => {
|
||||||
|
ensureValidCall(currentCall);
|
||||||
|
const commonFunction = functions.getFunctionByName(currentCall.function);
|
||||||
|
ensureExpectedParameters(commonFunction, currentCall);
|
||||||
|
let functionCode = compileCode(commonFunction, currentCall.parameters, this.expressionsCompiler);
|
||||||
|
if (currentCallIndex !== calls.length - 1) {
|
||||||
|
functionCode = appendLine(functionCode);
|
||||||
|
}
|
||||||
|
compiledCodes.push(functionCode);
|
||||||
|
});
|
||||||
|
const compiledCode = merge(compiledCodes);
|
||||||
|
return compiledCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureExpectedParameters(func: FunctionData, call: FunctionCallData) {
|
||||||
|
if (!func.parameters && !call.parameters) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const unexpectedParameters = Object.keys(call.parameters || {})
|
||||||
|
.filter((callParam) => !func.parameters.includes(callParam));
|
||||||
|
if (unexpectedParameters.length) {
|
||||||
|
throw new Error(
|
||||||
|
`function "${func.name}" has unexpected parameter(s) provided: "${unexpectedParameters.join('", "')}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge(codes: readonly ICompiledCode[]): ICompiledCode {
|
||||||
|
return {
|
||||||
|
code: codes.map((code) => code.code).join(''),
|
||||||
|
revertCode: codes.map((code) => code.revertCode).join(''),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function compileCode(
|
||||||
|
func: FunctionData,
|
||||||
|
parameters: FunctionCallParametersData,
|
||||||
|
compiler: IExpressionsCompiler): ICompiledCode {
|
||||||
|
return {
|
||||||
|
code: compiler.compileExpressions(func.code, parameters),
|
||||||
|
revertCode: compiler.compileExpressions(func.revertCode, parameters),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCallSequence(call: ScriptFunctionCallData): FunctionCallData[] {
|
||||||
|
if (typeof call !== 'object') {
|
||||||
|
throw new Error('called function(s) must be an object');
|
||||||
|
}
|
||||||
|
if (call instanceof Array) {
|
||||||
|
return call as FunctionCallData[];
|
||||||
|
}
|
||||||
|
return [ call as FunctionCallData ];
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureValidCall(call: FunctionCallData) {
|
||||||
|
if (!call) {
|
||||||
|
throw new Error(`undefined function call`);
|
||||||
|
}
|
||||||
|
if (!call.function) {
|
||||||
|
throw new Error(`empty function name called`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendLine(code: ICompiledCode): ICompiledCode {
|
||||||
|
const appendLineIfNotEmpty = (str: string) => str ? `${str}\n` : str;
|
||||||
|
return {
|
||||||
|
code: appendLineIfNotEmpty(code.code),
|
||||||
|
revertCode: appendLineIfNotEmpty(code.revertCode),
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export interface ICompiledCode {
|
||||||
|
readonly code: string;
|
||||||
|
readonly revertCode?: string;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { ScriptFunctionCallData } from 'js-yaml-loader!*';
|
||||||
|
import { ICompiledCode } from './ICompiledCode';
|
||||||
|
import { ISharedFunctionCollection } from '../Function/ISharedFunctionCollection';
|
||||||
|
|
||||||
|
export interface IFunctionCallCompiler {
|
||||||
|
compileCall(
|
||||||
|
call: ScriptFunctionCallData,
|
||||||
|
functions: ISharedFunctionCollection): ICompiledCode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { IScriptCode } from '@/domain/IScriptCode';
|
||||||
|
import { ScriptData } from 'js-yaml-loader!@/*';
|
||||||
|
|
||||||
|
export interface IScriptCompiler {
|
||||||
|
canCompile(script: ScriptData): boolean;
|
||||||
|
compile(script: ScriptData): IScriptCode;
|
||||||
|
}
|
||||||
42
src/application/Parser/Script/Compiler/ScriptCompiler.ts
Normal file
42
src/application/Parser/Script/Compiler/ScriptCompiler.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { IScriptCode } from '@/domain/IScriptCode';
|
||||||
|
import { ScriptCode } from '@/domain/ScriptCode';
|
||||||
|
import { FunctionData, ScriptData } from 'js-yaml-loader!@/*';
|
||||||
|
import { IScriptCompiler } from './IScriptCompiler';
|
||||||
|
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||||
|
import { ISharedFunctionCollection } from './Function/ISharedFunctionCollection';
|
||||||
|
import { IFunctionCallCompiler } from './FunctionCall/IFunctionCallCompiler';
|
||||||
|
import { FunctionCallCompiler } from './FunctionCall/FunctionCallCompiler';
|
||||||
|
import { IFunctionCompiler } from './Function/IFunctionCompiler';
|
||||||
|
import { FunctionCompiler } from './Function/FunctionCompiler';
|
||||||
|
|
||||||
|
export class ScriptCompiler implements IScriptCompiler {
|
||||||
|
private readonly functions: ISharedFunctionCollection;
|
||||||
|
constructor(
|
||||||
|
functions: readonly FunctionData[] | undefined,
|
||||||
|
private readonly syntax: ILanguageSyntax,
|
||||||
|
functionCompiler: IFunctionCompiler = FunctionCompiler.instance,
|
||||||
|
private readonly callCompiler: IFunctionCallCompiler = FunctionCallCompiler.instance,
|
||||||
|
) {
|
||||||
|
if (!syntax) { throw new Error('undefined syntax'); }
|
||||||
|
this.functions = functionCompiler.compileFunctions(functions);
|
||||||
|
}
|
||||||
|
public canCompile(script: ScriptData): boolean {
|
||||||
|
if (!script) { throw new Error('undefined script'); }
|
||||||
|
if (!script.call) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public compile(script: ScriptData): IScriptCode {
|
||||||
|
if (!script) { throw new Error('undefined script'); }
|
||||||
|
try {
|
||||||
|
const compiledCode = this.callCompiler.compileCall(script.call, this.functions);
|
||||||
|
return new ScriptCode(
|
||||||
|
compiledCode.code,
|
||||||
|
compiledCode.revertCode,
|
||||||
|
this.syntax);
|
||||||
|
} catch (error) {
|
||||||
|
throw Error(`Script "${script.name}" ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||||
|
import { IScriptCompiler } from './Compiler/IScriptCompiler';
|
||||||
|
|
||||||
|
export interface ICategoryCollectionParseContext {
|
||||||
|
readonly compiler: IScriptCompiler;
|
||||||
|
readonly syntax: ILanguageSyntax;
|
||||||
|
}
|
||||||
54
src/application/Parser/Script/ScriptParser.ts
Normal file
54
src/application/Parser/Script/ScriptParser.ts
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import { Script } from '@/domain/Script';
|
||||||
|
import { ScriptData } from 'js-yaml-loader!@/*';
|
||||||
|
import { parseDocUrls } from '../DocumentationParser';
|
||||||
|
import { RecommendationLevel } from '@/domain/RecommendationLevel';
|
||||||
|
import { IScriptCode } from '@/domain/IScriptCode';
|
||||||
|
import { ScriptCode } from '@/domain/ScriptCode';
|
||||||
|
import { createEnumParser, IEnumParser } from '../../Common/Enum';
|
||||||
|
import { ICategoryCollectionParseContext } from './ICategoryCollectionParseContext';
|
||||||
|
|
||||||
|
export function parseScript(
|
||||||
|
data: ScriptData, context: ICategoryCollectionParseContext,
|
||||||
|
levelParser = createEnumParser(RecommendationLevel)): Script {
|
||||||
|
validateScript(data);
|
||||||
|
if (!context) { throw new Error('undefined context'); }
|
||||||
|
const script = new Script(
|
||||||
|
/* name */ data.name,
|
||||||
|
/* code */ parseCode(data, context),
|
||||||
|
/* docs */ parseDocUrls(data),
|
||||||
|
/* level */ parseLevel(data.recommend, levelParser));
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseLevel(level: string, parser: IEnumParser<RecommendationLevel>): RecommendationLevel | undefined {
|
||||||
|
if (!level) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return parser.parseEnum(level, 'level');
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCode(script: ScriptData, context: ICategoryCollectionParseContext): IScriptCode {
|
||||||
|
if (context.compiler.canCompile(script)) {
|
||||||
|
return context.compiler.compile(script);
|
||||||
|
}
|
||||||
|
return new ScriptCode(script.code, script.revertCode, context.syntax);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureNotBothCallAndCode(script: ScriptData) {
|
||||||
|
if (script.code && script.call) {
|
||||||
|
throw new Error('cannot define both "call" and "code"');
|
||||||
|
}
|
||||||
|
if (script.revertCode && script.call) {
|
||||||
|
throw new Error('cannot define "revertCode" if "call" is defined');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateScript(script: ScriptData) {
|
||||||
|
if (!script) {
|
||||||
|
throw new Error('undefined script');
|
||||||
|
}
|
||||||
|
if (!script.code && !script.call) {
|
||||||
|
throw new Error('must define either "call" or "code"');
|
||||||
|
}
|
||||||
|
ensureNotBothCallAndCode(script);
|
||||||
|
}
|
||||||
6
src/application/Parser/Script/Syntax/BatchFileSyntax.ts
Normal file
6
src/application/Parser/Script/Syntax/BatchFileSyntax.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||||
|
|
||||||
|
export class BatchFileSyntax implements ILanguageSyntax {
|
||||||
|
public readonly commentDelimiters = [ 'REM', '::' ];
|
||||||
|
public readonly commonCodeParts = [ '(', ')', 'else' ];
|
||||||
|
}
|
||||||
6
src/application/Parser/Script/Syntax/ISyntaxFactory.ts
Normal file
6
src/application/Parser/Script/Syntax/ISyntaxFactory.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||||
|
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||||
|
|
||||||
|
export interface ISyntaxFactory {
|
||||||
|
create(language: ScriptingLanguage): ILanguageSyntax;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||||
|
|
||||||
|
export class ShellScriptSyntax implements ILanguageSyntax {
|
||||||
|
public readonly commentDelimiters = [ '#' ];
|
||||||
|
public readonly commonCodeParts = [ '(', ')', 'else' ];
|
||||||
|
}
|
||||||
15
src/application/Parser/Script/Syntax/SyntaxFactory.ts
Normal file
15
src/application/Parser/Script/Syntax/SyntaxFactory.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||||
|
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||||
|
import { ISyntaxFactory } from './ISyntaxFactory';
|
||||||
|
import { BatchFileSyntax } from './BatchFileSyntax';
|
||||||
|
import { ShellScriptSyntax } from './ShellScriptSyntax';
|
||||||
|
|
||||||
|
export class SyntaxFactory implements ISyntaxFactory {
|
||||||
|
public create(language: ScriptingLanguage): ILanguageSyntax {
|
||||||
|
switch (language) {
|
||||||
|
case ScriptingLanguage.batchfile: return new BatchFileSyntax();
|
||||||
|
case ScriptingLanguage.shellscript: return new ShellScriptSyntax();
|
||||||
|
default: throw new RangeError(`unknown language: "${ScriptingLanguage[language]}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { Script } from '@/domain/Script';
|
|
||||||
import { YamlScript } from 'js-yaml-loader!./application.yaml';
|
|
||||||
import { parseDocUrls } from './DocumentationParser';
|
|
||||||
|
|
||||||
export function parseScript(yamlScript: YamlScript): Script {
|
|
||||||
if (!yamlScript) {
|
|
||||||
throw new Error('script is null or undefined');
|
|
||||||
}
|
|
||||||
const script = new Script(
|
|
||||||
/* name */ yamlScript.name,
|
|
||||||
/* code */ yamlScript.code,
|
|
||||||
/* revertCode */ yamlScript.revertCode,
|
|
||||||
/* docs */ parseDocUrls(yamlScript),
|
|
||||||
/* isRecommended */ yamlScript.recommend);
|
|
||||||
return script;
|
|
||||||
}
|
|
||||||
36
src/application/Parser/ScriptingDefinitionParser.ts
Normal file
36
src/application/Parser/ScriptingDefinitionParser.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
|
||||||
|
import { ScriptingDefinitionData } from 'js-yaml-loader!@/*';
|
||||||
|
import { ScriptingDefinition } from '@/domain/ScriptingDefinition';
|
||||||
|
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||||
|
import { IProjectInformation } from '@/domain/IProjectInformation';
|
||||||
|
import { createEnumParser } from '../Common/Enum';
|
||||||
|
import { generateIlCode } from './Script/Compiler/Expressions/ILCode';
|
||||||
|
|
||||||
|
export function parseScriptingDefinition(
|
||||||
|
definition: ScriptingDefinitionData,
|
||||||
|
info: IProjectInformation,
|
||||||
|
date = new Date(),
|
||||||
|
languageParser = createEnumParser(ScriptingLanguage)): IScriptingDefinition {
|
||||||
|
if (!info) {
|
||||||
|
throw new Error('undefined info');
|
||||||
|
}
|
||||||
|
if (!definition) {
|
||||||
|
throw new Error('undefined definition');
|
||||||
|
}
|
||||||
|
const language = languageParser.parseEnum(definition.language, 'language');
|
||||||
|
const startCode = applySubstitutions(definition.startCode, info, date);
|
||||||
|
const endCode = applySubstitutions(definition.endCode, info, date);
|
||||||
|
return new ScriptingDefinition(
|
||||||
|
language,
|
||||||
|
startCode,
|
||||||
|
endCode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applySubstitutions(code: string, info: IProjectInformation, date: Date): string {
|
||||||
|
let ilCode = generateIlCode(code);
|
||||||
|
ilCode = ilCode.substituteParameter('homepage', info.homepage);
|
||||||
|
ilCode = ilCode.substituteParameter('version', info.version);
|
||||||
|
ilCode = ilCode.substituteParameter('date', date.toUTCString());
|
||||||
|
return ilCode.compile();
|
||||||
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { UserFilter } from './Filter/UserFilter';
|
|
||||||
import { IUserFilter } from './Filter/IUserFilter';
|
|
||||||
import { ApplicationCode } from './Code/ApplicationCode';
|
|
||||||
import { UserSelection } from './Selection/UserSelection';
|
|
||||||
import { IUserSelection } from './Selection/IUserSelection';
|
|
||||||
import { AsyncLazy } from '@/infrastructure/Threading/AsyncLazy';
|
|
||||||
import { Signal } from '@/infrastructure/Events/Signal';
|
|
||||||
import { parseApplication } from '../Parser/ApplicationParser';
|
|
||||||
import { IApplicationState } from './IApplicationState';
|
|
||||||
import { Script } from '@/domain/Script';
|
|
||||||
import { IApplication } from '@/domain/IApplication';
|
|
||||||
import { IApplicationCode } from './Code/IApplicationCode';
|
|
||||||
import applicationFile from 'js-yaml-loader!@/application/application.yaml';
|
|
||||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
|
||||||
|
|
||||||
/** Mutatable singleton application state that's the single source of truth throughout the application */
|
|
||||||
export class ApplicationState implements IApplicationState {
|
|
||||||
/** Get singleton application state */
|
|
||||||
public static GetAsync(): Promise<IApplicationState> {
|
|
||||||
return ApplicationState.instance.getValueAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Application instance with all scripts. */
|
|
||||||
private static instance = new AsyncLazy<IApplicationState>(() => {
|
|
||||||
const application = parseApplication(applicationFile);
|
|
||||||
const selectedScripts = new Array<Script>();
|
|
||||||
const state = new ApplicationState(application, selectedScripts);
|
|
||||||
return Promise.resolve(state);
|
|
||||||
});
|
|
||||||
|
|
||||||
public readonly code: IApplicationCode;
|
|
||||||
public readonly stateChanged = new Signal<IApplicationState>();
|
|
||||||
public readonly selection: IUserSelection;
|
|
||||||
public readonly filter: IUserFilter;
|
|
||||||
|
|
||||||
private constructor(
|
|
||||||
/** Inner instance of the all scripts */
|
|
||||||
public readonly app: IApplication,
|
|
||||||
/** Initially selected scripts */
|
|
||||||
public readonly defaultScripts: Script[]) {
|
|
||||||
this.selection = new UserSelection(app, defaultScripts.map((script) => new SelectedScript(script, false)));
|
|
||||||
this.code = new ApplicationCode(this.selection, app.version);
|
|
||||||
this.filter = new UserFilter(app);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
|
||||||
import { ICodePosition } from '@/application/State/Code/Position/ICodePosition';
|
|
||||||
|
|
||||||
export interface IUserScript {
|
|
||||||
code: string;
|
|
||||||
scriptPositions: Map<SelectedScript, ICodePosition>;
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
|
||||||
import { IUserScript } from './IUserScript';
|
|
||||||
export interface IUserScriptGenerator {
|
|
||||||
buildCode(
|
|
||||||
selectedScripts: ReadonlyArray<SelectedScript>,
|
|
||||||
version: string): IUserScript;
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import { SelectedScript } from '@/application/State/Selection/SelectedScript';
|
|
||||||
import { IUserScriptGenerator } from './IUserScriptGenerator';
|
|
||||||
import { CodeBuilder } from './CodeBuilder';
|
|
||||||
import { ICodePosition } from '@/application/State/Code/Position/ICodePosition';
|
|
||||||
import { CodePosition } from '../Position/CodePosition';
|
|
||||||
import { IUserScript } from './IUserScript';
|
|
||||||
|
|
||||||
export const adminRightsScript = {
|
|
||||||
name: 'Ensure admin privileges',
|
|
||||||
code: 'fltmc >nul 2>&1 || (\n' +
|
|
||||||
' echo Administrator privileges are required.\n' +
|
|
||||||
' PowerShell Start -Verb RunAs \'%0\' 2> nul || (\n' +
|
|
||||||
' echo Right-click on the script and select "Run as administrator".\n' +
|
|
||||||
' pause & exit 1\n' +
|
|
||||||
' )\n' +
|
|
||||||
' exit 0\n' +
|
|
||||||
')',
|
|
||||||
};
|
|
||||||
|
|
||||||
export class UserScriptGenerator implements IUserScriptGenerator {
|
|
||||||
public buildCode(selectedScripts: ReadonlyArray<SelectedScript>, version: string): IUserScript {
|
|
||||||
if (!selectedScripts) { throw new Error('scripts is undefined'); }
|
|
||||||
if (!version) { throw new Error('version is undefined'); }
|
|
||||||
let scriptPositions = new Map<SelectedScript, ICodePosition>();
|
|
||||||
if (!selectedScripts.length) {
|
|
||||||
return { code: '', scriptPositions };
|
|
||||||
}
|
|
||||||
const builder = initializeCode(version);
|
|
||||||
for (const selection of selectedScripts) {
|
|
||||||
scriptPositions = appendSelection(selection, scriptPositions, builder);
|
|
||||||
}
|
|
||||||
const code = finalizeCode(builder);
|
|
||||||
return { code, scriptPositions };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function initializeCode(version: string): CodeBuilder {
|
|
||||||
return new CodeBuilder()
|
|
||||||
.appendLine('@echo off')
|
|
||||||
.appendCommentLine(`https://privacy.sexy — v${version} — ${new Date().toUTCString()}`)
|
|
||||||
.appendFunction(adminRightsScript.name, adminRightsScript.code)
|
|
||||||
.appendLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
function finalizeCode(builder: CodeBuilder): string {
|
|
||||||
return builder.appendLine()
|
|
||||||
.appendLine('pause')
|
|
||||||
.appendLine('exit /b 0')
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendSelection(
|
|
||||||
selection: SelectedScript,
|
|
||||||
scriptPositions: Map<SelectedScript, ICodePosition>,
|
|
||||||
builder: CodeBuilder): Map<SelectedScript, ICodePosition> {
|
|
||||||
const startPosition = builder.currentLine + 1;
|
|
||||||
appendCode(selection, builder);
|
|
||||||
const endPosition = builder.currentLine - 1;
|
|
||||||
builder.appendLine();
|
|
||||||
scriptPositions.set(selection, new CodePosition(startPosition, endPosition));
|
|
||||||
return scriptPositions;
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendCode(selection: SelectedScript, builder: CodeBuilder) {
|
|
||||||
const name = selection.revert ? `${selection.script.name} (revert)` : selection.script.name;
|
|
||||||
const scriptCode = selection.revert ? selection.script.revertCode : selection.script.code;
|
|
||||||
builder.appendFunction(name, scriptCode);
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import { IFilterResult } from './IFilterResult';
|
|
||||||
import { ISignal } from '@/infrastructure/Events/Signal';
|
|
||||||
|
|
||||||
export interface IUserFilter {
|
|
||||||
readonly filtered: ISignal<IFilterResult>;
|
|
||||||
readonly filterRemoved: ISignal<void>;
|
|
||||||
setFilter(filter: string): void;
|
|
||||||
removeFilter(): void;
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { IApplication } from './../../domain/IApplication';
|
|
||||||
import { IUserFilter } from './Filter/IUserFilter';
|
|
||||||
import { IUserSelection } from './Selection/IUserSelection';
|
|
||||||
import { ISignal } from '@/infrastructure/Events/ISignal';
|
|
||||||
import { IApplicationCode } from './Code/IApplicationCode';
|
|
||||||
export { IUserSelection, IApplicationCode, IUserFilter };
|
|
||||||
|
|
||||||
export interface IApplicationState {
|
|
||||||
/** Event that fires when the application states changes with new application state as parameter */
|
|
||||||
readonly code: IApplicationCode;
|
|
||||||
readonly filter: IUserFilter;
|
|
||||||
readonly stateChanged: ISignal<IApplicationState>;
|
|
||||||
readonly selection: IUserSelection;
|
|
||||||
readonly app: IApplication;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
29
src/application/application.yaml.d.ts
vendored
29
src/application/application.yaml.d.ts
vendored
@@ -1,29 +0,0 @@
|
|||||||
declare module 'js-yaml-loader!*' {
|
|
||||||
export type CategoryOrScript = YamlCategory | YamlScript;
|
|
||||||
export type DocumentationUrls = ReadonlyArray<string> | string;
|
|
||||||
|
|
||||||
export interface YamlDocumentable {
|
|
||||||
docs?: DocumentationUrls;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface YamlScript extends YamlDocumentable {
|
|
||||||
name: string;
|
|
||||||
code: string;
|
|
||||||
revertCode: string;
|
|
||||||
recommend: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface YamlCategory extends YamlDocumentable {
|
|
||||||
children: ReadonlyArray<CategoryOrScript>;
|
|
||||||
category: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ApplicationYaml {
|
|
||||||
name: string;
|
|
||||||
repositoryUrl: string;
|
|
||||||
actions: ReadonlyArray<YamlCategory>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const content: ApplicationYaml;
|
|
||||||
export default content;
|
|
||||||
}
|
|
||||||
59
src/application/collections/collection.yaml.d.ts
vendored
Normal file
59
src/application/collections/collection.yaml.d.ts
vendored
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
declare module 'js-yaml-loader!*' {
|
||||||
|
export interface CollectionData {
|
||||||
|
readonly os: string;
|
||||||
|
readonly scripting: ScriptingDefinitionData;
|
||||||
|
readonly actions: ReadonlyArray<CategoryData>;
|
||||||
|
readonly functions?: ReadonlyArray<FunctionData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CategoryData extends DocumentableData {
|
||||||
|
readonly children: ReadonlyArray<CategoryOrScriptData>;
|
||||||
|
readonly category: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CategoryOrScriptData = CategoryData | ScriptData;
|
||||||
|
export type DocumentationUrlsData = ReadonlyArray<string> | string;
|
||||||
|
|
||||||
|
export interface DocumentableData {
|
||||||
|
readonly docs?: DocumentationUrlsData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InstructionHolder {
|
||||||
|
readonly name: string;
|
||||||
|
|
||||||
|
readonly code?: string;
|
||||||
|
readonly revertCode?: string;
|
||||||
|
|
||||||
|
readonly call?: ScriptFunctionCallData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FunctionData extends InstructionHolder {
|
||||||
|
readonly parameters?: readonly string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FunctionCallParametersData {
|
||||||
|
readonly [index: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FunctionCallData {
|
||||||
|
readonly function: string;
|
||||||
|
readonly parameters?: FunctionCallParametersData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ScriptFunctionCallData = readonly FunctionCallData[] | FunctionCallData | undefined;
|
||||||
|
|
||||||
|
export interface ScriptData extends InstructionHolder, DocumentableData {
|
||||||
|
readonly name: string;
|
||||||
|
readonly recommend?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScriptingDefinitionData {
|
||||||
|
readonly language: string;
|
||||||
|
readonly fileExtension: string;
|
||||||
|
readonly startCode: string;
|
||||||
|
readonly endCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const content: CollectionData;
|
||||||
|
export default content;
|
||||||
|
}
|
||||||
523
src/application/collections/macos.yaml
Normal file
523
src/application/collections/macos.yaml
Normal file
@@ -0,0 +1,523 @@
|
|||||||
|
# Structure documented in "docs/collections.md"
|
||||||
|
os: macos
|
||||||
|
scripting:
|
||||||
|
language: shellscript
|
||||||
|
startCode: |-
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# {{ $homepage }} — v{{ $version }} — {{ $date }}
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
script_path=$([[ "$0" = /* ]] && echo "$0" || echo "$PWD/${0#./}")
|
||||||
|
sudo "$script_path" || (
|
||||||
|
echo 'Administrator privileges are required.'
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
endCode: |-
|
||||||
|
echo 'Your privacy and security is now hardened 🎉💪'
|
||||||
|
echo 'Press any key to exit.'
|
||||||
|
read -n 1 -s
|
||||||
|
actions:
|
||||||
|
-
|
||||||
|
category: Privacy cleanup
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
category: Clear terminal history
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Clear bash history
|
||||||
|
recommend: standard
|
||||||
|
code: rm -f ~/.bash_history
|
||||||
|
-
|
||||||
|
name: Clear zsh history
|
||||||
|
recommend: standard
|
||||||
|
code: rm -f ~/.zsh_history
|
||||||
|
-
|
||||||
|
name: Clear CUPS printer job cache
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
sudo rm -rfv /var/spool/cups/c0*
|
||||||
|
sudo rm -rfv /var/spool/cups/tmp/*
|
||||||
|
sudo rm -rfv /var/spool/cups/cache/job.cache*
|
||||||
|
-
|
||||||
|
name: Empty trash on all volumes
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
# on all mounted volumes
|
||||||
|
sudo rm -rfv /Volumes/*/.Trashes/* &>/dev/null
|
||||||
|
# on main HDD
|
||||||
|
sudo rm -rfv ~/.Trash/* &>/dev/null
|
||||||
|
-
|
||||||
|
name: Clear system cache files
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
sudo rm -rfv /Library/Caches/* &>/dev/null
|
||||||
|
sudo rm -rfv /System/Library/Caches/* &>/dev/null
|
||||||
|
sudo rm -rfv ~/Library/Caches/* &>/dev/null
|
||||||
|
-
|
||||||
|
name: Clear system log files
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
sudo rm -rfv /private/var/log/asl/*.asl &>/dev/null
|
||||||
|
sudo rm -rfv /Library/Logs/DiagnosticReports/* &>/dev/null
|
||||||
|
sudo rm -rfv /Library/Logs/Adobe/* &>/dev/null
|
||||||
|
rm -rfv ~/Library/Containers/com.apple.mail/Data/Library/Logs/Mail/* &>/dev/null
|
||||||
|
rm -rfv ~/Library/Logs/CoreSimulator/* &>/dev/null
|
||||||
|
sudo rm -rfv /var/log/*
|
||||||
|
-
|
||||||
|
category: Clear browser history
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
category: Clear Google Chrome history
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Clear Google Chrome browsing history
|
||||||
|
code: |-
|
||||||
|
rm -rfv ~/Library/Application\ Support/Google/Chrome/Default/History &>/dev/null
|
||||||
|
rm -rfv ~/Library/Application\ Support/Google/Chrome/Default/History-journal &>/dev/null
|
||||||
|
-
|
||||||
|
name: Google Chrome Cache Files
|
||||||
|
code: sudo rm -rfv ~/Library/Application\ Support/Google/Chrome/Default/Application\ Cache/* &>/dev/null
|
||||||
|
-
|
||||||
|
category: Clear Safari history
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Clear Safari browsing history
|
||||||
|
code: |-
|
||||||
|
rm -f ~/Library/Safari/History.plist
|
||||||
|
rm -f ~/Library/Safari/HistoryIndex.sk
|
||||||
|
-
|
||||||
|
name: Clear Safari downloads history
|
||||||
|
code: rm -f ~/Library/Safari/Downloads.plist
|
||||||
|
-
|
||||||
|
name: Clear Safari top sites
|
||||||
|
code: rm -f ~/Library/Safari/TopSites.plist
|
||||||
|
-
|
||||||
|
name: Clear Safari last session history
|
||||||
|
code: rm -f ~/Library/Safari/LastSession.plist
|
||||||
|
-
|
||||||
|
name: Clear Safari caches
|
||||||
|
code: |-
|
||||||
|
rm -f ~/Library/Caches/com.apple.Safari/Cache.db
|
||||||
|
rm -f ~/Library/Safari/WebpageIcons.db
|
||||||
|
rm -rf ~/Library/Caches/com.apple.Safari/Webpage Previews
|
||||||
|
-
|
||||||
|
name: Clear copy of the Safari history
|
||||||
|
code: rm -rf ~/Library/Caches/Metadata/Safari/History
|
||||||
|
-
|
||||||
|
name: Clear search history embedded in Safari preferences
|
||||||
|
code: defaults write ~/Library/Preferences/com.apple.Safari RecentSearchStrings '( )'
|
||||||
|
-
|
||||||
|
name: Clear Safari cookies
|
||||||
|
code: rm -f ~/Library/Cookies/Cookies.plists
|
||||||
|
-
|
||||||
|
name: Clear Safari zoom level preferences per site
|
||||||
|
code: rm -f ~/Library/Safari/PerSiteZoomPreferences.plists
|
||||||
|
-
|
||||||
|
name: Clear URLs that are allowed to display notifications in Safari
|
||||||
|
code: rm -f ~/Library/Safari/UserNotificationPreferences.plist
|
||||||
|
-
|
||||||
|
name: Clear Safari per-site preferences for Downloads, Geolocation, PopUps, and Autoplays
|
||||||
|
code: rm -f ~/Library/Safari/PerSitePreferences.db
|
||||||
|
-
|
||||||
|
category: Clear Firefox history
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Clear Firefox cache
|
||||||
|
code: |-
|
||||||
|
sudo rm -rf ~/Library/Caches/Mozilla/
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/netpredictions.sqlite
|
||||||
|
-
|
||||||
|
name: Delete Firefox form history
|
||||||
|
code: |-
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/formhistory.sqlite
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/formhistory.dat
|
||||||
|
-
|
||||||
|
name: Delete Firefox site preferences
|
||||||
|
code: rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/content-prefs.sqlite
|
||||||
|
-
|
||||||
|
name: Delete Firefox session restore data (loads after the browser closes or crashes)
|
||||||
|
code: |-
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionCheckpoints.json
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionstore*.js*
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionstore.bak*
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionstore-backups/previous.js*
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionstore-backups/recovery.js*
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionstore-backups/recovery.bak*
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionstore-backups/previous.bak*
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/sessionstore-backups/upgrade.js*-20*
|
||||||
|
-
|
||||||
|
name: Delete Firefox passwords
|
||||||
|
docs: http://kb.mozillazine.org/Password_Manager
|
||||||
|
code: |-
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/signons.txt
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/signons2.txt
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/signons3.txt
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/signons.sqlite
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/logins.json
|
||||||
|
-
|
||||||
|
name: Delete Firefox HTML5 cookies
|
||||||
|
code: rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/webappsstore.sqlite
|
||||||
|
-
|
||||||
|
name: Delete Firefox crash reports
|
||||||
|
code: |-
|
||||||
|
rm -rfv ~/Library/Application\ Support/Firefox/Crash\ Reports/
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/minidumps/*.dmp
|
||||||
|
-
|
||||||
|
name: Delete Firefox backup files
|
||||||
|
code: |-
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/bookmarkbackups/*.json
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/bookmarkbackups/*.jsonlz4
|
||||||
|
-
|
||||||
|
name: Delete Firefox cookies
|
||||||
|
code: |-
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/cookies.txt
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/cookies.sqlite
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/cookies.sqlite-shm
|
||||||
|
rm -fv ~/Library/Application\ Support/Firefox/Profiles/*/cookies.sqlite-wal
|
||||||
|
rm -rfv ~/Library/Application\ Support/Firefox/Profiles/*/storage/default/http*
|
||||||
|
-
|
||||||
|
category: Clear third party application data
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Clear Adobe cache
|
||||||
|
recommend: standard
|
||||||
|
code: sudo rm -rfv ~/Library/Application\ Support/Adobe/Common/Media\ Cache\ Files/* &>/dev/null
|
||||||
|
-
|
||||||
|
name: Clear Gradle cache
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if [ -d "/Users/${HOST}/.gradle/caches" ]; then
|
||||||
|
rm -rfv ~/.gradle/caches/ &> /dev/null
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear Dropbox cache
|
||||||
|
recommend: standard
|
||||||
|
code: |-
|
||||||
|
if [ -d "/Users/${HOST}/Dropbox" ]; then
|
||||||
|
sudo rm -rfv ~/Dropbox/.dropbox.cache/* &>/dev/null
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear Google Drive file stream cache
|
||||||
|
recommend: standard
|
||||||
|
code: |-
|
||||||
|
killall "Google Drive File Stream"
|
||||||
|
rm -rfv ~/Library/Application\ Support/Google/DriveFS/[0-9a-zA-Z]*/content_cache &>/dev/null
|
||||||
|
-
|
||||||
|
name: Clear Composer cache
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if type "composer" &> /dev/null; then
|
||||||
|
composer clearcache &> /dev/null
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear Homebrew cache
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if type "brew" &>/dev/null; then
|
||||||
|
brew cleanup -s &>/dev/null
|
||||||
|
rm -rfv $(brew --cache) &>/dev/null
|
||||||
|
brew tap --repair &>/dev/null
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear any old versions of Ruby gems
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if type "gem" &> /dev/null; then
|
||||||
|
gem cleanup &>/dev/null
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear Docker
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if type "docker" &> /dev/null; then
|
||||||
|
docker system prune -af
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear Pyenv-VirtualEnv cache
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if [ "$PYENV_VIRTUALENV_CACHE_PATH" ]; then
|
||||||
|
rm -rfv $PYENV_VIRTUALENV_CACHE_PATH &>/dev/null
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear NPM cache
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if type "npm" &> /dev/null; then
|
||||||
|
npm cache clean --force
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear Yarn cache
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if type "yarn" &> /dev/null; then
|
||||||
|
echo 'Cleanup Yarn Cache...'
|
||||||
|
yarn cache clean --force
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
category: iOS Cleanup
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Clear iOS applications
|
||||||
|
recommend: strict
|
||||||
|
code: rm -rfv ~/Music/iTunes/iTunes\ Media/Mobile\ Applications/* &>/dev/null
|
||||||
|
-
|
||||||
|
name: Clear iOS photo caches
|
||||||
|
recommend: standard
|
||||||
|
code: rm -rf ~/Pictures/iPhoto\ Library/iPod\ Photo\ Cache/*
|
||||||
|
-
|
||||||
|
name: Remove iOS Device Backups
|
||||||
|
recommend: strict
|
||||||
|
code: rm -rfv ~/Library/Application\ Support/MobileSync/Backup/* &>/dev/null
|
||||||
|
-
|
||||||
|
name: Clear iOS Simulators
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
if type "xcrun" &>/dev/null; then
|
||||||
|
osascript -e 'tell application "com.apple.CoreSimulator.CoreSimulatorService" to quit'
|
||||||
|
osascript -e 'tell application "iOS Simulator" to quit'
|
||||||
|
osascript -e 'tell application "Simulator" to quit'
|
||||||
|
xcrun simctl shutdown all
|
||||||
|
xcrun simctl erase all
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Clear the list of iOS devices connected
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
sudo defaults delete /Users/$USER/Library/Preferences/com.apple.iPod.plist "conn:128:Last Connect"
|
||||||
|
sudo defaults delete /Users/$USER/Library/Preferences/com.apple.iPod.plist Devices
|
||||||
|
sudo defaults delete /Library/Preferences/com.apple.iPod.plist "conn:128:Last Connect"
|
||||||
|
sudo defaults delete /Library/Preferences/com.apple.iPod.plist Devices
|
||||||
|
sudo rm -rfv /var/db/lockdown/*
|
||||||
|
-
|
||||||
|
name: Clear XCode Derived Data and Archives
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
rm -rfv ~/Library/Developer/Xcode/DerivedData/* &>/dev/null
|
||||||
|
rm -rfv ~/Library/Developer/Xcode/Archives/* &>/dev/null
|
||||||
|
rm -rfv ~/Library/Developer/Xcode/iOS Device Logs/* &>/dev/null
|
||||||
|
-
|
||||||
|
name: Clear DNS cache
|
||||||
|
recommend: standard
|
||||||
|
code: |-
|
||||||
|
sudo dscacheutil -flushcache
|
||||||
|
sudo killall -HUP mDNSResponder
|
||||||
|
-
|
||||||
|
name: Purge inactive memory
|
||||||
|
recommend: standard
|
||||||
|
code: sudo purge
|
||||||
|
-
|
||||||
|
category: Reset privacy permissions for all applications
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Reset camera permissions
|
||||||
|
code: tccutil reset Camera
|
||||||
|
-
|
||||||
|
name: Reset microphone permissions
|
||||||
|
code: tccutil reset Microphone
|
||||||
|
-
|
||||||
|
name: Reset accessibility permissions
|
||||||
|
code: tccutil reset Accessibility
|
||||||
|
-
|
||||||
|
name: Reset screen capture permissions
|
||||||
|
code: tccutil reset ScreenCapture
|
||||||
|
-
|
||||||
|
name: Reset reminders permissions
|
||||||
|
code: tccutil reset Reminders
|
||||||
|
-
|
||||||
|
name: Reset photos permissions
|
||||||
|
code: tccutil reset Photos
|
||||||
|
-
|
||||||
|
name: Reset calendar permissions
|
||||||
|
code: tccutil reset Calendar
|
||||||
|
-
|
||||||
|
name: Reset full disk access permissions
|
||||||
|
code: tccutil reset SystemPolicyAllFiles
|
||||||
|
-
|
||||||
|
name: Reset contacts permissions
|
||||||
|
code: tccutil reset SystemPolicyAllFiles
|
||||||
|
-
|
||||||
|
name: Reset desktop folder permissions
|
||||||
|
code: tccutil reset SystemPolicyDesktopFolder
|
||||||
|
-
|
||||||
|
name: Reset documents folder permissions
|
||||||
|
code: tccutil reset SystemPolicyDocumentsFolder
|
||||||
|
-
|
||||||
|
name: Reset downloads permissions
|
||||||
|
code: tccutil reset SystemPolicyDownloadsFolder
|
||||||
|
-
|
||||||
|
name: Reset all app permissions
|
||||||
|
code: tccutil reset All
|
||||||
|
-
|
||||||
|
category: Configure programs
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Disable Firefox telemetry
|
||||||
|
recommend: standard
|
||||||
|
docs: https://github.com/mozilla/policy-templates/blob/master/README.md
|
||||||
|
code: |-
|
||||||
|
# Enable Firefox policies so the telemetry can be configured.
|
||||||
|
sudo defaults write /Library/Preferences/org.mozilla.firefox EnterprisePoliciesEnabled -bool TRUE
|
||||||
|
# Disable sending usage data
|
||||||
|
sudo defaults write /Library/Preferences/org.mozilla.firefox DisableTelemetry -bool TRUE
|
||||||
|
revertCode: |-
|
||||||
|
sudo defaults delete /Library/Preferences/org.mozilla.firefox EnterprisePoliciesEnabled
|
||||||
|
sudo defaults delete /Library/Preferences/org.mozilla.firefox DisableTelemetry
|
||||||
|
-
|
||||||
|
name: Disable Microsoft Office diagnostics data sending
|
||||||
|
recommend: standard
|
||||||
|
code: defaults write com.microsoft.office DiagnosticDataTypePreference -string ZeroDiagnosticData
|
||||||
|
revertCode: defaults delete com.microsoft.office DiagnosticDataTypePreference
|
||||||
|
-
|
||||||
|
name: Uninstall Google update
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
googleUpdateFile=~/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/Resources/ksinstall
|
||||||
|
if [ -f "$googleUpdateFile" ]; then
|
||||||
|
$googleUpdateFile --nuke
|
||||||
|
echo Uninstalled google update
|
||||||
|
else
|
||||||
|
echo Google update file does not exist
|
||||||
|
fi
|
||||||
|
-
|
||||||
|
name: Disable Homebrew user behavior analytics
|
||||||
|
recommend: standard
|
||||||
|
docs: https://docs.brew.sh/Analytics
|
||||||
|
call:
|
||||||
|
-
|
||||||
|
function: PersistUserEnvironmentConfiguration
|
||||||
|
parameters:
|
||||||
|
configuration: export HOMEBREW_NO_ANALYTICS=1
|
||||||
|
-
|
||||||
|
name: Disable NET Core CLI telemetry
|
||||||
|
recommend: standard
|
||||||
|
call:
|
||||||
|
-
|
||||||
|
function: PersistUserEnvironmentConfiguration
|
||||||
|
parameters:
|
||||||
|
configuration: export DOTNET_CLI_TELEMETRY_OPTOUT=1
|
||||||
|
-
|
||||||
|
name: Disable PowerShell Core telemetry
|
||||||
|
recommend: standard
|
||||||
|
docs: https://github.com/PowerShell/PowerShell/tree/release/v7.1.1#telemetry
|
||||||
|
call:
|
||||||
|
-
|
||||||
|
function: PersistUserEnvironmentConfiguration
|
||||||
|
parameters:
|
||||||
|
configuration: export POWERSHELL_TELEMETRY_OPTOUT=1
|
||||||
|
-
|
||||||
|
category: Configure OS
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
category: Configure Apple Remote Desktop
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Deactivate the Remote Management Service
|
||||||
|
recommend: strict
|
||||||
|
code: sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -stop
|
||||||
|
revertCode: sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -restart -agent -console
|
||||||
|
-
|
||||||
|
name: Remove Apple Remote Desktop Settings
|
||||||
|
recommend: strict
|
||||||
|
code: |-
|
||||||
|
sudo rm -rf /var/db/RemoteManagement
|
||||||
|
sudo defaults delete /Library/Preferences/com.apple.RemoteDesktop.plist
|
||||||
|
defaults delete ~/Library/Preferences/com.apple.RemoteDesktop.plist
|
||||||
|
sudo rm -r /Library/Application\ Support/Apple/Remote\ Desktop/
|
||||||
|
rm -r ~/Library/Application\ Support/Remote\ Desktop/
|
||||||
|
rm -r ~/Library/Containers/com.apple.RemoteDesktop
|
||||||
|
-
|
||||||
|
name: Disable Internet based spell correction
|
||||||
|
code: defaults write NSGlobalDomain WebAutomaticSpellingCorrectionEnabled -bool false
|
||||||
|
revertCode: defaults delete NSGlobalDomain WebAutomaticSpellingCorrectionEnabled
|
||||||
|
-
|
||||||
|
name: Disable Remote Apple Events
|
||||||
|
recommend: strict
|
||||||
|
code: sudo systemsetup -setremoteappleevents off
|
||||||
|
revertCode: sudo systemsetup -setremoteappleevents on
|
||||||
|
-
|
||||||
|
name: Do not store documents to iCloud Drive by default
|
||||||
|
docs: https://macos-defaults.com/finder/nsdocumentsavenewdocumentstocloud.html
|
||||||
|
recommend: standard
|
||||||
|
code: defaults write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false
|
||||||
|
revertCode: defaults delete NSGlobalDomain NSDocumentSaveNewDocumentsToCloud
|
||||||
|
-
|
||||||
|
category: Security improvements
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
category: Configure macOS Application Firewall
|
||||||
|
children:
|
||||||
|
-
|
||||||
|
name: Enable firewall
|
||||||
|
recommend: standard
|
||||||
|
docs: https://www.stigviewer.com/stig/apple_os_x_10.13/2018-10-01/finding/V-81681
|
||||||
|
code: /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
|
||||||
|
revertCode: /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate off
|
||||||
|
-
|
||||||
|
name: Turn on firewall logging
|
||||||
|
recommend: standard
|
||||||
|
docs: https://www.stigviewer.com/stig/apple_os_x_10.13/2018-10-01/finding/V-81671
|
||||||
|
code: /usr/libexec/ApplicationFirewall/socketfilterfw --setloggingmode on
|
||||||
|
revertCode: /usr/libexec/ApplicationFirewall/socketfilterfw --setloggingmode off
|
||||||
|
-
|
||||||
|
name: Turn on stealth mode
|
||||||
|
recommend: standard
|
||||||
|
docs: https://www.stigviewer.com/stig/apple_os_x_10.8_mountain_lion_workstation/2015-02-10/finding/V-51327
|
||||||
|
code: /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode on
|
||||||
|
revertCode: /usr/libexec/ApplicationFirewall/socketfilterfw --setstealthmode off
|
||||||
|
-
|
||||||
|
name: Disable Spotlight indexing
|
||||||
|
code: sudo mdutil -i off -d /
|
||||||
|
revertCode: sudo mdutil -i on /
|
||||||
|
-
|
||||||
|
name: Disable Captive portal
|
||||||
|
docs:
|
||||||
|
- https://web.archive.org/web/20171008071031if_/http://blog.erratasec.com/2010/09/apples-secret-wispr-request.html#.WdnPa5OyL6Y
|
||||||
|
- https://web.archive.org/web/20130407200745/http://www.divertednetworks.net/apple-captiveportal.html
|
||||||
|
- https://web.archive.org/web/20170622064304/https://grpugh.wordpress.com/2014/10/29/an-undocumented-change-to-captive-network-assistant-settings-in-os-x-10-10-yosemite/
|
||||||
|
code: sudo defaults write /Library/Preferences/SystemConfiguration/com.apple.captive.control.plist Active -bool false
|
||||||
|
revertCode: sudo defaults delete /Library/Preferences/SystemConfiguration/com.apple.captive.control.plist Active
|
||||||
|
-
|
||||||
|
name: Require a password to wake the computer from sleep or screen saver
|
||||||
|
code: defaults write /Library/Preferences/com.apple.screensaver askForPassword -bool true
|
||||||
|
revertCode: sudo defaults delete /Library/Preferences/com.apple.screensaver askForPassword
|
||||||
|
-
|
||||||
|
name: Do not show recent items on dock
|
||||||
|
docs: https://developer.apple.com/documentation/devicemanagement/dock
|
||||||
|
code: defaults write com.apple.dock show-recents -bool false
|
||||||
|
revertCode: defaults delete com.apple.dock show-recents
|
||||||
|
-
|
||||||
|
name: Disable AirDrop file sharing
|
||||||
|
recommend: strict
|
||||||
|
code: defaults write com.apple.NetworkBrowser DisableAirDrop -bool true
|
||||||
|
revertCode: defaults write com.apple.NetworkBrowser DisableAirDrop -bool false
|
||||||
|
functions:
|
||||||
|
-
|
||||||
|
name: PersistUserEnvironmentConfiguration
|
||||||
|
parameters: [ configuration ]
|
||||||
|
code: |-
|
||||||
|
command='{{ $configuration }}'
|
||||||
|
declare -a profile_files=("$HOME/.bash_profile" "$HOME/.zprofile")
|
||||||
|
for profile_file in "${profile_files[@]}"
|
||||||
|
do
|
||||||
|
touch "$profile_file"
|
||||||
|
if ! grep -q "$command" "${profile_file}"; then
|
||||||
|
echo "$command" >> "$profile_file"
|
||||||
|
echo "[$profile_file] Configured"
|
||||||
|
else
|
||||||
|
echo "[$profile_file] No need for any action, already configured"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
revertCode: |-
|
||||||
|
command='{{ $configuration }}'
|
||||||
|
declare -a profile_files=("$HOME/.bash_profile" "$HOME/.zprofile")
|
||||||
|
for profile_file in "${profile_files[@]}"
|
||||||
|
do
|
||||||
|
if grep -q "$command" "${profile_file}" 2>/dev/null; then
|
||||||
|
sed -i '' "/$command/d" "$profile_file"
|
||||||
|
echo "[$profile_file] Reverted configuration"
|
||||||
|
else
|
||||||
|
echo "[$profile_file] No need for any action, configuration does not exist"
|
||||||
|
fi
|
||||||
|
done
|
||||||
4418
src/application/collections/windows.yaml
Normal file
4418
src/application/collections/windows.yaml
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user