Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1 code area #2

Merged
merged 14 commits into from
Oct 27, 2024
12 changes: 10 additions & 2 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@
},
"configurations": {
"production": {
"optimization": {
"scripts": true,
"styles": {
"minify": true,
"inlineCritical": false
},
"fonts": true
},
"budgets": [
{
"type": "initial",
Expand All @@ -49,7 +57,7 @@
{
"type": "anyComponentStyle",
"maximumWarning": "2kB",
"maximumError": "4kB"
"maximumError": "10kB"
}
],
"outputHashing": "all"
Expand Down Expand Up @@ -100,4 +108,4 @@
}
}
}
}
}
22 changes: 6 additions & 16 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
"express": "^4.18.2",
"prismjs": "^1.29.0",
"prism-code-editor": "^4.0.0-beta.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.10"
Expand All @@ -37,7 +37,6 @@
"@types/express": "^4.17.17",
"@types/jasmine": "~5.1.0",
"@types/node": "^18.18.0",
"@types/prismjs": "^1.26.4",
"jasmine-core": "~5.2.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
Expand Down
10 changes: 4 additions & 6 deletions src/app/code-area/code-area.component.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
@import "../../../node_modules/prismjs/themes/prism-dark.min.css";

:host.dark {
background: #333;
color: #FFF;
}
@import '../../../node_modules/prism-code-editor/dist/layout.css';
@import '../../../node_modules/prism-code-editor/dist/themes/prism.css';
@import '../../../node_modules/prism-code-editor/dist/themes/github-dark.css';
@import '../../../node_modules/prism-code-editor/dist/copy.css';
110 changes: 80 additions & 30 deletions src/app/code-area/code-area.component.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,94 @@
import { AfterViewInit, Component, ElementRef, HostListener, input, Input } from '@angular/core';
import Prism from 'prismjs';
import { debounceTime, Subject, takeLast, tap } from 'rxjs';
import {
AfterViewInit,
Component,
ElementRef,
Inject,
Input,
input,
model,
OnChanges,
PLATFORM_ID,
SimpleChanges,
ViewChild,
ViewEncapsulation,
} from "@angular/core";
import { isPlatformBrowser } from "@angular/common";
import { createEditor, PrismEditor } from "prism-code-editor";
import { matchBrackets } from "prism-code-editor/match-brackets";
import { highlightBracketPairs } from "prism-code-editor/highlight-brackets";
import { editHistory } from "prism-code-editor/commands";
import { copyButton } from "prism-code-editor/copy-button";
import "prism-code-editor/prism/languages/json";
import "prism-code-editor/prism/languages/yaml";
import "prism-code-editor/prism/languages/toml";
import "prism-code-editor/prism/languages/java";
import "prism-code-editor/prism/languages/xml";
import "prism-code-editor/prism/languages/csharp";
import "prism-code-editor/prism/languages/typescript";

@Component({
selector: 'code-area, [code-area]',
selector: 'code-area',
standalone: true,
imports: [],
template: '<ng-content></ng-content>',
styleUrl: './code-area.component.css'
template: '<div style="display: grid; {{innerStyle}}" class="{{innerClass}}" #editorContainer></div>',
styleUrl: './code-area.component.css',
encapsulation: ViewEncapsulation.ShadowDom
})
export class CodeAreaComponent implements AfterViewInit {
@Input()
code!: string;
export class CodeAreaComponent implements AfterViewInit, OnChanges {
code = model<string>("");
language = input<string>("typescript");
readonly = input<boolean, string>(false, {
transform: (value: string) => value == "true",
});
@Input() innerStyle!: string;
@Input() innerClass!: string;
editor: PrismEditor | undefined = undefined;

@Input()
language = 'javascript';
@ViewChild("editorContainer") editorContainer!: ElementRef;

constructor(private el: ElementRef) { }
isBrowser = false;
constructor(@Inject(PLATFORM_ID) private platformId: any) {
this.isBrowser = isPlatformBrowser(this.platformId);
}

ngAfterViewInit() {
this.highlight(this.code || this.el.nativeElement.innerText)
ngAfterViewInit(): void {
if (!this.isBrowser)
return;

this.inputDebouncer.pipe(
debounceTime(500),
tap(value => this.highlight(value)),
takeLast(1),
).subscribe();
if (this.editorContainer.nativeElement) {
this.editor = this.initEditor();
}
}

private inputDebouncer = new Subject<string>();

@HostListener("input")
protected onInput(){
this.inputDebouncer.next(this.el.nativeElement.innerText);

ngOnChanges(changes: SimpleChanges): void {
if (changes["code"].previousValue !== changes["code"].currentValue) {
this.editor?.setOptions({ value: changes["code"].currentValue });
}
}

private highlight(code: string){
const grammar = Prism.languages[this.language];
const html = Prism.highlight(code, grammar, this.language);
this.el.nativeElement.innerHTML = html;
console.log(code);
initEditor(): PrismEditor {
const editor = createEditor(this.editorContainer.nativeElement, {
value: this.code(),
language: this.language(),
lineNumbers: true,
wordWrap: false,
readOnly: this.readonly(),

onUpdate: (code: string) => {
this.code.set(code);
},
});
editor.addExtensions(
copyButton(),
matchBrackets(true),
highlightBracketPairs(),
editHistory(),
);

this.code.subscribe(() => {
this.editor?.update();
});

return editor;
}
}
14 changes: 7 additions & 7 deletions src/app/cs2ts/cs2ts.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@ <h2>C# to TS Converter</h2>
<div class="row">
<div class="col-md-6">
<label for="csharp-code" class="form-label">C# class fields:</label>
<code>
<textarea #csCode class="form-control" id="csharp-code" rows="16" code-area language="clike" (input)="onInput()"
[(ngModel)]="csModel" [placeholder]="placeholder1"></textarea>
</code>
<div class="code-border" >
<code-area innerStyle="min-height:500px;" [(code)]="csCode" (codeChange)="inputDebouncer.next(csCode)"
language="csharp" />
</div>
<br />
</div>
<div class="col-md-6">
<label for="ts-code" class="form-label">TS interface fields:</label>
<code>
<textarea #tsCode [@valueChangeAnim]="status" class="form-control" id="ts-code" rows="16" disabled="true" [ngModel]="tsModel" [placeholder]="placeholder2"></textarea>
</code>
<div class="code-border" [@valueChangeAnim]="status">
<code-area innerStyle="min-height:500px;" [(code)]="tsCode" language="typescript" readonly="true" />
</div>
<br />
</div>
</div>
Expand Down
40 changes: 13 additions & 27 deletions src/app/cs2ts/cs2ts.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,28 @@ import { Meta } from '@angular/platform-browser';
templateUrl: './cs2ts.component.html',
animations: [
trigger('valueChangeAnim', [
state('*', style({ "border-width": "3px" })),
transition('* <=> *', [
animate('0.1s ease-out', style({ "border-color": "var(--bs-success)" })),
animate('0.1s ease-in', style({ "border-color": "none" }))
animate('0.07s ease-out', style({ "border-color": "limegreen" })),
animate('0.07s ease-in', style({ "border-color": "var(--bs-border-color)" }))
]),
])
]
],
styles: `
.code-border{
border: 3px solid var(--bs-border-color);
}
`
})
export class Cs2tsComponent implements AfterContentInit {
@ViewChild("csCode", { read: ElementRef })
protected csCode!: ElementRef<HTMLInputElement>;
@ViewChild("tsCode", { read: ElementRef })
protected tsCode!: ElementRef<HTMLInputElement>;

protected placeholder1: string = `public class a : b {
protected csCode: string = `public class a : b {
public int x1 { get; set; }
public float? x2 { get; set; }
public string x3 { get; set; }
public bool[] x8 { get; set; }
public long[] x9 { get; set; }
public IEnumerable<string> x10 { get; set; }
}`;
protected placeholder2!: string;

protected csModel: string = "";
protected tsModel !: string;
protected tsCode !: string;
protected status: boolean = false;

protected inputDebouncer = new Subject<string>();
Expand All @@ -47,8 +43,6 @@ export class Cs2tsComponent implements AfterContentInit {
{ name: "description", content: "Converts C# model to TS model, converts fields, types, arrays and generics." },
{ name: "keywords", content: "C#, TS, CSharp, TypeScript, script, type, generic, array, converter, model, DTO, DataTransferObject, POCO, fields, string, number, int, class, code, language, long, float, boolean, bool" },
]);

this.placeholder2 = Cs2tsComponent.convert(this.placeholder1);
}

ngAfterContentInit(): void {
Expand All @@ -58,20 +52,12 @@ export class Cs2tsComponent implements AfterContentInit {
takeLast(1),
).subscribe();

this.convert(this.csModel);
}

protected onInput() {
this.inputDebouncer.next(this.csModel);
this.csCode.nativeElement.style.height = "auto";
this.csCode.nativeElement.style.height = `${this.csCode.nativeElement.scrollHeight + 5}px`;
this.tsCode.nativeElement.style.height = "auto";
this.tsCode.nativeElement.style.height = `${this.csCode.nativeElement.scrollHeight + 5}px`;
this.convert(this.csCode);
}

protected convert(csCode?: string) {
let code = csCode ? csCode : this.csModel;
this.tsModel = Cs2tsComponent.convert(code);
let code = csCode ? csCode : this.csCode;
this.tsCode = Cs2tsComponent.convert(code);
this.status = !this.status;
}

Expand Down
1 change: 1 addition & 0 deletions src/app/header/header.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
height: var(--height);
background-color: #212529b0;
backdrop-filter: blur(2px);
z-index: 2;
}

img {
Expand Down
13 changes: 12 additions & 1 deletion src/app/not-found/not-found.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { NotFoundComponent } from './not-found.component';
import { ActivatedRoute } from '@angular/router';

describe('NotFoundComponent', () => {
let component: NotFoundComponent;
let fixture: ComponentFixture<NotFoundComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NotFoundComponent]
imports: [NotFoundComponent],
providers: [
{
provide: ActivatedRoute,
useValue: {
snapshot: {
url: ["404"]
}
}
},
]
})
.compileComponents();

Expand Down
Loading