Intermediate commit:

- webpack build does not run successfully, typescript errors out, saying
  "TS2304: Cannot find name 'module'." or 'require' or 'process' in
  certain .ts files.
This commit is contained in:
Manuel Friedli 2017-03-14 15:42:11 +01:00
parent d6604351fe
commit be51aab2ee
43 changed files with 213 additions and 53 deletions

127
src/app/app.component.css Normal file
View file

@ -0,0 +1,127 @@
@font-face {
font-family: "ABeeZee";
font-stretch: normal;
font-style: normal;
font-variant: normal;
font-weight: normal;
src: local("ABeeZee Regular"),
local("ABeeZee-Regular"),
local("ABeeZee"),
url("abeezee-regular.woff") format("woff");
}
@font-face {
font-family: "Free Monospaced";
src: url("freemono.eot?") format("eot"),
url("freemono.woff") format("woff"),
url("freemono.ttf") format("truetype"),
url("freemono.svg#FreeMono") format("svg");
font-weight: normal;
font-style: normal;
}
.inputwrapper {
font-family: "ABeeZee", sans-serif;
margin: 0 1em 1em 1em;
}
.textwrapper {
margin: 0 0 1em 0;
padding: 0 1em 0 0;
}
.arrow_box {
position: relative;
background: #fff;
border: 1px solid #ddd;
}
.arrow_box:focus {
border-color: #888;
}
.arrow_box:hover {
border-color: #333;
}
.arrow_box:after, .arrow_box:before {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.arrow_box:after {
border-color: rgba(255, 255, 255, 0);
border-top-color: #fff;
border-width: 1em;
margin-left: -1em;
}
.arrow_box:before {
border-color: rgba(221, 221, 221, 0);
border-top-color: #ddd;
border-width: calc(1em + 1px);
margin-left: calc(-1em - 1px);
}
.arrow_box:focus:before {
border-color: rgba(136, 136, 136, 0);
border-top-color: #888;
}
.arrow_box:hover:before {
border-color: rgba(51, 51, 51, 0);
border-top-color: #333;
}
.selectwrapper > .arrow_box {
display: inline-block;
}
.textinput {
background-color: #fff;
border: none;
color: #000;
font-family: "Free Monospaced", monospace;
height: 10em;
margin: 0;
padding: 0.5em;
resize: vertical;
width: 100%;
}
.textinput:focus {
border-color: #888;
}
.textinput:hover {
border-color: #333;
}
.selectwrapper {
margin: 0 0 1em 0;
padding: 0;
text-align: center;
}
.select {
background-color: #fff;
border: none;
color: #000;
font-family: "ABeeZee", sans-serif;
margin: 0;
padding: 0.5em;
}
.option {
/* font-family: "ABeeZee", sans-serif;*/
}
.errormessage {
/* font-family: "ABeeZee", sans-serif;*/
}

View file

@ -0,0 +1,16 @@
<div *ngFor="let step of steps" class="inputwrapper">
<div class="textwrapper arrow_box">
<textarea class="textinput" (keyup)="update(step)" placeholder="Please enter your input ..."
[(ngModel)]="step.content">{{step.content}}</textarea>
</div>
<div class="selectwrapper">
<div class="arrow_box">
<select class="select" (change)="convert(step, $event)">
<option id="undefined">Select conversion ...</option>
<option class="option" *ngFor="let c of converters" id="{{c.getId()}}">{{c.getDisplayname()}}
</option>
</select>
</div>
</div>
<div class="errormessage" *ngIf="step.error">{{step.message}}</div>
</div>

61
src/app/app.component.ts Normal file
View file

@ -0,0 +1,61 @@
import {Component, OnInit} from "@angular/core";
import {ConverterRegistryService} from "./converterregistry.service";
import {InputComponentManagerService} from "./inputcomponentmanager.service";
import {Converter} from "./converter/converter";
import {NativeLibraryWrapperService} from "./nativelibrarywrapper.service";
import {Step} from "./step";
@Component({
moduleId: module.id,
selector: "den-app",
templateUrl: "app.component.html",
styleUrls: ["app.component.css"],
providers: [ConverterRegistryService, InputComponentManagerService, NativeLibraryWrapperService]
})
export class AppComponent extends OnInit {
public steps:Step[] = [];
public converters:Converter[] = [];
constructor(private converterRegistryService:ConverterRegistryService, private inputComponentManagerService:InputComponentManagerService) {
super();
}
convert(step:Step, $event:any):void {
step.selectedConverter = this.converterRegistryService.getConverter($event.target.selectedOptions[0].id);
this.update(step);
}
update(step:Step):void {
let converter:Converter = step.selectedConverter;
if (converter !== undefined) {
let content:string = step.content;
let result:string;
try {
result = converter.convert(content);
} catch (error) {
if (typeof console === "object" && typeof console.log === "function") {
console.log(error);
}
step.message = error.message;
step.error = true;
result = null;
}
if (result !== null) {
step.message = "";
step.error = false;
if (result !== "") {
let nextComponent:Step = this.inputComponentManagerService.getNext(step);
nextComponent.content = result;
this.update(nextComponent);
}
}
}
}
ngOnInit():void {
this.converters = this.converterRegistryService.getAllConverters();
this.steps = this.inputComponentManagerService.getAllComponents();
this.inputComponentManagerService.getFirst();
}
}

17
src/app/app.module.ts Normal file
View file

@ -0,0 +1,17 @@
import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser";
import {FormsModule} from "@angular/forms";
import {AppComponent} from "./app.component";
@NgModule({
imports: [
BrowserModule,
FormsModule
],
declarations: [
AppComponent
],
bootstrap: [AppComponent]
})
export class AppModule {
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class Base64Decoder implements Converter {
getDisplayname():string {
return "Decode Base 64";
}
getId():string {
return "base64decode";
}
convert(input:string):string {
try {
return atob(input);
} catch (exception) {
throw new Error("Could not decode base64 string. Maybe corrupt input?");
}
}
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class Base64Encoder implements Converter {
getDisplayname():string {
return "Encode Base 64";
}
getId():string {
return "base64encode";
}
convert(input:string):string {
try {
return btoa(input);
} catch (exception) {
throw new Error("Could not encode base64 string. This should not happen, so why don't you just try again?");
}
}
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class BinToDecConverter implements Converter {
getDisplayname():string {
return "Convert binary to decimal";
}
getId():string {
return "bintodec";
}
convert(input:string):string {
let n:number = parseInt(input, 2);
if (isNaN(n)) {
throw new Error("The input seems not to be a valid binary number.");
}
return n.toString(10);
}
}

View file

@ -0,0 +1,5 @@
export interface Converter {
getDisplayname():string;
getId():string;
convert(input:string):string;
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class DecToBinConverter implements Converter {
getDisplayname():string {
return "Convert decimal to binary";
}
getId():string {
return "dectobin";
}
convert(input:string):string {
let n:number = parseInt(input, 10);
if (isNaN(n)) {
throw new Error("The input seems not to be a valid integer.");
}
return n.toString(2);
}
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class DecToHexConverter implements Converter {
getDisplayname():string {
return "Convert decimal to hexadecimal";
}
getId():string {
return "dectohex";
}
convert(input:string):string {
let n:number = parseInt(input, 10);
if (isNaN(n)) {
throw new Error("The input seems not to be a valid integer.");
}
return n.toString(16);
}
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class HexToDecConverter implements Converter {
getDisplayname():string {
return "Convert hexadecimal to decimal";
}
getId():string {
return "hextodec";
}
convert(input:string):string {
let n:number = parseInt(input, 16);
if (isNaN(n)) {
throw new Error("The input seems not to be a valid hexadecimal number.")
}
return n.toString(10);
}
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class HTMLEntitiesDecoder implements Converter {
getDisplayname():string {
return "Decode HTML entities";
}
getId():string {
return "decodehtmlentities";
}
convert(input:string):string {
return input
.replace(/\&quot\;/g, "\"")
.replace(/\&gt\;/g, ">")
.replace(/\&lt\;/g, "<")
.replace(/\&amp\;/g, "&");
}
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
export class HTMLEntitiesEncoder implements Converter {
getDisplayname():string {
return "Encode HTML entities";
}
getId():string {
return "encodehtmlentities";
}
convert(input:string):string {
return input
.replace(/\&/g, "&amp;")
.replace(/\</g, "&lt;")
.replace(/\>/g, "&gt;")
.replace(/\"/g, "&quot;");
}
}

View file

@ -0,0 +1,20 @@
import {Converter} from "./converter";
import {NativeLibraryWrapperService} from "../nativelibrarywrapper.service";
export class PunycodeDecoder implements Converter {
constructor(private nativeLibraryWrapperService: NativeLibraryWrapperService) {
}
getDisplayname(): string {
return "Decode from punycode";
}
getId(): string {
return "decodepunycode";
}
convert(input: string): string {
return this.nativeLibraryWrapperService.punycode.decode(input);
}
}

View file

@ -0,0 +1,20 @@
import {Converter} from "./converter";
import {NativeLibraryWrapperService} from "../nativelibrarywrapper.service";
export class PunycodeEncoder implements Converter {
constructor(private nativeLibraryWrapperService: NativeLibraryWrapperService) {
}
getDisplayname(): string {
return "Encode as punycode";
}
getId(): string {
return "encodepunycode";
}
convert(input: string): string {
return this.nativeLibraryWrapperService.punycode.encode(input);
}
}

View file

@ -0,0 +1,23 @@
import {Converter} from "./converter";
import {NativeLibraryWrapperService} from "../nativelibrarywrapper.service";
export class QuotedPrintableDecoder implements Converter {
constructor(private nativeLibraryWrapperService:NativeLibraryWrapperService) {
}
getDisplayname():string {
return "Decode quoted printable";
}
getId():string {
return "decodequotedprintable";
}
convert(input:string):string {
try {
return this.nativeLibraryWrapperService.utf8.decode(this.nativeLibraryWrapperService.quotedPrintable.decode(input));
} catch (error) {
throw new Error("The input can not be interpreted as quoted-printable. May be corrupt?");
}
}
}

View file

@ -0,0 +1,19 @@
import {Converter} from "./converter";
import {NativeLibraryWrapperService} from "../nativelibrarywrapper.service";
export class QuotedPrintableEncoder implements Converter {
constructor(private nativeLibraryWrapperService:NativeLibraryWrapperService) {
}
getDisplayname():string {
return "Encode quoted printable";
}
getId():string {
return "encodequotedprintable";
}
convert(input:string):string {
return this.nativeLibraryWrapperService.quotedPrintable.encode(this.nativeLibraryWrapperService.utf8.encode(input));
}
}

View file

@ -0,0 +1,15 @@
import {Converter} from "./converter";
export class URIComponentDecoder implements Converter {
getDisplayname():string {
return "Decode URI component";
}
getId():string {
return "uricomponentdecode";
}
convert(input:string):string {
return decodeURIComponent(input);
}
}

View file

@ -0,0 +1,17 @@
import {Converter} from "./converter";
export class URIComponentEncoder implements Converter {
getDisplayname():string {
return "Encode URI component";
}
getId():string {
return "uricomponentencode";
}
convert(input:string):string {
return encodeURIComponent(input).replace(/[!'()*]/g, function (c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
}

View file

@ -0,0 +1,15 @@
import {Converter} from "./converter";
export class URIDecoder implements Converter {
getDisplayname():string {
return "Decode URI";
}
getId():string {
return "uridecode";
}
convert(input:string):string {
return decodeURI(input);
}
}

View file

@ -0,0 +1,15 @@
import {Converter} from "./converter";
export class URIEncoder implements Converter {
getDisplayname():string {
return "Encode URI";
}
getId():string {
return "uriencode";
}
convert(input:string):string {
return encodeURI(input).replace(/%5B/g, '[').replace(/%5D/g, ']');
}
}

View file

@ -0,0 +1,69 @@
import {Injectable} from "@angular/core";
import {Converter} from "./converter/converter";
import {Base64Encoder} from "./converter/base64encoder";
import {Base64Decoder} from "./converter/base64decoder";
import {URIEncoder} from "./converter/uriencoder";
import {URIDecoder} from "./converter/uridecoder";
import {URIComponentEncoder} from "./converter/uricomponentencoder";
import {URIComponentDecoder} from "./converter/uricomponentdecoder";
import {HTMLEntitiesEncoder} from "./converter/htmlentitiesencoder";
import {HTMLEntitiesDecoder} from "./converter/htmlentitiesdecoder";
import {DecToHexConverter} from "./converter/dectohexconverter";
import {HexToDecConverter} from "./converter/hextodecconverter";
import {DecToBinConverter} from "./converter/dectobinconverter";
import {BinToDecConverter} from "./converter/bintodecconverter";
import {QuotedPrintableDecoder} from "./converter/quotedprintabledecoder";
import {QuotedPrintableEncoder} from "./converter/quotedprintableencoder";
import {NativeLibraryWrapperService} from "./nativelibrarywrapper.service";
import {PunycodeEncoder} from "./converter/punycodeencoder";
import {PunycodeDecoder} from "./converter/punycodedecoder";
@Injectable()
export class ConverterRegistryService {
private converters:Converter[] = [];
constructor(private wrapper:NativeLibraryWrapperService) {
this.init();
}
public getAllConverters():Converter[] {
return this.converters;
}
public getConverter(id:string):Converter {
for (let i = 0; i < this.converters.length; i++) {
if (this.converters[i].getId() == id) {
return this.converters[i];
}
}
return undefined;
}
private init():void {
this.registerConverter(new Base64Encoder());
this.registerConverter(new Base64Decoder());
this.registerConverter(new URIEncoder());
this.registerConverter(new URIDecoder());
this.registerConverter(new URIComponentEncoder());
this.registerConverter(new URIComponentDecoder());
this.registerConverter(new HTMLEntitiesEncoder());
this.registerConverter(new HTMLEntitiesDecoder());
this.registerConverter(new QuotedPrintableEncoder(this.wrapper));
this.registerConverter(new QuotedPrintableDecoder(this.wrapper));
this.registerConverter(new DecToHexConverter());
this.registerConverter(new HexToDecConverter());
this.registerConverter(new DecToBinConverter());
this.registerConverter(new BinToDecConverter());
this.registerConverter(new PunycodeEncoder(this.wrapper));
this.registerConverter(new PunycodeDecoder(this.wrapper));
}
private registerConverter(converter:Converter):void {
this.converters.forEach((c:Converter) => {
if (c.getId() == converter.getId()) {
throw new Error("Converter-ID " + converter.getId() + " is already registered!");
}
});
this.converters.push(converter);
}
}

View file

@ -0,0 +1,37 @@
import {Injectable} from "@angular/core";
import {Step} from "./step";
@Injectable()
export class InputComponentManagerService {
private components:Step[] = [];
public constructor() {
}
public register(component:Step):void {
this.components.push(component);
}
public getAllComponents():Step[] {
return this.components;
}
public getNext(component:Step):Step {
let index:number = component.index;
if (index == this.components.length - 1) {
this.addComponent();
}
return this.components[index + 1];
}
public getFirst():Step {
if (this.components.length == 0) {
this.addComponent();
}
return this.components[0];
}
private addComponent():void {
this.register(new Step(this.components.length));
}
}

View file

@ -0,0 +1,18 @@
import {Injectable} from "@angular/core";
declare var utf8:any;
declare var quotedPrintable:any;
declare var punycode:any;
@Injectable()
export class NativeLibraryWrapperService {
public utf8:any;
public quotedPrintable:any;
public punycode:any;
constructor() {
this.utf8 = utf8;
this.quotedPrintable = quotedPrintable;
this.punycode = punycode;
}
}

13
src/app/step.ts Normal file
View file

@ -0,0 +1,13 @@
import {Converter} from "./converter/converter";
export class Step {
public content:string = "";
public selectedConverter:Converter = undefined;
public index:number;
public error:boolean = false;
public message:string = "";
constructor(index:number) {
this.index = index;
}
}