Refactor to Vue 3 recommended ESLint rules

These updates ensure better adherence to Vue 3 standards and improve
overall code quality and readability.

- Update ESLint configuration from Vue 2.x to Vue 3 rules.
- Switch from "essential" to strictest "recommended" ESLint ruleset.
- Adjust ESLint script to treat warnings as errors by using
  `--max-warnings=0` flag. This enforces stricter code quality controls
  provided by Vue 3 rules.
This commit is contained in:
undergroundwires
2023-11-17 13:57:13 +01:00
parent bf3426f91b
commit 4531645b4c
50 changed files with 231 additions and 166 deletions

View File

@@ -10,7 +10,7 @@ module.exports = {
}, },
extends: [ extends: [
// Vue specific rules, eslint-plugin-vue // Vue specific rules, eslint-plugin-vue
'plugin:vue/essential', 'plugin:vue/vue3-recommended',
// Extends eslint-config-airbnb // Extends eslint-config-airbnb
'@vue/eslint-config-airbnb-with-typescript', '@vue/eslint-config-airbnb-with-typescript',

2
package-lock.json generated
View File

@@ -6,7 +6,7 @@
"packages": { "packages": {
"": { "": {
"name": "privacy.sexy", "name": "privacy.sexy",
"version": "0.12.5", "version": "0.12.7",
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@floating-ui/vue": "^1.0.2", "@floating-ui/vue": "^1.0.2",

View File

@@ -24,7 +24,7 @@
"electron:preview": "electron-vite preview", "electron:preview": "electron-vite preview",
"electron:prebuild": "electron-vite build", "electron:prebuild": "electron-vite build",
"electron:build": "electron-builder", "electron:build": "electron-builder",
"lint:eslint": "eslint . --ignore-path .gitignore", "lint:eslint": "eslint . --max-warnings=0 --ignore-path .gitignore",
"lint:md": "markdownlint **/*.md --ignore node_modules", "lint:md": "markdownlint **/*.md --ignore node_modules",
"lint:md:consistency": "remark . --frail --use remark-preset-lint-consistent", "lint:md:consistency": "remark . --frail --use remark-preset-lint-consistent",
"lint:md:relative-urls": "remark . --frail --use remark-validate-links", "lint:md:relative-urls": "remark . --frail --use remark-validate-links",

View File

@@ -7,7 +7,10 @@
<TheCodeButtons class="app__row app__code-buttons" /> <TheCodeButtons class="app__row app__code-buttons" />
<TheFooter /> <TheFooter />
</div> </div>
<component v-if="devToolkitComponent" :is="devToolkitComponent" /> <component
:is="devToolkitComponent"
v-if="devToolkitComponent"
/>
</div> </div>
</template> </template>

View File

@@ -1,8 +1,8 @@
<template> <template>
<IconButton <IconButton
text="Copy" text="Copy"
@click="copyCode"
icon-name="copy" icon-name="copy"
@click="copyCode"
/> />
</template> </template>

View File

@@ -2,8 +2,8 @@
<IconButton <IconButton
v-if="canRun" v-if="canRun"
text="Run" text="Run"
@click="executeCode"
icon-name="play" icon-name="play"
@click="executeCode"
/> />
</template> </template>

View File

@@ -9,7 +9,9 @@
class="button__icon" class="button__icon"
:icon="iconName" :icon="iconName"
/> />
<div class="button__text">{{text}}</div> <div class="button__text">
{{ text }}
</div>
</button> </button>
</div> </div>
</template> </template>

View File

@@ -2,8 +2,8 @@
<div> <div>
<IconButton <IconButton
:text="isDesktopVersion ? 'Save' : 'Download'" :text="isDesktopVersion ? 'Save' : 'Download'"
@click="saveCode"
:icon-name="isDesktopVersion ? 'floppy-disk' : 'file-arrow-down'" :icon-name="isDesktopVersion ? 'floppy-disk' : 'file-arrow-down'"
@click="saveCode"
/> />
<ModalDialog v-if="instructions" v-model="areInstructionsVisible"> <ModalDialog v-if="instructions" v-model="areInstructionsVisible">
<InstructionList :data="instructions" /> <InstructionList :data="instructions" />

View File

@@ -9,7 +9,7 @@
class="copy-button" class="copy-button"
@click="copyCode" @click="copyCode"
/> />
<template v-slot:tooltip> <template #tooltip>
Copy Copy
</template> </template>
</TooltipWrapper> </TooltipWrapper>

View File

@@ -1,7 +1,7 @@
<template> <template>
<TooltipWrapper> <TooltipWrapper>
<AppIcon icon="circle-info" /> <AppIcon icon="circle-info" />
<template v-slot:tooltip> <template #tooltip>
<slot /> <slot />
</template> </template>
</TooltipWrapper> </TooltipWrapper>

View File

@@ -20,19 +20,21 @@
<p> <p>
<ol> <ol>
<li <li
v-for='(step, index) in data.steps' v-for="(step, index) in data.steps"
v-bind:key="index" :key="index"
class="step" class="step"
> >
<div class="step__action"> <div class="step__action">
<span>{{ step.action.instruction }}</span> <span>{{ step.action.instruction }}</span>
<div class="details-container" v-if="step.action.details"> <div v-if="step.action.details" class="details-container">
<!-- eslint-disable vue/no-v-html -->
<InfoTooltip><div v-html="step.action.details" /></InfoTooltip> <InfoTooltip><div v-html="step.action.details" /></InfoTooltip>
</div> </div>
</div> </div>
<div v-if="step.code" class="step__code"> <div v-if="step.code" class="step__code">
<CodeInstruction>{{ step.code.instruction }}</CodeInstruction> <CodeInstruction>{{ step.code.instruction }}</CodeInstruction>
<div class="details-container" v-if="step.code.details"> <div v-if="step.code.details" class="details-container">
<!-- eslint-disable vue/no-v-html -->
<InfoTooltip><div v-html="step.code.details" /></InfoTooltip> <InfoTooltip><div v-html="step.code.details" /></InfoTooltip>
</div> </div>
</div> </div>

View File

@@ -1,5 +1,5 @@
<template> <template>
<div class="container" v-if="hasCode"> <div v-if="hasCode" class="container">
<CodeRunButton class="code-button" /> <CodeRunButton class="code-button" />
<CodeSaveButton class="code-button" /> <CodeSaveButton class="code-button" />
<CodeCopyButton class="code-button" /> <CodeCopyButton class="code-button" />

View File

@@ -1,7 +1,8 @@
<template> <template>
<SizeObserver <SizeObserver
v-on:sizeChanged="sizeChanged()" v-non-collapsing
v-non-collapsing> @size-changed="sizeChanged()"
>
<div <div
:id="editorId" :id="editorId"
class="code-area" class="code-area"
@@ -24,18 +25,18 @@ import { NonCollapsing } from '@/presentation/components/Scripts/View/Cards/NonC
import ace from './ace-importer'; import ace from './ace-importer';
export default defineComponent({ export default defineComponent({
props: {
theme: {
type: String,
default: undefined,
},
},
components: { components: {
SizeObserver, SizeObserver,
}, },
directives: { directives: {
NonCollapsing, NonCollapsing,
}, },
props: {
theme: {
type: String,
default: undefined,
},
},
setup(props) { setup(props) {
const { onStateChange, currentState } = injectKey((keys) => keys.useCollectionState); const { onStateChange, currentState } = injectKey((keys) => keys.useCollectionState);
const { events } = injectKey((keys) => keys.useAutoUnsubscribedEvents); const { events } = injectKey((keys) => keys.useAutoUnsubscribedEvents);

View File

@@ -6,9 +6,10 @@
<hr /> <hr />
<button <button
v-for="action in devActions" v-for="action in devActions"
@click="action.handler"
:key="action.name" :key="action.name"
type="button"> type="button"
@click="action.handler"
>
{{ action.name }} {{ action.name }}
</button> </button>
</div> </div>

View File

@@ -1,6 +1,8 @@
<template> <template>
<div class="list"> <div class="list">
<div v-if="label">{{ label }}:</div> <div v-if="label">
{{ label }}:
</div>
<div class="items"> <div class="items">
<slot /> <slot />
</div> </div>

View File

@@ -5,12 +5,13 @@
such as adding content in `::before` block without making it clickable. such as adding content in `::before` block without making it clickable.
--> -->
<span <span
v-bind:class="{ v-non-collapsing
:class="{
disabled: !enabled, disabled: !enabled,
enabled: enabled, enabled: enabled,
}" }"
v-non-collapsing @click="onClicked()"
@click="onClicked()">{{label}}</span> >{{ label }}</span>
</span> </span>
</template> </template>

View File

@@ -7,7 +7,7 @@
:enabled="currentSelection !== SelectionType.None" :enabled="currentSelection !== SelectionType.None"
@click="selectType(SelectionType.None)" @click="selectType(SelectionType.None)"
/> />
<template v-slot:tooltip> <template #tooltip>
Deselect all selected scripts. Deselect all selected scripts.
<br /> <br />
💡 Good start to dive deeper into tweaks and select only what you want. 💡 Good start to dive deeper into tweaks and select only what you want.
@@ -21,7 +21,7 @@
:enabled="currentSelection !== SelectionType.Standard" :enabled="currentSelection !== SelectionType.Standard"
@click="selectType(SelectionType.Standard)" @click="selectType(SelectionType.Standard)"
/> />
<template v-slot:tooltip> <template #tooltip>
🛡 Balanced for privacy and functionality. 🛡 Balanced for privacy and functionality.
<br /> <br />
OS and applications will function normally. OS and applications will function normally.
@@ -37,7 +37,7 @@
:enabled="currentSelection !== SelectionType.Strict" :enabled="currentSelection !== SelectionType.Strict"
@click="selectType(SelectionType.Strict)" @click="selectType(SelectionType.Strict)"
/> />
<template v-slot:tooltip> <template #tooltip>
🚫 Stronger privacy, disables risky functions that may leak your data. 🚫 Stronger privacy, disables risky functions that may leak your data.
<br /> <br />
Double check to remove scripts where you would trade functionality for privacy Double check to remove scripts where you would trade functionality for privacy
@@ -53,7 +53,7 @@
:enabled="currentSelection !== SelectionType.All" :enabled="currentSelection !== SelectionType.All"
@click="selectType(SelectionType.All)" @click="selectType(SelectionType.All)"
/> />
<template v-slot:tooltip> <template #tooltip>
🔒 Strongest privacy, disabling any functionality that may leak your data. 🔒 Strongest privacy, disabling any functionality that may leak your data.
<br /> <br />
🛑 Not designed for daily users, it will break important functionalities. 🛑 Not designed for daily users, it will break important functionalities.

View File

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

View File

@@ -3,9 +3,10 @@
<TheSelector class="item" /> <TheSelector class="item" />
<TheOsChanger class="item" /> <TheOsChanger class="item" />
<TheViewChanger <TheViewChanger
v-if="!isSearching"
class="item" class="item"
v-on:viewChanged="$emit('viewChanged', $event)" @view-changed="$emit('viewChanged', $event)"
v-if="!isSearching" /> />
</div> </div>
</template> </template>
@@ -17,6 +18,7 @@ import { IEventSubscription } from '@/infrastructure/Events/IEventSource';
import TheOsChanger from './TheOsChanger.vue'; import TheOsChanger from './TheOsChanger.vue';
import TheSelector from './Selector/TheSelector.vue'; import TheSelector from './Selector/TheSelector.vue';
import TheViewChanger from './View/TheViewChanger.vue'; import TheViewChanger from './View/TheViewChanger.vue';
import { ViewType } from './View/ViewType';
export default defineComponent({ export default defineComponent({
components: { components: {
@@ -24,6 +26,11 @@ export default defineComponent({
TheOsChanger, TheOsChanger,
TheViewChanger, TheViewChanger,
}, },
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
viewChanged: (viewType: ViewType) => true,
/* eslint-enable @typescript-eslint/no-unused-vars */
},
setup() { setup() {
const { onStateChange } = injectKey((keys) => keys.useCollectionState); const { onStateChange } = injectKey((keys) => keys.useCollectionState);
const { events } = injectKey((keys) => keys.useAutoUnsubscribedEvents); const { events } = injectKey((keys) => keys.useAutoUnsubscribedEvents);

View File

@@ -1,7 +1,8 @@
<template> <template>
<MenuOptionList <MenuOptionList
label="View" label="View"
class="part"> class="part"
>
<MenuOptionListItem <MenuOptionListItem
v-for="view in viewOptions" v-for="view in viewOptions"
:key="view.type" :key="view.type"

View File

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

View File

@@ -2,7 +2,8 @@
<div <div
class="handle" class="handle"
:style="{ cursor: cursorCssValue }" :style="{ cursor: cursorCssValue }"
@mousedown="startResize"> @mousedown="startResize"
>
<div class="line" /> <div class="line" />
<AppIcon <AppIcon
class="icon" class="icon"

View File

@@ -1,17 +1,17 @@
<template> <template>
<div class="scripts"> <div class="scripts">
<TheScriptsMenu v-on:viewChanged="currentView = $event" /> <TheScriptsMenu @view-changed="currentView = $event" />
<HorizontalResizeSlider <HorizontalResizeSlider
class="row" class="row"
verticalMargin="15px" vertical-margin="15px"
firstInitialWidth="55%" first-initial-width="55%"
firstMinWidth="20%" first-min-width="20%"
secondMinWidth="20%" second-min-width="20%"
> >
<template v-slot:first> <template #first>
<TheScriptsView :currentView="currentView" /> <TheScriptsView :current-view="currentView" />
</template> </template>
<template v-slot:second> <template #second>
<TheCodeArea theme="xcode" /> <TheCodeArea theme="xcode" />
</template> </template>
</HorizontalResizeSlider> </HorizontalResizeSlider>

View File

@@ -1,5 +1,7 @@
<template> <template>
<SizeObserver v-on:widthChanged="width = $event"> <SizeObserver
@width-changed="width = $event"
>
<transition name="fade-transition"> <transition name="fade-transition">
<div v-if="width"> <div v-if="width">
<!-- <div id="responsivity-debug"> <!-- <div id="responsivity-debug">
@@ -14,21 +16,23 @@
class="cards" class="cards"
> >
<CardListItem <CardListItem
v-for="categoryId of categoryIds"
:key="categoryId"
class="card" class="card"
v-bind:class="{ :class="{
'small-screen': width <= 500, 'small-screen': width <= 500,
'medium-screen': width > 500 && width < 750, 'medium-screen': width > 500 && width < 750,
'big-screen': width >= 750, 'big-screen': width >= 750,
}" }"
v-for="categoryId of categoryIds"
:data-category="categoryId" :data-category="categoryId"
v-bind:key="categoryId" :category-id="categoryId"
:categoryId="categoryId" :active-category-id="activeCategoryId"
:activeCategoryId="activeCategoryId" @card-expansion-changed="onSelected(categoryId, $event)"
v-on:cardExpansionChanged="onSelected(categoryId, $event)"
/> />
</div> </div>
<div v-else class="error">Something went bad 😢</div> <div v-else class="error">
Something went bad 😢
</div>
</div> </div>
</transition> </transition>
</SizeObserver> </SizeObserver>

View File

@@ -1,19 +1,21 @@
<template> <template>
<div <div
ref="cardElement"
class="card" class="card"
v-on:click="isExpanded = !isExpanded" :class="{
v-bind:class="{
'is-collapsed': !isExpanded, 'is-collapsed': !isExpanded,
'is-inactive': activeCategoryId && activeCategoryId != categoryId, 'is-inactive': activeCategoryId && activeCategoryId != categoryId,
'is-expanded': isExpanded, 'is-expanded': isExpanded,
}" }"
ref="cardElement"> @click="isExpanded = !isExpanded"
>
<div class="card__inner"> <div class="card__inner">
<!-- Title --> <!-- Title -->
<span <span
v-if="cardTitle.length > 0"
class="card__inner__title" class="card__inner__title"
v-if="cardTitle && cardTitle.length > 0"> >
<span>{{cardTitle}}</span> <span>{{ cardTitle }}</span>
</span> </span>
<span v-else>Oh no 😢</span> <span v-else>Oh no 😢</span>
<!-- Expand icon --> <!-- Expand icon -->
@@ -24,17 +26,17 @@
<!-- Indeterminate and full states --> <!-- Indeterminate and full states -->
<CardSelectionIndicator <CardSelectionIndicator
class="card__inner__selection_indicator" class="card__inner__selection_indicator"
:categoryId="categoryId" :category-id="categoryId"
/> />
</div> </div>
<div class="card__expander" v-on:click.stop> <div class="card__expander" @click.stop>
<div class="card__expander__content"> <div class="card__expander__content">
<ScriptsTree :categoryId="categoryId" /> <ScriptsTree :category-id="categoryId" />
</div> </div>
<div class="card__expander__close-button"> <div class="card__expander__close-button">
<AppIcon <AppIcon
icon="xmark" icon="xmark"
v-on:click="collapse()" @click="collapse()"
/> />
</div> </div>
</div> </div>

View File

@@ -1,12 +1,12 @@
<template> <template>
<div> <div>
<AppIcon <AppIcon
icon="battery-half"
v-if="isAnyChildSelected && !areAllChildrenSelected" v-if="isAnyChildSelected && !areAllChildrenSelected"
icon="battery-half"
/> />
<AppIcon <AppIcon
icon="battery-full"
v-if="areAllChildrenSelected" v-if="areAllChildrenSelected"
icon="battery-full"
/> />
</div> </div>
</template> </template>

View File

@@ -10,13 +10,14 @@
</div> </div>
</template> </template>
</div> </div>
<div v-else> <!-- Searching --> <div v-else>
<!-- Searching -->
<div class="search"> <div class="search">
<div class="search__query"> <div class="search__query">
<div>Searching for "{{ trimmedSearchQuery }}"</div> <div>Searching for "{{ trimmedSearchQuery }}"</div>
<div <div
class="search__query__close-button" class="search__query__close-button"
v-on:click="clearSearchQuery()" @click="clearSearchQuery()"
> >
<AppIcon icon="xmark" /> <AppIcon icon="xmark" />
</div> </div>

View File

@@ -6,22 +6,26 @@
</div> </div>
<ToggleDocumentationButton <ToggleDocumentationButton
v-if="docs && docs.length > 0" v-if="docs && docs.length > 0"
v-on:show="isExpanded = true" @show="isExpanded = true"
v-on:hide="isExpanded = false" @hide="isExpanded = false"
/> />
</div> </div>
<div <div
v-if="docs && docs.length > 0 && isExpanded" v-if="docs && docs.length > 0 && isExpanded"
class="docs" class="docs"
v-bind:class="{ 'docs-expanded': isExpanded, 'docs-collapsed': !isExpanded }" :class="{
'docs-expanded': isExpanded,
'docs-collapsed': !isExpanded,
}"
> >
<DocumentationText <DocumentationText
:docs="docs" :docs="docs"
class="text" class="text"
v-bind:class="{ :class="{
expanded: isExpanded, expanded: isExpanded,
collapsed: !isExpanded, collapsed: !isExpanded,
}" /> }"
/>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -1,8 +1,9 @@
<template> <template>
<!-- eslint-disable vue/no-v-html -->
<div <div
class="documentation-text" class="documentation-text"
@click.stop
v-html="renderedText" v-html="renderedText"
v-on:click.stop
/> />
</template> </template>

View File

@@ -2,9 +2,9 @@
<a <a
class="button" class="button"
target="_blank" target="_blank"
v-bind:class="{ 'button-on': isOn }" :class="{ 'button-on': isOn }"
v-on:click.stop @click.stop
v-on:click="toggle()" @click="toggle()"
> >
<AppIcon icon="circle-info" /> <AppIcon icon="circle-info" />
</a> </a>

View File

@@ -1,11 +1,14 @@
<template> <template>
<DocumentableNode :docs="nodeMetadata.docs"> <DocumentableNode :docs="nodeMetadata.docs">
<div id="node"> <div id="node">
<div class="item text">{{ nodeMetadata.text }}</div> <div class="item text">
{{ nodeMetadata.text }}
</div>
<RevertToggle <RevertToggle
class="item"
v-if="nodeMetadata.isReversible" v-if="nodeMetadata.isReversible"
:node="nodeMetadata" /> class="item"
:node="nodeMetadata"
/>
</div> </div>
</DocumentableNode> </DocumentableNode>
</template> </template>

View File

@@ -1,7 +1,7 @@
<template> <template>
<ToggleSwitch <ToggleSwitch
v-model="isReverted" v-model="isReverted"
:stopClickPropagation="true" :stop-click-propagation="true"
:label="'revert'" :label="'revert'"
/> />
</template> </template>

View File

@@ -4,9 +4,9 @@
@click="handleClickPropagation" @click="handleClickPropagation"
> >
<input <input
v-model="isChecked"
type="checkbox" type="checkbox"
class="toggle-input" class="toggle-input"
v-model="isChecked"
> >
<div class="toggle-animation"> <div class="toggle-animation">
<span class="label-off">{{ label }}</span> <span class="label-off">{{ label }}</span>

View File

@@ -2,13 +2,13 @@
<span id="container"> <span id="container">
<span v-if="initialNodes.length"> <span v-if="initialNodes.length">
<TreeView <TreeView
:initialNodes="initialNodes" :initial-nodes="initialNodes"
:selectedLeafNodeIds="selectedScriptNodeIds" :selected-leaf-node-ids="selectedScriptNodeIds"
:latestFilterEvent="latestFilterEvent" :latest-filter-event="latestFilterEvent"
@nodeStateChanged="handleNodeChangedEvent($event)" @node-state-changed="handleNodeChangedEvent($event)"
> >
<template v-slot:node-content="{ nodeMetadata }"> <template #node-content="{ nodeMetadata }">
<NodeContent :nodeMetadata="nodeMetadata" /> <NodeContent :node-metadata="nodeMetadata" />
</template> </template>
</TreeView> </TreeView>
</span> </span>
@@ -28,16 +28,16 @@ import { TreeNodeStateChangedEmittedEvent } from './TreeView/Bindings/TreeNodeSt
import { useSelectedScriptNodeIds } from './TreeViewAdapter/UseSelectedScriptNodeIds'; import { useSelectedScriptNodeIds } from './TreeViewAdapter/UseSelectedScriptNodeIds';
export default defineComponent({ export default defineComponent({
components: {
TreeView,
NodeContent,
},
props: { props: {
categoryId: { categoryId: {
type: [Number], type: [Number],
default: undefined, default: undefined,
}, },
}, },
components: {
TreeView,
NodeContent,
},
setup(props) { setup(props) {
const useUserCollectionStateHook = injectKey((keys) => keys.useUserSelectionState); const useUserCollectionStateHook = injectKey((keys) => keys.useUserSelectionState);
const { selectedScriptNodeIds } = useSelectedScriptNodeIds(useUserCollectionStateHook); const { selectedScriptNodeIds } = useSelectedScriptNodeIds(useUserCollectionStateHook);

View File

@@ -2,10 +2,11 @@
<div class="wrapper"> <div class="wrapper">
<div <div
class="expansible-node" class="expansible-node"
@click="toggleCheck"
:style="{ :style="{
'padding-left': `${currentNode.hierarchy.depthInTree * 24}px`, 'padding-left': `${currentNode.hierarchy.depthInTree * 24}px`,
}"> }"
@click="toggleCheck"
>
<div <div
class="expand-collapse-arrow" class="expand-collapse-arrow"
:class="{ :class="{
@@ -15,10 +16,10 @@
@click.stop="toggleExpand" @click.stop="toggleExpand"
/> />
<LeafTreeNode <LeafTreeNode
:nodeId="nodeId" :node-id="nodeId"
:treeRoot="treeRoot" :tree-root="treeRoot"
> >
<template v-slot:node-content="slotProps"> <template #node-content="slotProps">
<slot name="node-content" v-bind="slotProps" /> <slot name="node-content" v-bind="slotProps" />
</template> </template>
</LeafTreeNode> </LeafTreeNode>
@@ -32,11 +33,11 @@
<HierarchicalTreeNode <HierarchicalTreeNode
v-for="id in renderedNodeIds" v-for="id in renderedNodeIds"
:key="id" :key="id"
:nodeId="id" :node-id="id"
:treeRoot="treeRoot" :tree-root="treeRoot"
:renderingStrategy="renderingStrategy" :rendering-strategy="renderingStrategy"
> >
<template v-slot:node-content="slotProps"> <template #node-content="slotProps">
<slot name="node-content" v-bind="slotProps" /> <slot name="node-content" v-bind="slotProps" />
</template> </template>
</HierarchicalTreeNode> </HierarchicalTreeNode>

View File

@@ -5,11 +5,11 @@
> >
<div <div
class="node focusable" class="node focusable"
@focus="onNodeFocus"
tabindex="-1"
:class="{ :class="{
'keyboard-focus': hasKeyboardFocus, 'keyboard-focus': hasKeyboardFocus,
}" }"
tabindex="-1"
@focus="onNodeFocus"
> >
<div <div
class="checkbox" class="checkbox"
@@ -22,7 +22,7 @@
<div class="content"> <div class="content">
<slot <slot
name="node-content" name="node-content"
:nodeMetadata="currentNode.metadata" :node-metadata="currentNode.metadata"
/> />
</div> </div>
</div> </div>

View File

@@ -5,11 +5,11 @@
<HierarchicalTreeNode <HierarchicalTreeNode
v-for="nodeId in renderedNodeIds" v-for="nodeId in renderedNodeIds"
:key="nodeId" :key="nodeId"
:nodeId="nodeId" :node-id="nodeId"
:treeRoot="treeRoot" :tree-root="treeRoot"
:renderingStrategy="renderingStrategy" :rendering-strategy="renderingStrategy"
> >
<template v-slot:node-content="slotProps"> <template #node-content="slotProps">
<slot v-bind="slotProps" /> <slot v-bind="slotProps" />
</template> </template>
</HierarchicalTreeNode> </HierarchicalTreeNode>

View File

@@ -1,10 +1,10 @@
<template> <template>
<div <div
class="tree"
ref="treeContainerElement" ref="treeContainerElement"
class="tree"
> >
<TreeRoot :treeRoot="tree" :renderingStrategy="nodeRenderingScheduler"> <TreeRoot :tree-root="tree" :rendering-strategy="nodeRenderingScheduler">
<template v-slot="slotProps"> <template #default="slotProps">
<slot name="node-content" v-bind="slotProps" /> <slot name="node-content" v-bind="slotProps" />
</template> </template>
</TreeRoot> </TreeRoot>
@@ -34,11 +34,6 @@ export default defineComponent({
components: { components: {
TreeRoot, TreeRoot,
}, },
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
nodeStateChanged: (node: TreeNodeStateChangedEmittedEvent) => true,
/* eslint-enable @typescript-eslint/no-unused-vars */
},
props: { props: {
initialNodes: { initialNodes: {
type: Array as PropType<readonly TreeInputNodeData[]>, type: Array as PropType<readonly TreeInputNodeData[]>,
@@ -53,6 +48,11 @@ export default defineComponent({
default: () => [], default: () => [],
}, },
}, },
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
nodeStateChanged: (node: TreeNodeStateChangedEmittedEvent) => true,
/* eslint-enable @typescript-eslint/no-unused-vars */
},
setup(props, { emit }) { setup(props, { emit }) {
const treeContainerElement = shallowRef<HTMLElement | undefined>(); const treeContainerElement = shallowRef<HTMLElement | undefined>();

View File

@@ -1,9 +1,11 @@
<template> <template>
<div <div
class="inline-icon" class="icon-container"
v-html="svgContent"
@click="onClicked" @click="onClicked"
/> >
<!-- eslint-disable vue/no-v-html -->
<div class="inline-icon" v-html="svgContent" />
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@@ -41,13 +43,14 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.inline-icon { .icon-container {
display: inline-block; display: inline-block;
.inline-icon {
:deep(svg) { // using :deep because when v-html is used the content doesn't go through Vue's template compiler. :deep(svg) { // using :deep because when v-html is used the content doesn't go through Vue's template compiler.
display: inline-block;
height: 1em; height: 1em;
overflow: visible; overflow: visible;
vertical-align: -0.125em; vertical-align: -0.125em;
} }
}
} }
</style> </style>

View File

@@ -4,14 +4,14 @@
class="modal-container" class="modal-container"
> >
<ModalOverlay <ModalOverlay
@transitionedOut="onOverlayTransitionedOut"
@click="onBackgroundOverlayClick"
:show="isOpen" :show="isOpen"
@transitioned-out="onOverlayTransitionedOut"
@click="onBackgroundOverlayClick"
/> />
<ModalContent <ModalContent
class="modal-content" class="modal-content"
:show="isOpen" :show="isOpen"
@transitionedOut="onContentTransitionedOut" @transitioned-out="onContentTransitionedOut"
> >
<slot /> <slot />
</ModalContent> </ModalContent>
@@ -34,11 +34,6 @@ export default defineComponent({
ModalOverlay, ModalOverlay,
ModalContent, ModalContent,
}, },
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
'update:modelValue': (isOpen: boolean) => true,
/* eslint-enable @typescript-eslint/no-unused-vars */
},
props: { props: {
modelValue: { modelValue: {
type: Boolean, type: Boolean,
@@ -49,6 +44,11 @@ export default defineComponent({
default: true, default: true,
}, },
}, },
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
'update:modelValue': (isOpen: boolean) => true,
/* eslint-enable @typescript-eslint/no-unused-vars */
},
setup(props, { emit }) { setup(props, { emit }) {
const isRendered = ref(false); const isRendered = ref(false);
const isOpen = ref(false); const isOpen = ref(false);

View File

@@ -26,17 +26,17 @@ export default defineComponent({
ModalContainer, ModalContainer,
AppIcon, AppIcon,
}, },
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
'update:modelValue': (isOpen: boolean) => true,
/* eslint-enable @typescript-eslint/no-unused-vars */
},
props: { props: {
modelValue: { modelValue: {
type: Boolean, type: Boolean,
required: true, required: true,
}, },
}, },
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
'update:modelValue': (isOpen: boolean) => true,
/* eslint-enable @typescript-eslint/no-unused-vars */
},
setup(props, { emit }) { setup(props, { emit }) {
const showDialog = computed({ const showDialog = computed({
get: () => props.modelValue, get: () => props.modelValue,

View File

@@ -5,8 +5,9 @@
It allows the tooltip content to calculate its position based on the trigger's location. It allows the tooltip content to calculate its position based on the trigger's location.
--> -->
<div <div
ref="triggeringElement"
class="tooltip__trigger" class="tooltip__trigger"
ref="triggeringElement"> >
<slot /> <slot />
</div> </div>
<div class="tooltip__overlay"> <div class="tooltip__overlay">

View File

@@ -1,17 +1,22 @@
<template> <template>
<span <span
class="container" class="container"
v-bind:class="{ :class="{
'container-unsupported': !hasCurrentOsDesktopVersion, 'container-unsupported': !hasCurrentOsDesktopVersion,
'container-supported': hasCurrentOsDesktopVersion, 'container-supported': hasCurrentOsDesktopVersion,
}"> }"
>
<span class="description"> <span class="description">
<AppIcon class="description__icon" icon="desktop" /> <AppIcon class="description__icon" icon="desktop" />
<span class="description__text">For desktop:</span> <span class="description__text">For desktop:</span>
</span> </span>
<span class="urls"> <span class="urls">
<span class="urls__url" v-for="os of supportedDesktops" v-bind:key="os"> <span
<DownloadUrlListItem :operatingSystem="os" /> v-for="os of supportedDesktops"
:key="os"
class="urls__url"
>
<DownloadUrlListItem :operating-system="os" />
</span> </span>
</span> </span>
</span> </span>

View File

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

View File

@@ -1,29 +1,39 @@
<template> <template>
<div class="privacy-policy"> <div class="privacy-policy">
<div v-if="!isDesktop" class="line"> <div v-if="!isDesktop" class="line">
<div class="line__emoji">🚫🍪</div> <div class="line__emoji">
🚫🍪
</div>
<div>No cookies!</div> <div>No cookies!</div>
</div> </div>
<div v-if="isDesktop" class="line"> <div v-if="isDesktop" class="line">
<div class="line__emoji">🚫🌐</div> <div class="line__emoji">
🚫🌐
</div>
<div> <div>
Everything is offline, except single request GitHub Everything is offline, except single request GitHub
to check for updates on application start. to check for updates on application start.
</div> </div>
</div> </div>
<div class="line"> <div class="line">
<div class="line__emoji">🚫👀</div> <div class="line__emoji">
🚫👀
</div>
<div>No user behavior / IP address collection!</div> <div>No user behavior / IP address collection!</div>
</div> </div>
<div class="line"> <div class="line">
<div class="line__emoji">🤖</div> <div class="line__emoji">
🤖
</div>
<div> <div>
All transparent: Deployed automatically from the master branch All transparent: Deployed automatically from the master branch
of the <a :href="repositoryUrl" target="_blank" rel="noopener noreferrer">source code</a> with no changes. of the <a :href="repositoryUrl" target="_blank" rel="noopener noreferrer">source code</a> with no changes.
</div> </div>
</div> </div>
<div v-if="!isDesktop" class="line"> <div v-if="!isDesktop" class="line">
<div class="line__emoji">📈</div> <div class="line__emoji">
📈
</div>
<div> <div>
Basic <a href="https://aws.amazon.com/cloudfront/reporting/" target="_blank" rel="noopener noreferrer">CDN statistics</a> Basic <a href="https://aws.amazon.com/cloudfront/reporting/" target="_blank" rel="noopener noreferrer">CDN statistics</a>
are collected by AWS but they cannot be traced to you or your behavior. are collected by AWS but they cannot be traced to you or your behavior.
@@ -31,11 +41,14 @@
</div> </div>
</div> </div>
<div class="line"> <div class="line">
<div class="line__emoji">🎉</div> <div class="line__emoji">
🎉
</div>
<div> <div>
As almost no data is collected, the application gets better As almost no data is collected, the application gets better
only with your active feedback. only with your active feedback.
Feel free to <a :href="feedbackUrl" target="_blank" rel="noopener noreferrer">create an issue</a> 😊</div> Feel free to <a :href="feedbackUrl" target="_blank" rel="noopener noreferrer">create an issue</a> 😊
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -1,7 +1,11 @@
<template> <template>
<div id="container"> <div id="container">
<h1 class="child title">{{ title }}</h1> <h1 class="child title">
<h2 class="child subtitle">{{ subtitle }}</h2> {{ title }}
</h1>
<h2 class="child subtitle">
{{ subtitle }}
</h2>
</div> </div>
</template> </template>

View File

@@ -1,10 +1,10 @@
<template> <template>
<div class="search" v-non-collapsing> <div v-non-collapsing class="search">
<input <input
v-model="searchQuery"
type="search" type="search"
class="search-term" class="search-term"
:placeholder="searchPlaceholder" :placeholder="searchPlaceholder"
v-model="searchQuery"
> >
<div class="icon-wrapper"> <div class="icon-wrapper">
<AppIcon icon="magnifying-glass" /> <AppIcon icon="magnifying-glass" />

View File

@@ -201,14 +201,6 @@ function mountToggleSwitchParent(options?: {
ToggleSwitch, ToggleSwitch,
}, },
emits: [parentClickEventName], emits: [parentClickEventName],
template: `
<div @click="handleParentClick">
<ToggleSwitch
:stopClickPropagation="stopClickPropagation"
:label="'test-label'"
/>
</div>
`,
setup(_, { emit }) { setup(_, { emit }) {
const stopClickPropagation = options?.stopClickPropagation; const stopClickPropagation = options?.stopClickPropagation;
@@ -221,6 +213,14 @@ function mountToggleSwitchParent(options?: {
stopClickPropagation, stopClickPropagation,
}; };
}, },
template: `
<div @click="handleParentClick">
<ToggleSwitch
:stopClickPropagation="stopClickPropagation"
:label="'test-label'"
/>
</div>
`,
}); });
const wrapper = mount( const wrapper = mount(
parentComponent, parentComponent,

View File

@@ -61,6 +61,7 @@ describe('AppIcon.vue', () => {
// act // act
await wrapper.trigger('click'); await wrapper.trigger('click');
await nextTick();
// assert // assert
expect(wrapper.emitted().click).to.have.lengthOf(1); expect(wrapper.emitted().click).to.have.lengthOf(1);

View File

@@ -8,7 +8,6 @@ export function createSizeObserverStub(
) { ) {
const component = defineComponent({ const component = defineComponent({
name: COMPONENT_SIZE_OBSERVER_NAME, name: COMPONENT_SIZE_OBSERVER_NAME,
template: `<div id="${COMPONENT_SIZE_OBSERVER_NAME}-stub"><slot /></div>`,
emits: { emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
widthChanged: (newWidth: number) => true, widthChanged: (newWidth: number) => true,
@@ -19,6 +18,7 @@ export function createSizeObserverStub(
emit('widthChanged', newValue); emit('widthChanged', newValue);
}); });
}, },
template: `<div id="${COMPONENT_SIZE_OBSERVER_NAME}-stub"><slot /></div>`,
}); });
return { return {
name: COMPONENT_SIZE_OBSERVER_NAME, name: COMPONENT_SIZE_OBSERVER_NAME,