typo fixes + whitespace refactorings

This commit is contained in:
undergroundwires
2020-01-01 12:31:41 +01:00
parent 090e831909
commit e99f210c9d
22 changed files with 148 additions and 95 deletions

View File

@@ -1,8 +1,7 @@
<template> <template>
<div id="app"> <div id="app">
<div class="wrapper"> <div class="wrapper">
<TheHeader <TheHeader class="row"
class="row"
github-url="https://github.com/undergroundwires/privacy.sexy" /> github-url="https://github.com/undergroundwires/privacy.sexy" />
<!-- <TheSearchBar> </TheSearchBar> --> <!-- <TheSearchBar> </TheSearchBar> -->
<!-- <div style="display: flex; justify-content: space-between;"> --> <!-- <div style="display: flex; justify-content: space-between;"> -->

View File

@@ -28,6 +28,7 @@ export class ApplicationParser {
const app = new Application(name, version, categories); const app = new Application(name, version, categories);
return { application: app, selectedScripts }; return { application: app, selectedScripts };
} }
private static categoryIdCounter = 0; private static categoryIdCounter = 0;
private static parseCategory(category: YamlCategory, selectedScripts: Script[]): Category { private static parseCategory(category: YamlCategory, selectedScripts: Script[]): Category {
@@ -43,9 +44,12 @@ export class ApplicationParser {
} else if (ApplicationParser.isScript(categoryOrScript)) { } else if (ApplicationParser.isScript(categoryOrScript)) {
const yamlScript = categoryOrScript as YamlScript; const yamlScript = categoryOrScript as YamlScript;
const script = new Script( const script = new Script(
/* name */ yamlScript.name, /* name */
/* code */ yamlScript.code, yamlScript.name,
/* docs */ this.parseDocUrls(yamlScript)); /* code */
yamlScript.code,
/* docs */
this.parseDocUrls(yamlScript));
subScripts.push(script); subScripts.push(script);
if (yamlScript.default === true) { if (yamlScript.default === true) {
selectedScripts.push(script); selectedScripts.push(script);
@@ -56,11 +60,16 @@ export class ApplicationParser {
} }
} }
return new Category( return new Category(
/*id*/ ApplicationParser.categoryIdCounter++, /*id*/
/*name*/ category.category, ApplicationParser.categoryIdCounter++,
/*docs*/ this.parseDocUrls(category), /*name*/
/*categories*/ subCategories, category.category,
/*scripts*/ subScripts, /*docs*/
this.parseDocUrls(category),
/*categories*/
subCategories,
/*scripts*/
subScripts,
); );
} }
@@ -97,6 +106,7 @@ export class ApplicationParser {
private static isScript(categoryOrScript: any): boolean { private static isScript(categoryOrScript: any): boolean {
return categoryOrScript.code && categoryOrScript.code.length > 0; return categoryOrScript.code && categoryOrScript.code.length > 0;
} }
private static isCategory(categoryOrScript: any): boolean { private static isCategory(categoryOrScript: any): boolean {
return categoryOrScript.category && categoryOrScript.category.length > 0; return categoryOrScript.category && categoryOrScript.category.length > 0;
} }

View File

@@ -2,11 +2,13 @@ import { FunctionRenderer } from './FunctionRenderer';
export class AdminRightsFunctionRenderer { export class AdminRightsFunctionRenderer {
private readonly functionRenderer: FunctionRenderer; private readonly functionRenderer: FunctionRenderer;
constructor() { constructor() {
this.functionRenderer = new FunctionRenderer(); this.functionRenderer = new FunctionRenderer();
} }
public renderAdminRightsFunction() { public renderAdminRightsFunction() {
const name = 'Ensure admin priviliges'; const name = 'Ensure admin privileges';
const code = 'fltmc >nul 2>&1 || (\n' + const code = 'fltmc >nul 2>&1 || (\n' +
' echo This batch script requires administrator privileges. Right-click on\n' + ' echo This batch script requires administrator privileges. Right-click on\n' +
' echo the script and select "Run as administrator".\n' + ' echo the script and select "Run as administrator".\n' +

View File

@@ -2,7 +2,9 @@ import { CodeRenderer } from './CodeRenderer';
export class AsciiArtRenderer extends CodeRenderer { export class AsciiArtRenderer extends CodeRenderer {
public renderAsciiArt(version: string): string { public renderAsciiArt(version: string): string {
if (!version) { throw new Error('Version is not defined'); } if (!version) {
throw new Error('Version is not defined');
}
return ( return (
'██████╗ ██████╗ ██╗██╗ ██╗ █████╗ ██████╗██╗ ██╗███████╗███████╗██╗ ██╗██╗ ██╗\n' + '██████╗ ██████╗ ██╗██╗ ██╗ █████╗ ██████╗██╗ ██╗███████╗███████╗██╗ ██╗██╗ ██╗\n' +
'██╔══██╗██╔══██╗██║██║ ██║██╔══██╗██╔════╝╚██╗ ██╔╝██╔════╝██╔════╝╚██╗██╔╝╚██╗ ██╔╝\n' + '██╔══██╗██╔══██╗██║██║ ██║██╔══██╗██╔════╝╚██╗ ██╔╝██╔════╝██╔════╝╚██╗██╔╝╚██╗ ██╔╝\n' +
@@ -10,7 +12,7 @@ export class AsciiArtRenderer extends CodeRenderer {
'██╔═══╝ ██╔══██╗██║╚██╗ ██╔╝██╔══██║██║ ╚██╔╝ ╚════██║██╔══╝ ██╔██╗ ╚██╔╝ \n' + '██╔═══╝ ██╔══██╗██║╚██╗ ██╔╝██╔══██║██║ ╚██╔╝ ╚════██║██╔══╝ ██╔██╗ ╚██╔╝ \n' +
'██║ ██║ ██║██║ ╚████╔╝ ██║ ██║╚██████╗ ██║██╗███████║███████╗██╔╝ ██╗ ██║ \n' + '██║ ██║ ██║██║ ╚████╔╝ ██║ ██║╚██████╗ ██║██╗███████║███████╗██╔╝ ██╗ ██║ \n' +
'╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ') '╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ')
.split('\n').map((line) => this.renderComment(line)).join('\n') .split('\n').map((line) => this.renderComment(line)).join('\n') +
+ `\n${this.renderComment(`https://privacy.sexy — v${version}${new Date().toUTCString()}`)}`; `\n${this.renderComment(`https://privacy.sexy — v${version}${new Date().toUTCString()}`)}`;
} }
} }

View File

@@ -20,9 +20,9 @@ export class FunctionRenderer extends CodeRenderer {
} }
private renderFunctionName(functionName: string) { private renderFunctionName(functionName: string) {
const autoFirstHypens = '-'.repeat(Math.floor((this.totalFunctionSeparatorChars - functionName.length) / 2)); const firstHyphens = '-'.repeat(Math.floor((this.totalFunctionSeparatorChars - functionName.length) / 2));
const secondHypens = '-'.repeat(Math.ceil((this.totalFunctionSeparatorChars - functionName.length) / 2)); const secondHyphens = '-'.repeat(Math.ceil((this.totalFunctionSeparatorChars - functionName.length) / 2));
return `${this.renderComment()}${autoFirstHypens}${functionName}${secondHypens}`; return `${this.renderComment()}${firstHyphens}${functionName}${secondHyphens}`;
} }
private renderFunctionEndComment(): string { private renderFunctionEndComment(): string {

View File

@@ -16,8 +16,8 @@ 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 filteredScripts = this.application.getAllScripts().filter( const filteredScripts = this.application.getAllScripts().filter(
(script) => script.name.toLowerCase().includes(filter.toLowerCase()) (script) => script.name.toLowerCase().includes(filter.toLowerCase()) ||
|| script.code.toLowerCase().includes(filter.toLowerCase())); script.code.toLowerCase().includes(filter.toLowerCase()));
const matches: IFilterMatches = { const matches: IFilterMatches = {
scriptMatches: filteredScripts, scriptMatches: filteredScripts,

View File

@@ -18,4 +18,3 @@ export interface IApplicationState {
readonly defaultScripts: ReadonlyArray<IScript>; readonly defaultScripts: ReadonlyArray<IScript>;
getCategory(categoryId: number): ICategory | undefined; getCategory(categoryId: number): ICategory | undefined;
} }

View File

@@ -1,23 +1,28 @@
declare module 'js-yaml-loader!*' { declare module 'js-yaml-loader!*' {
type CategoryOrScript = YamlCategory | YamlScript; type CategoryOrScript = YamlCategory | YamlScript;
type DocumentationUrls = ReadonlyArray<string> | string; type DocumentationUrls = ReadonlyArray<string> | string;
export interface YamlDocumentable { export interface YamlDocumentable {
docs?: DocumentationUrls; docs?: DocumentationUrls;
} }
export interface YamlScript extends YamlDocumentable { export interface YamlScript extends YamlDocumentable {
name: string; name: string;
code: string; code: string;
default: boolean; default: boolean;
} }
export interface YamlCategory extends YamlDocumentable { export interface YamlCategory extends YamlDocumentable {
children: ReadonlyArray<CategoryOrScript>; children: ReadonlyArray<CategoryOrScript>;
category: string; category: string;
} }
interface ApplicationYaml { interface ApplicationYaml {
name: string; name: string;
version: number; version: number;
actions: ReadonlyArray<YamlCategory>; actions: ReadonlyArray<YamlCategory>;
} }
const content: ApplicationYaml; const content: ApplicationYaml;
export default content; export default content;
} }

View File

@@ -9,6 +9,7 @@ export class Application implements IApplication {
throw new Error('an application must consist of at least one category'); throw new Error('an application must consist of at least one category');
} }
} }
/** /**
* Checks all categories against duplicates, throws exception if it find any duplicates * Checks all categories against duplicates, throws exception if it find any duplicates
* @return {number} Total unique categories * @return {number} Total unique categories
@@ -17,6 +18,7 @@ export class Application implements IApplication {
private static mustNotHaveDuplicatedCategories(categories: ReadonlyArray<ICategory>): number { private static mustNotHaveDuplicatedCategories(categories: ReadonlyArray<ICategory>): number {
return Application.ensureNoDuplicateEntities(categories, Application.visitAllCategoriesOnce); return Application.ensureNoDuplicateEntities(categories, Application.visitAllCategoriesOnce);
} }
/** /**
* Checks all scripts against duplicates, throws exception if it find any scripts duplicates total scripts. * Checks all scripts against duplicates, throws exception if it find any scripts duplicates total scripts.
* @return {number} Total unique scripts * @return {number} Total unique scripts
@@ -24,6 +26,7 @@ export class Application implements IApplication {
private static mustNotHaveDuplicatedScripts(categories: ReadonlyArray<ICategory>): number { private static mustNotHaveDuplicatedScripts(categories: ReadonlyArray<ICategory>): number {
return Application.ensureNoDuplicateEntities(categories, Application.visitAllScriptsOnce); return Application.ensureNoDuplicateEntities(categories, Application.visitAllScriptsOnce);
} }
/** /**
* Checks entities against duplicates using a visit function, throws exception if it find any duplicates. * Checks entities against duplicates using a visit function, throws exception if it find any duplicates.
* @return {number} Result from the visit function * @return {number} Result from the visit function
@@ -50,25 +53,31 @@ export class Application implements IApplication {
} }
return totalVisited; return totalVisited;
} }
// Runs handler on each category and returns sum of total visited categories // Runs handler on each category and returns sum of total visited categories
private static visitAllCategoriesOnce( private static visitAllCategoriesOnce(
categories: ReadonlyArray<ICategory>, handler: (category: ICategory) => any): number { categories: ReadonlyArray<ICategory>,
handler: (category: ICategory) => any): number {
let total = 0; let total = 0;
for (const category of categories) { for (const category of categories) {
handler(category); handler(category);
total++; total++;
if (category.subCategories && category.subCategories.length > 0) { if (category.subCategories && category.subCategories.length > 0) {
total += Application.visitAllCategoriesOnce( total += Application.visitAllCategoriesOnce(
category.subCategories as ReadonlyArray<ICategory>, handler); category.subCategories as ReadonlyArray<ICategory>,
handler);
} }
} }
return total; return total;
} }
// Runs handler on each script and returns sum of total visited scripts // Runs handler on each script and returns sum of total visited scripts
private static visitAllScriptsOnce( private static visitAllScriptsOnce(
categories: ReadonlyArray<ICategory>, handler: (script: IScript) => any): number { categories: ReadonlyArray<ICategory>,
handler: (script: IScript) => any): number {
let total = 0; let total = 0;
Application.visitAllCategoriesOnce(categories, (category) => { Application.visitAllCategoriesOnce(categories,
(category) => {
if (category.scripts) { if (category.scripts) {
for (const script of category.scripts) { for (const script of category.scripts) {
handler(script); handler(script);
@@ -78,6 +87,7 @@ export class Application implements IApplication {
}); });
return total; return total;
} }
public readonly totalScripts: number; public readonly totalScripts: number;
public readonly totalCategories: number; public readonly totalCategories: number;
@@ -92,25 +102,30 @@ export class Application implements IApplication {
public findCategory(categoryId: number): ICategory | undefined { public findCategory(categoryId: number): ICategory | undefined {
let result: ICategory | undefined; let result: ICategory | undefined;
Application.visitAllCategoriesOnce(this.categories, (category) => { Application.visitAllCategoriesOnce(this.categories,
(category) => {
if (category.id === categoryId) { if (category.id === categoryId) {
result = category; result = category;
} }
}); });
return result; return result;
} }
public findScript(scriptId: string): IScript | undefined { public findScript(scriptId: string): IScript | undefined {
let result: IScript | undefined; let result: IScript | undefined;
Application.visitAllScriptsOnce(this.categories, (script) => { Application.visitAllScriptsOnce(this.categories,
(script) => {
if (script.id === scriptId) { if (script.id === scriptId) {
result = script; result = script;
} }
}); });
return result; return result;
} }
public getAllScripts(): IScript[] { public getAllScripts(): IScript[] {
const result = new Array<IScript>(); const result = new Array<IScript>();
Application.visitAllScriptsOnce(this.categories, (script) => { Application.visitAllScriptsOnce(this.categories,
(script) => {
result.push(script); result.push(script);
}); });
return result; return result;

View File

@@ -7,8 +7,8 @@ export class Category extends BaseEntity<number> implements ICategory {
if (!category.name) { if (!category.name) {
throw new Error('name is null or empty'); throw new Error('name is null or empty');
} }
if ((!category.subCategories || category.subCategories.length === 0) if ((!category.subCategories || category.subCategories.length === 0) &&
&& (!category.scripts || category.scripts.length === 0)) { (!category.scripts || category.scripts.length === 0)) {
throw new Error('A category must have at least one sub-category or scripts'); throw new Error('A category must have at least one sub-category or scripts');
} }
} }

9
src/global.d.ts vendored
View File

@@ -1,9 +1,9 @@
// Two ways of typing other libraries: https://stackoverflow.com/a/53070501 // Two ways of typing other libraries: https://stackoverflow.com/a/53070501
declare module 'liquor-tree' { declare module 'liquor-tree' {
import { PluginObject } from 'vue'; import { PluginObject } from 'vue';
import { VueClass } from 'vue-class-component/lib/declarations'; import { VueClass } from 'vue-class-component/lib/declarations';
// https://github.com/amsik/liquor-tree/blob/master/src/lib/Tree.js // https://github.com/amsik/liquor-tree/blob/master/src/lib/Tree.js
export interface ILiquorTree { export interface ILiquorTree {
readonly model: ReadonlyArray<ILiquorTreeExistingNode>; readonly model: ReadonlyArray<ILiquorTreeExistingNode>;
@@ -14,6 +14,7 @@ declare module 'liquor-tree' {
interface ICustomLiquorTreeData { interface ICustomLiquorTreeData {
documentationUrls: ReadonlyArray<string>; documentationUrls: ReadonlyArray<string>;
} }
/** /**
* Returned from Node tree view events. * Returned from Node tree view events.
* See constructor in https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js * See constructor in https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js
@@ -24,6 +25,7 @@ declare module 'liquor-tree' {
states: ILiquorTreeNodeState | undefined; states: ILiquorTreeNodeState | undefined;
children: ReadonlyArray<ILiquorTreeExistingNode> | undefined; children: ReadonlyArray<ILiquorTreeExistingNode> | undefined;
} }
/** /**
* Sent to liquor tree to define of new nodes. * Sent to liquor tree to define of new nodes.
* https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js * https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js
@@ -35,13 +37,16 @@ declare module 'liquor-tree' {
children: ReadonlyArray<ILiquorTreeNewNode> | undefined; children: ReadonlyArray<ILiquorTreeNewNode> | undefined;
data: ICustomLiquorTreeData; data: ICustomLiquorTreeData;
} }
// https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js // https://github.com/amsik/liquor-tree/blob/master/src/lib/Node.js
interface ILiquorTreeNodeState { interface ILiquorTreeNodeState {
checked: boolean; checked: boolean;
} }
interface ILiquorTreeNodeData extends ICustomLiquorTreeData { interface ILiquorTreeNodeData extends ICustomLiquorTreeData {
text: string; text: string;
} }
// https://github.com/amsik/liquor-tree/blob/master/src/components/TreeRoot.vue // https://github.com/amsik/liquor-tree/blob/master/src/components/TreeRoot.vue
interface ILiquorTreeOptions { interface ILiquorTreeOptions {
checkbox: boolean; checkbox: boolean;
@@ -49,11 +54,13 @@ declare module 'liquor-tree' {
filter: ILiquorTreeFilter; filter: ILiquorTreeFilter;
deletion(node: ILiquorTreeNewNode): boolean; deletion(node: ILiquorTreeNewNode): boolean;
} }
// https://github.com/amsik/liquor-tree/blob/master/src/components/TreeRoot.vue // https://github.com/amsik/liquor-tree/blob/master/src/components/TreeRoot.vue
interface ILiquorTreeFilter { interface ILiquorTreeFilter {
emptyText: string; emptyText: string;
matcher(query: string, node: ILiquorTreeNewNode): boolean; matcher(query: string, node: ILiquorTreeNewNode): boolean;
} }
const LiquorTree: PluginObject<any> & VueClass<any>; const LiquorTree: PluginObject<any> & VueClass<any>;
export default LiquorTree; export default LiquorTree;
} }

View File

@@ -1,14 +1,13 @@
import { IEntity } from './IEntity'; import { IEntity } from './IEntity';
export abstract class BaseEntity<TId> implements IEntity<TId> { export abstract class BaseEntity<TId> implements IEntity<TId> {
constructor(public id: TId) { protected constructor(public id: TId) {
if (typeof id !== 'number' && !id) { if (typeof id !== 'number' && !id) {
throw new Error('Id cannot be null or empty'); throw new Error('Id cannot be null or empty');
} }
} }
public equals(otherId: TId): boolean { public equals(otherId: TId): boolean {
return this.id === otherId; return this.id === otherId;
} }
} }

View File

@@ -3,6 +3,7 @@ import { IRepository } from './IRepository';
export class InMemoryRepository<TKey, TEntity extends IEntity<TKey>> implements IRepository<TKey, TEntity> { export class InMemoryRepository<TKey, TEntity extends IEntity<TKey>> implements IRepository<TKey, TEntity> {
private readonly items: TEntity[]; private readonly items: TEntity[];
constructor(items?: TEntity[]) { constructor(items?: TEntity[]) {
this.items = items || new Array<TEntity>(); this.items = items || new Array<TEntity>();
} }

View File

@@ -10,7 +10,7 @@ export class SaveFileDialog {
const blob = new Blob([file], { type: fileType }); const blob = new Blob([file], { type: fileType });
fileSaver.saveAs(blob, fileName); fileSaver.saveAs(blob, fileName);
} catch (e) { } catch (e) {
window.open('data:' + fileType + ',' + encodeURIComponent(file.toString()), '_blank', ''); window.open(`data:${fileType},${encodeURIComponent(file.toString())}`, '_blank', '');
} }
} }
} }

View File

@@ -11,8 +11,15 @@ import { faTimes, faFileDownload, faCopy, faSearch, faInfoCircle } from '@fortaw
export class IconBootstrapper implements IVueBootstrapper { export class IconBootstrapper implements IVueBootstrapper {
public bootstrap(vue: VueConstructor): void { public bootstrap(vue: VueConstructor): void {
library.add(faGithub, faFolderOpen, faFolder, library.add(
faTimes, faFileDownload, faCopy, faSearch, faInfoCircle); faGithub,
faFolderOpen,
faFolder,
faTimes,
faFileDownload,
faCopy,
faSearch,
faInfoCircle);
vue.component('font-awesome-icon', FontAwesomeIcon); vue.component('font-awesome-icon', FontAwesomeIcon);
} }
} }

View File

@@ -1,4 +1,6 @@
// based on https://github.com/Akryum/v-tooltip/blob/83615e394c96ca491a4df04b892ae87e833beb97/demo-src/src/App.vue#L179-L303 // based on https://github.com/Akryum/v-tooltip/blob/83615e394c96ca491a4df04b892ae87e833beb97/demo-src/src/App.vue#L179-L303
@import "@/presentation/styles/colors.scss";
.tooltip { .tooltip {
display: block !important; display: block !important;
z-index: 10000; z-index: 10000;

View File

@@ -1,4 +1,5 @@
// Overrides base styling for LiquorTree // Overrides base styling for LiquorTree
@import "@/presentation/styles/colors.scss";
.tree-node > .tree-content > .tree-anchor > span { .tree-node > .tree-content > .tree-anchor > span {
color: $white !important; color: $white !important;

8
src/shims-tsx.d.ts vendored
View File

@@ -3,9 +3,13 @@ import Vue, { VNode } from 'vue';
declare global { declare global {
namespace JSX { namespace JSX {
// tslint:disable no-empty-interface // tslint:disable no-empty-interface
interface Element extends VNode {} interface Element extends VNode {
}
// tslint:disable no-empty-interface // tslint:disable no-empty-interface
interface ElementClass extends Vue {} interface ElementClass extends Vue {
}
interface IntrinsicElements { interface IntrinsicElements {
[elem: string]: any; [elem: string]: any;
} }