Compare commits

...

11 Commits

42 changed files with 999 additions and 258 deletions

View File

@@ -34,7 +34,7 @@
}, },
{ {
"glob":"**/*", "glob":"**/*",
"input":"node_modules/ace-builds/src-noconflict", "input":"node_modules/ace-builds/src-min-noconflict",
"output":"ace" "output":"ace"
} }
], ],
@@ -44,9 +44,11 @@
"node_modules/bootstrap/scss/bootstrap.scss", "node_modules/bootstrap/scss/bootstrap.scss",
"node_modules/bootstrap-icons/font/bootstrap-icons.css", "node_modules/bootstrap-icons/font/bootstrap-icons.css",
"src/assets/css/styles.css", "src/assets/css/styles.css",
"src/assets/css/overrides.css"
"src/assets/css/ace-overrides.css" "src/assets/css/ace-overrides.css"
], ],
"scripts":[ "scripts":[
"src/libs/showdown.min.js"
], ],
"optimization": true "optimization": true
}, },
@@ -64,7 +66,7 @@
"maximumError":"8kB" "maximumError":"8kB"
} }
], ],
"optimization":false "optimization": true
}, },
"development":{ "development":{
"outputHashing": "all", "outputHashing": "all",
@@ -110,7 +112,6 @@
"src/styles.css" "src/styles.css"
], ],
"scripts":[ "scripts":[
] ]
} }
} }

View File

@@ -100,6 +100,26 @@ const saveFileAs = () => {
}); });
} }
const chooseFolder = () => {
return dialog.showOpenDialog(
{
title: "Choose Folder:",
defaultPath: HOME_DIR,
properties: [
'openDirectory'
]
}
).then((response) => {
if (response.canceled) {
console.debug("Canceled folder selection...");
return "";
}
console.log(response)
return response.filePaths[0];
});
}
const openFiles = (startPath) => { const openFiles = (startPath) => {
dialog.showOpenDialog( dialog.showOpenDialog(
{ {
@@ -171,6 +191,7 @@ const closeFile = (fpath) => {
module.exports = { module.exports = {
newtonFs: { newtonFs: {
setWindow: setWindow, setWindow: setWindow,
chooseFolder: chooseFolder,
openFiles: openFiles, openFiles: openFiles,
saveFile: saveFile, saveFile: saveFile,
saveFileAs: saveFileAs, saveFileAs: saveFileAs,

View File

@@ -72,7 +72,8 @@ const loadHandlers = () => {
ipcMain.handle('openFiles', (eve, startPath) => newton.fs.openFiles(startPath)); ipcMain.handle('openFiles', (eve, startPath) => newton.fs.openFiles(startPath));
ipcMain.handle('saveFile', (eve, path, content) => newton.fs.saveFile(path, content)); ipcMain.handle('saveFile', (eve, path, content) => newton.fs.saveFile(path, content));
ipcMain.handle('closeFile', (eve, path) => newton.fs.closeFile(path)); ipcMain.handle('closeFile', (eve, path) => newton.fs.closeFile(path));
ipcMain.handle('saveFileAs', (eve, content) => newton.fs.saveFileAs(content)); ipcMain.handle('saveFileAs', (eve) => newton.fs.saveFileAs());
ipcMain.handle('chooseFolder', (eve) => newton.fs.chooseFolder());
} }
app.whenReady().then(async () => { app.whenReady().then(async () => {

View File

@@ -19,6 +19,7 @@ contextBridge.exposeInMainWorld('fs', {
openFiles: (startPath) => ipcRenderer.invoke("openFiles", startPath), openFiles: (startPath) => ipcRenderer.invoke("openFiles", startPath),
saveFile: (path, content) => ipcRenderer.invoke("saveFile", path, content), saveFile: (path, content) => ipcRenderer.invoke("saveFile", path, content),
saveFileAs: () => ipcRenderer.invoke("saveFileAs"), saveFileAs: () => ipcRenderer.invoke("saveFileAs"),
chooseFolder: () => ipcRenderer.invoke("chooseFolder"),
closeFile: (path) => ipcRenderer.invoke("closeFile", path), closeFile: (path) => ipcRenderer.invoke("closeFile", path),
getPathForFile: (file) => webUtils.getPathForFile(file), getPathForFile: (file) => webUtils.getPathForFile(file),
onLoadFiles: (callback) => ipcRenderer.on('load-files', (_event, paths) => callback(paths)), onLoadFiles: (callback) => ipcRenderer.on('load-files', (_event, paths) => callback(paths)),

View File

@@ -4,6 +4,8 @@
"version": "0.0.1", "version": "0.0.1",
"author": "ITDominator", "author": "ITDominator",
"license": "GPL-2.0-only", "license": "GPL-2.0-only",
"homepage": "https://www.itdominator.com",
"email": "1itdominator@gmail.com",
"main": "newton/main.js", "main": "newton/main.js",
"private": true, "private": true,
"scripts": { "scripts": {
@@ -11,6 +13,7 @@
"electron-start": "electron . --trace-warnings --start-as=build", "electron-start": "electron . --trace-warnings --start-as=build",
"electron-pack": "ng build --base-href ./ && electron-builder --dir", "electron-pack": "ng build --base-href ./ && electron-builder --dir",
"electron-dist": "ng build --base-href ./ && electron-builder", "electron-dist": "ng build --base-href ./ && electron-builder",
"electron-dist-linux": "ng build --base-href ./ && electron-builder --linux deb zip AppImage",
"electron-dist-all": "ng build --base-href ./ && electron-builder -mwl", "electron-dist-all": "ng build --base-href ./ && electron-builder -mwl",
"electron-concurrently": "concurrently 'ng serve' 'electron . --trace-warnings --start-as=ng-serve'", "electron-concurrently": "concurrently 'ng serve' 'electron . --trace-warnings --start-as=ng-serve'",
"ng-serve": "ng serve", "ng-serve": "ng serve",
@@ -24,7 +27,10 @@
"icon": "./icos/", "icon": "./icos/",
"files": [ "files": [
"newton/", "newton/",
"build/" "build/",
"!node_modules/ace-builds/",
"!node_modules/web-streams-polyfill/",
"!node_modules/@angular/"
], ],
"mac": { "mac": {
"category": "public.app-category.developer-tools" "category": "public.app-category.developer-tools"
@@ -33,8 +39,9 @@
"target": "portable" "target": "portable"
}, },
"linux": { "linux": {
"target": "AppImage", "target": "zip",
"category": "Development" "category": "Development",
"maintainer": "ITDominator"
} }
}, },
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps",

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
public/imgs/whole-word.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -2,6 +2,8 @@
<info-bar></info-bar> <info-bar></info-bar>
<tabs></tabs> <tabs></tabs>
<editors></editors> <editors></editors>
<search-replace></search-replace>
<markdown-preview></markdown-preview>
<files-modal></files-modal> <lsp-manager></lsp-manager>
</div> </div>

View File

@@ -3,7 +3,9 @@ import { Component } from '@angular/core';
import { InfoBarComponent } from './editor/info-bar/info-bar.component'; import { InfoBarComponent } from './editor/info-bar/info-bar.component';
import { TabsComponent } from './editor/tabs/tabs.component'; import { TabsComponent } from './editor/tabs/tabs.component';
import { EditorsComponent } from './editor/editors.component'; import { EditorsComponent } from './editor/editors.component';
import { FilesModalComponent } from "./common/components/modals/files/files-modal.component"; import { SearchReplaceComponent } from "./editor/search-replace/search-replace.component";
import { MarkdownPreviewComponent } from "./editor/markdown-preview/markdown-preview.component";
import { LspManagerComponent } from "./editor/lsp-manager/lsp-manager.component";
@@ -13,7 +15,9 @@ import { FilesModalComponent } from "./common/components/modals/files/files-moda
InfoBarComponent, InfoBarComponent,
TabsComponent, TabsComponent,
EditorsComponent, EditorsComponent,
FilesModalComponent SearchReplaceComponent,
MarkdownPreviewComponent,
LspManagerComponent,
], ],
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrl: './app.component.css', styleUrl: './app.component.css',

View File

@@ -1,16 +0,0 @@
.modal-column {
min-height: 24em;
max-height: 24em;
overflow: auto;
}
.close-button {
background: rgba(116, 0, 0, 0.64);
border-style: solid;
border-color: rgba(0, 0, 0, 0.64);
border-width: 1px;
}
.close-button:hover {
background: rgba(256, 0, 0, 0.64);
}

View File

@@ -1,52 +0,0 @@
<div #filesModal
id="filesModal" class="modal fade" tabindex="-1" role="dialog"
>
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Files:</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col">
<div class="row">
<div class="col modal-column">
<div #filesList *ngFor="let file of files" class="row">
<div class="col-11 title"
title="{{file.path}}"
uuid="{{file.uuid}}"
path="{{file.path}}"
>
{{file.title}}
</div>
<div class="col-1 close-button">
X
</div>
</div>
</div>
</div>
<div class="row">
<input #filesSearch type="text" placeholder="Search..." />
</div>
</div>
<div class="col modal-column">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -1,85 +0,0 @@
import { Component, inject } from "@angular/core";
import { CommonModule } from "@angular/common";
import { Subject, takeUntil } from 'rxjs';
import * as bootstrap from "bootstrap";
import { FilesModalService } from "../../../services/editor/modals/files-modal.service";
import { TabsService } from '../../../services/editor/tabs/tabs.service';
import { ServiceMessage } from '../../../types/service-message.type';
@Component({
selector: 'files-modal',
standalone: true,
imports: [
CommonModule
],
templateUrl: './files-modal.component.html',
styleUrl: './files-modal.component.css',
host: {
'class': ''
}
})
export class FilesModalComponent {
private unsubscribe: Subject<void> = new Subject();
private filesModalService: FilesModalService = inject(FilesModalService);
private tabsService: TabsService = inject(TabsService);
filesModal!: bootstrap.Modal;
files: any[] = [];
constructor() {
}
private ngAfterViewInit(): void {
this.loadSubscribers();
}
private loadSubscribers() {
this.tabsService.getMessage$().pipe(
takeUntil(this.unsubscribe)
).subscribe((data: ServiceMessage) => {
if (data.action === "create-tab") {
this.createFileRow(data.fileName, data.fileUUID, data.filePath);
}
});
this.filesModalService.showFilesModalRequested$().pipe(
takeUntil(this.unsubscribe)
).subscribe(() => {
if (!this.filesModal) {
this.createModal();
}
this.showModal();
});
this.filesModalService.addFileToModalRequested$().pipe(
takeUntil(this.unsubscribe)
).subscribe((uuid: string) => {
if (!this.filesModal) {
this.createModal();
}
});
}
private createModal() {
this.filesModal = new bootstrap.Modal("#filesModal", {});
}
public createFileRow(title: string, uuid: string, path: string): void {
this.files.push({title: title, uuid: uuid, path: path})
}
public showModal() {
this.filesModal?.toggle();
}
}

View File

@@ -15,23 +15,23 @@ export const Keybindings: Array<{}> = [
name: "openCommandPalette2", name: "openCommandPalette2",
bindKey: {linux: "command-shift-/|F1", win: "ctrl-shift-/|F1"}, bindKey: {linux: "command-shift-/|F1", win: "ctrl-shift-/|F1"},
readOnly: false readOnly: false
}, {
name: "showFilesModal",
bindKey: {win: "ctrl-shift-b", mac: "ctrl-shift-b"},
service: "filesModalService",
readOnly: false
}, { }, {
name: "showFilesList", name: "showFilesList",
bindKey: {win: "ctrl-b", mac: "ctrl-b"}, bindKey: {win: "ctrl-b", mac: "ctrl-b"},
readOnly: false readOnly: false
}, { }, {
name: "showLSPModal", name: "lspManagerPopup",
bindKey: {win: "ctrl-shift-l", mac: "ctrl-shift-l"}, bindKey: {win: "ctrl-shift-l", mac: "ctrl-shift-l"},
service: "",
readOnly: false
}, {
name: "markdownPreviewPopup",
bindKey: {win: "ctrl-shift-m", mac: "ctrl-shift-m"},
readOnly: false readOnly: false
}, { }, {
name: "searchPopup", name: "searchPopup",
bindKey: {win: "ctrl-f", mac: "ctrl-f"}, bindKey: {win: "ctrl-f", mac: "ctrl-f"},
readOnly: true readOnly: false
}, { }, {
name: "replacePopup", name: "replacePopup",
bindKey: {win: "ctrl-r", mac: "ctrl-r"}, bindKey: {win: "ctrl-r", mac: "ctrl-r"},

View File

@@ -7,6 +7,7 @@ import { ServiceMessage } from '../../types/service-message.type';
import { EditorSettings } from "../../configs/editor.config"; import { EditorSettings } from "../../configs/editor.config";
import { NewtonFile } from '../../types/file.type'; import { NewtonFile } from '../../types/file.type';
import { EditorType } from '../../types/editor.type';
@@ -38,7 +39,7 @@ export class EditorsService {
} }
public set(uuid: string, component: CodeViewComponent) { public set(uuid: string, component: CodeViewComponent) {
if (component.isMiniMap) { if (component.mode == EditorType.MiniMap) {
this.miniMapView = component; this.miniMapView = component;
return; return;
} }

View File

@@ -1,26 +1,30 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { BehaviorSubject, ReplaySubject, Observable } from 'rxjs'; import { ReplaySubject, Observable } from 'rxjs';
import { AceLanguageClient, LanguageClientConfig } from 'ace-linters/build/ace-language-client'; import { AceLanguageClient, LanguageClientConfig } from 'ace-linters/build/ace-language-client';
import { LanguageProvider } from "ace-linters"; import { LanguageProvider } from "ace-linters";
import { ServiceMessage } from '../../../types/service-message.type';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class LSPService { export class LspManagerService {
private messageSubject: ReplaySubject<ServiceMessage> = new ReplaySubject<ServiceMessage>(1);
lspConfigData!: {}; lspConfigData!: {};
languageProviders: {} = {}; languageProviders: {} = {};
workspaceFolder: string = "";
constructor() { constructor() {
this.loadLSPService();
} }
private loadLSPService() { public loadLspConfigData(): Promise<string | void> {
this.getLspConfigData().then((lspConfigData: string) => { return this.getLspConfigData().then((lspConfigData: string) => {
this.lspConfigData = JSON.parse(lspConfigData); this.lspConfigData = JSON.parse(lspConfigData);
if (this.lspConfigData["message"]) { if (this.lspConfigData["message"]) {
@@ -31,11 +35,13 @@ export class LSPService {
this.lspConfigData = {}; this.lspConfigData = {};
} }
return lspConfigData;
}); });
} }
public registerEditor(editor: any): void { public registerEditor(editor: any): void {
let modeParts = editor.getSession()["$modeId"].split("/"); let modeParts = editor.session.getMode()["$Id"].split("/");
let mode = modeParts[ modeParts.length - 1 ]; let mode = modeParts[ modeParts.length - 1 ];
if ( !this.languageProviders[mode] ) { if ( !this.languageProviders[mode] ) {
@@ -75,14 +81,26 @@ export class LSPService {
return LanguageProvider.create(worker); return LanguageProvider.create(worker);
} }
protected setSessionFilePath(session: any, mode: string = "", filePath: string = "") => { protected setSessionFilePath(session: any, filePath: string = "") {
if ( !session || !mode || !filePath || !this.languageProviders[mode] ) return; if ( !session || !filePath ) return;
let mode = session.getMode()["$Id"];
if ( !this.languageProviders[mode] ) return;
this.languageProviders[mode].setSessionFilePath(session, filePath); this.languageProviders[mode].setSessionFilePath(session, filePath);
} }
protected closeDocument(session: any, mode: string) => { protected closeDocument(session: any) {
if ( !session || !mode || !this.languageProviders[mode] ) return; if ( !session ) return;
let mode = session.getMode()["$Id"];
if ( !this.languageProviders[mode] ) return;
this.languageProviders[mode].closeDocument(session); this.languageProviders[mode].closeDocument(session);
} }
public sendMessage(data: ServiceMessage): void {
this.messageSubject.next(data);
}
public getMessage$(): Observable<ServiceMessage> {
return this.messageSubject.asObservable();
}
} }

View File

@@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';
import { ReplaySubject, Observable } from 'rxjs';
import { ServiceMessage } from '../../../types/service-message.type';
@Injectable({
providedIn: 'root'
})
export class MarkdownPreviewService {
private messageSubject: ReplaySubject<ServiceMessage> = new ReplaySubject<ServiceMessage>(1);
constructor() {
}
public sendMessage(data: ServiceMessage): void {
this.messageSubject.next(data);
}
public getMessage$(): Observable<ServiceMessage> {
return this.messageSubject.asObservable();
}
}

View File

@@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';
import { ReplaySubject, Observable } from 'rxjs';
import { ServiceMessage } from '../../../types/service-message.type';
@Injectable({
providedIn: 'root'
})
export class SearchReplaceService {
private messageSubject: ReplaySubject<ServiceMessage> = new ReplaySubject<ServiceMessage>(1);
constructor() {
}
public sendMessage(data: ServiceMessage): void {
this.messageSubject.next(data);
}
public getMessage$(): Observable<ServiceMessage> {
return this.messageSubject.asObservable();
}
}

View File

@@ -4,10 +4,10 @@ import { ReplaySubject, Observable } from 'rxjs';
import { EditSession, UndoManager } from 'ace-builds'; import { EditSession, UndoManager } from 'ace-builds';
import { getModeForPath } from 'ace-builds/src-noconflict/ext-modelist'; import { getModeForPath } from 'ace-builds/src-noconflict/ext-modelist';
import { TabsService } from './tabs/tabs.service'; import { TabsService } from './editor/tabs/tabs.service';
import { NewtonFile } from '../../types/file.type'; import { NewtonFile } from '../types/file.type';
import { ServiceMessage } from '../../types/service-message.type'; import { ServiceMessage } from '../types/service-message.type';

View File

@@ -0,0 +1,5 @@
export abstract class EditorType {
static MiniMap: string = "mini-map";
static ReadOnly: string = "read-only";
static Standalone: string = "standalone";
}

View File

@@ -5,7 +5,10 @@ import { InfoBarService } from '../../common/services/editor/info-bar/info-bar.s
import { FilesModalService } from '../../common/services/editor/modals/files-modal.service'; import { FilesModalService } from '../../common/services/editor/modals/files-modal.service';
import { TabsService } from '../../common/services/editor/tabs/tabs.service'; import { TabsService } from '../../common/services/editor/tabs/tabs.service';
import { EditorsService } from '../../common/services/editor/editors.service'; import { EditorsService } from '../../common/services/editor/editors.service';
import { FilesService } from '../../common/services/editor/files.service'; import { FilesService } from '../../common/services/files.service';
import { SearchReplaceService } from '../../common/services/editor/search-replace/search-replace.service';
import { MarkdownPreviewService } from '../../common/services/editor/markdown-preview/markdown-preview.service';
import { LspManagerService } from '../../common/services/editor/lsp-manager/lsp-manager.service';
import { EditorSettings } from "../../common/configs/editor.config"; import { EditorSettings } from "../../common/configs/editor.config";
import { NewtonFile } from '../../common/types/file.type'; import { NewtonFile } from '../../common/types/file.type';
@@ -16,17 +19,20 @@ import { ServiceMessage } from '../../common/types/service-message.type';
@Directive() @Directive()
export class CodeViewBase { export class CodeViewBase {
public uuid: string = uuid.v4(); public uuid: string = uuid.v4();
@Input() public isDefault: boolean = false; @Input() public isDefault: boolean = false;
@Input() public isMiniMap: boolean = false; @Input() public mode: string = "";
public leftSiblingUUID!: string; public leftSiblingUUID!: string;
public rightSiblingUUID!: string; public rightSiblingUUID!: string;
protected infoBarService: InfoBarService = inject(InfoBarService); protected infoBarService: InfoBarService = inject(InfoBarService);
protected filesModalService: FilesModalService = inject(FilesModalService); protected filesModalService: FilesModalService = inject(FilesModalService);
protected tabsService: TabsService = inject(TabsService); protected tabsService: TabsService = inject(TabsService);
protected editorsService: EditorsService = inject(EditorsService); protected editorsService: EditorsService = inject(EditorsService);
protected filesService: FilesService = inject(FilesService); protected filesService: FilesService = inject(FilesService);
protected searchReplaceService: SearchReplaceService = inject(SearchReplaceService);
protected markdownPreviewService: MarkdownPreviewService = inject(MarkdownPreviewService);
protected lspManagerService: LspManagerService = inject(LspManagerService);
@ViewChild('editor') editorElm!: ElementRef; @ViewChild('editor') editorElm!: ElementRef;
@Input() editorSettings!: typeof EditorSettings; @Input() editorSettings!: typeof EditorSettings;
@@ -93,12 +99,32 @@ export class CodeViewBase {
this.editor.showKeyboardShortcuts(); this.editor.showKeyboardShortcuts();
} }
public lspManagerPopup() {
let message = new ServiceMessage();
message.action = "toggle-lsp-manager";
this.lspManagerService.sendMessage(message);
}
public markdownPreviewPopup() {
let message = new ServiceMessage();
message.action = "toggle-markdown-preview";
this.markdownPreviewService.sendMessage(message);
}
public searchPopup() { public searchPopup() {
this.editor.execCommand("find"); let message = new ServiceMessage();
message.action = "toggle-search-replace";
this.searchReplaceService.sendMessage(message);
// this.editor.execCommand("find");
} }
public replacePopup() { public replacePopup() {
this.editor.execCommand("replace"); let message = new ServiceMessage();
message.action = "toggle-search-replace";
this.searchReplaceService.sendMessage(message);
// this.editor.execCommand("replace");
} }
public showFilesList() { public showFilesList() {
@@ -159,6 +185,11 @@ export class CodeViewBase {
window.main.toggleFullScreen(); window.main.toggleFullScreen();
} }
public setAsReadOnly() {
this.editor.setReadOnly(true);
this.editor.setShowPrintMargin(false);
}
public setAsMiniMapView() { public setAsMiniMapView() {
this.editor.renderer.showLineNumbers = false; this.editor.renderer.showLineNumbers = false;
this.editor.renderer.setShowGutter(false); this.editor.renderer.setShowGutter(false);

View File

@@ -1,21 +1,22 @@
import { Component } from "@angular/core"; import { Component } from "@angular/core";
// Import Ace and its modes/themes so that `ace` global is defined // Import Ace and its modes/themes so that `ace` global is defined
import * as ace from "ace-builds/src-noconflict/ace"; import * as ace from "ace-builds/src-min-noconflict/ace";
import "ace-builds/src-noconflict/ext-settings_menu"; import "ace-builds/src-min-noconflict/ext-settings_menu";
import "ace-builds/src-noconflict/ext-keybinding_menu"; import "ace-builds/src-min-noconflict/ext-keybinding_menu";
import "ace-builds/src-noconflict/ext-command_bar"; import "ace-builds/src-min-noconflict/ext-command_bar";
import "ace-builds/src-noconflict/ext-prompt"; import "ace-builds/src-min-noconflict/ext-prompt";
import "ace-builds/src-noconflict/ext-code_lens"; import "ace-builds/src-min-noconflict/ext-code_lens";
import "ace-builds/src-noconflict/ext-searchbox"; // import "ace-builds/src-min-noconflict/ext-searchbox";
import "ace-builds/src-noconflict/ext-language_tools"; import "ace-builds/src-min-noconflict/ext-language_tools";
//import "ace-builds/src-noconflict/theme-one_dark"; // import "ace-builds/src-min-noconflict/theme-one_dark";
//import "ace-builds/src-noconflict/theme-penguins_in_space"; // import "ace-builds/src-min-noconflict/theme-penguins_in_space";
import "ace-builds/src-noconflict/theme-gruvbox"; import "ace-builds/src-min-noconflict/theme-gruvbox";
import { CodeViewBase } from './view.base'; import { CodeViewBase } from './view.base';
import { NewtonFile } from '../../common/types/file.type'; import { NewtonFile } from '../../common/types/file.type';
import { EditorType } from '../../common/types/editor.type';
import { ServiceMessage } from '../../common/types/service-message.type'; import { ServiceMessage } from '../../common/types/service-message.type';
@@ -47,19 +48,7 @@ export class CodeViewComponent extends CodeViewBase {
private loadAce(): void { private loadAce(): void {
this.configAceAndBindToElement() this.configAceAndBindToElement()
this.setupRequestedMode();
if (this.isDefault) {
this.editorsService.setActiveEditor(this.uuid);
this.addActiveStyling();
}
if (this.isMiniMap) {
this.setAsMiniMapView();
return;
}
this.loadAceKeyBindings();
this.loadAceEventBindings();
} }
private configAceAndBindToElement(): void { private configAceAndBindToElement(): void {
@@ -69,10 +58,34 @@ export class CodeViewComponent extends CodeViewBase {
this.editor = ace.edit( this.editorElm.nativeElement ); this.editor = ace.edit( this.editorElm.nativeElement );
this.editor.setOptions( this.editorSettings.CONFIG ); this.editor.setOptions( this.editorSettings.CONFIG );
this.editorsService.set(this.uuid, this); this.editorsService.set(this.uuid, this);
if (this.isDefault) {
this.editorsService.setActiveEditor(this.uuid);
this.addActiveStyling();
this.editor.focus();
}
} }
private loadAceKeyBindings(): void { private setupRequestedMode() {
switch(this.mode) {
case EditorType.Standalone:
// Note: Ace editor without any additional Newton setup...
break;
case EditorType.MiniMap:
this.setAsMiniMapView();
break;
case EditorType.ReadOnly:
this.setAsReadOnly();
break;
default:
this.loadNewtonKeyBindings();
this.loadNewtonEventBindings();
break;
}
}
private loadNewtonKeyBindings(): void {
let keyBindings = []; let keyBindings = [];
for (let i = 0; i < this.editorSettings.KEYBINDINGS.length; i++) { for (let i = 0; i < this.editorSettings.KEYBINDINGS.length; i++) {
let keyBinding = this.editorSettings.KEYBINDINGS[i]; let keyBinding = this.editorSettings.KEYBINDINGS[i];
@@ -104,15 +117,23 @@ export class CodeViewComponent extends CodeViewBase {
this.editor.commands.addCommands( keyBindings ); this.editor.commands.addCommands( keyBindings );
} }
private loadAceEventBindings(): void { private loadNewtonEventBindings(): void {
// Note: https://ajaxorg.github.io/ace-api-docs/interfaces/ace.Ace.EditorEvents.html // Note: https://ajaxorg.github.io/ace-api-docs/interfaces/ace.Ace.EditorEvents.html
this.editor.on("focus", (e) => { this.editor.on("focus", (e) => {
let message = new ServiceMessage(); let message = new ServiceMessage();
message.action = "set-active-editor"; message.action = "set-active-editor";
message.editorUUID = this.uuid; message.editorUUID = this.uuid;
message.rawData = this.editor;
this.editorsService.sendMessage(message); this.editorsService.sendMessage(message);
this.searchReplaceService.sendMessage(message);
this.lspManagerService.sendMessage(message);
message = new ServiceMessage();
message.action = "set-active-editor";
message.rawData = this;
this.markdownPreviewService.sendMessage(message);
this.updateInfoBar(); this.updateInfoBar();
}); });
@@ -154,6 +175,12 @@ export class CodeViewComponent extends CodeViewBase {
}); });
this.editor.on("changeSession", (session) => { this.editor.on("changeSession", (session) => {
let message = new ServiceMessage();
message.action = "set-active-editor";
message.rawData = this.editor;
this.lspManagerService.sendMessage(message);
this.updateInfoBar(); this.updateInfoBar();
}); });
} }

View File

@@ -4,7 +4,7 @@
<code-view [isDefault]="true"></code-view> <code-view [isDefault]="true"></code-view>
<hr class="col vr-pane-handle" pane-handle /> <hr class="col vr-pane-handle" pane-handle />
<code-view></code-view> <code-view></code-view>
<code-view [isMiniMap]="true"></code-view> <code-view [mode]="'mini-map'"></code-view>
</div> </div>
<div> <div>

View File

@@ -3,7 +3,7 @@ import { Subject, takeUntil } from 'rxjs';
import { EditorsService } from '../common/services/editor/editors.service'; import { EditorsService } from '../common/services/editor/editors.service';
import { TabsService } from '../common/services/editor/tabs/tabs.service'; import { TabsService } from '../common/services/editor/tabs/tabs.service';
import { FilesService } from '../common/services/editor/files.service'; import { FilesService } from '../common/services/files.service';
import { CodeViewComponent } from "./code-view/view.component"; import { CodeViewComponent } from "./code-view/view.component";

View File

@@ -0,0 +1,11 @@
.lsp-config-text {
display: grid;
min-height: 25em;
}
.clear-left-padding {
padding-left: 0px;
}
.clear-right-padding {
padding-right: 0px;
}

View File

@@ -0,0 +1,54 @@
<div class="container-fluid">
<div class="row mt-2 mb-3">
<div class="col clear-right-padding">
<div class="input-group-sm">
<label class="form-control" [innerText]="lspManagerService.workspaceFolder || 'Project Path...'">
</label>
</div>
</div>
<div class="col col-auto clear-left-padding">
<button class="btn btn-sm btn-dark" (click)="clearWorkspaceFolder()">x</button>
</div>
<div class="col col-auto">
<div class="input-group-sm">
<button class="btn btn-sm btn-dark" (click)="setWorkspaceFolder()">Workspace Folder</button>
<button class="btn btn-sm btn-danger ms-5" (click)="hideLspManager()">X</button>
</div>
</div>
</div>
<div class="row mt-2 md-2">
<div class="col">
LSP Configs:
</div>
</div>
<div class="row">
<div class="col">
<code-view #lspEditorComponent [mode]="'standalone'" class="lsp-config-text"></code-view>
</div>
</div>
<div class="row mt-2 md-2">
<div class="col">
Target Editor: <label [innerText]="editor?.id || 'Editor...'"></label>
</div>
<div class="col">
Active Editor Session:
</div>
</div>
<div class="row">
<div class="col">
<code-view #sessionEditorComponent [mode]="'read-only'" class="lsp-config-text"></code-view>
</div>
</div>
</div>

View File

@@ -0,0 +1,117 @@
import { Component, ChangeDetectorRef, ElementRef, HostBinding, ViewChild, inject } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { LspManagerService } from '../../common/services/editor/lsp-manager/lsp-manager.service';
import { CodeViewComponent } from '../code-view/view.component';
import { ServiceMessage } from '../../common/types/service-message.type';
@Component({
selector: 'lsp-manager',
standalone: true,
imports: [
CodeViewComponent
],
templateUrl: './lsp-manager.component.html',
styleUrl: './lsp-manager.component.css',
host: {
'class': 'lsp-manager',
"(keyup)": "globalLspManagerKeyHandler($event)"
}
})
export class LspManagerComponent {
private unsubscribe: Subject<void> = new Subject();
private changeDetectorRef: ChangeDetectorRef = inject(ChangeDetectorRef);
lspManagerService: LspManagerService = inject(LspManagerService);
@HostBinding("class.hidden") isHidden: boolean = true;
@ViewChild('lspEditorComponent') lspEditorComponent!: CodeViewComponent;
@ViewChild('sessionEditorComponent') sessionEditorComponent!: CodeViewComponent;
lspTextEditor: any;
innerEditor: any;
editor: any;
constructor() {
}
private ngAfterViewInit(): void {
this.lspTextEditor = this.lspEditorComponent.editor;
this.innerEditor = this.sessionEditorComponent.editor;
this.lspManagerService.loadLspConfigData().then((lspConfigData) => {
this.lspTextEditor.session.setMode("ace/mode/json");
this.lspTextEditor.session.setValue(lspConfigData);
});
this.loadSubscribers();
}
private ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
private loadSubscribers() {
this.lspManagerService.getMessage$().pipe(
takeUntil(this.unsubscribe)
).subscribe((message: ServiceMessage) => {
if (message.action === "toggle-lsp-manager") {
this.toggleLspManager(message);
} else if (message.action === "set-active-editor") {
this.setActiveEditor(message);
}
});
}
public clearWorkspaceFolder() {
this.lspManagerService.workspaceFolder = "";
}
public setWorkspaceFolder() {
window.fs.chooseFolder().then((folder: string) => {
if (!folder) return;
this.lspManagerService.workspaceFolder = folder;
});
}
public globalLspManagerKeyHandler(event: any) {
if (event.ctrlKey && event.shiftKey && event.key === "l") {
this.hideLspManager();
}
}
public hideLspManager() {
this.isHidden = true;
this.editor.focus();
}
private toggleLspManager(message: ServiceMessage) {
this.isHidden = !this.isHidden;
if (this.isHidden) return;
// Note: hack for issue with setActiveEditor TODO
setTimeout(() => {
this.innerEditor.setSession(this.editor.session);
}, 10);
}
private setActiveEditor(message: ServiceMessage) {
this.editor = message.rawData;
// TODO: figure out why this doesn't update the session consistently...
// It seems maybe bound to visible state as change detector ref didn't help either.
// this.innerEditor.setSession(this.editor.session);
}
}

View File

@@ -0,0 +1,6 @@
<div class="row">
<div class="col">
<div [innerHtml]="bodyHtml || defaultHtml">
</div>
</div>
</div>

View File

@@ -0,0 +1,96 @@
import { Component, HostBinding, inject } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { MarkdownPreviewService } from '../../common/services/editor/markdown-preview/markdown-preview.service';
import { ServiceMessage } from '../../common/types/service-message.type';
@Component({
selector: 'markdown-preview',
standalone: true,
imports: [
],
templateUrl: './markdown-preview.component.html',
styleUrl: './markdown-preview.component.css',
host: {
'class': 'container-fluid markdown-preview'
}
})
export class MarkdownPreviewComponent {
private unsubscribe: Subject<void> = new Subject();
private markdownPreviewService: MarkdownPreviewService = inject(MarkdownPreviewService);
@HostBinding("class.hidden") isHidden: boolean = true;
converter: any = new showdown.Converter();
defaultHtml: string = "<h1>NOT a Markdown file...</h1>"
bodyHtml: string = "";
private editorComponent!: any;
constructor() {
}
private ngAfterViewInit(): void {
this.loadSubscribers();
}
private ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
private loadSubscribers() {
this.markdownPreviewService.getMessage$().pipe(
takeUntil(this.unsubscribe)
).subscribe((message: ServiceMessage) => {
if (message.action === "toggle-markdown-preview") {
this.toggleMarkdownPreview(message);
} else if (message.action === "set-active-editor") {
this.setActiveEditor(message);
}
});
}
private toggleMarkdownPreview(message: ServiceMessage) {
this.isHidden = !this.isHidden;
setTimeout(() => {
this.updatePreview();
}, 10);
}
private setActiveEditor(message: ServiceMessage) {
if (this.editorComponent == message.rawData) return;
this.editorComponent = message.rawData;
if (this.isHidden) return;
this.updatePreview();
}
public updatePreview() {
let fileMode = this.editorComponent.editor.session.getMode()["$id"];
let isMdFile = (fileMode.includes("markdown"));
this.bodyHtml = "";
if (!isMdFile) return;
let mdStr = this.editorComponent.editor.session.getValue();
let pathParts = this.editorComponent.activeFile.path.split("/");
let basePath = "file://" + pathParts.slice(0, -1).join("/");
this.bodyHtml = this.converter.makeHtml(
mdStr.replaceAll("](images", `](${basePath}/images`)
.replaceAll("](imgs", `](${basePath}/imgs`)
.replaceAll("](pictures", `](${basePath}/pictures`)
.replaceAll("](pics", `](${basePath}/pics`)
.replaceAll("](screenshots", `](${basePath}/screenshots`)
);
}
}

View File

@@ -0,0 +1,39 @@
.buttons > button {
min-width: 3.5em;
min-height: 2.5em;
}
.width-8em {
width: 8em;
}
.margin-tb-1em {
margin-top: 1em;
margin-bottom: 1em;
}
.selected {
background-color: rgba(125, 125, 125, 1);
color: rgba(0, 0, 0, 1);
}
.searching,
.search-success,
.search-fail {
border-style: solid;
color: rgba(125, 125, 125, 1) !important;
}
.searching {
border-color: rgba(0, 225, 225, 0.64) !important;
}
.search-success {
background: rgba(136, 204, 39, 0.12) !important;
border-color: rgba(136, 204, 39, 1) !important;
}
.search-fail {
background: rgba(170, 18, 18, 0.12) !important;
border-color: rgba(200, 18, 18, 1) !important;
}

View File

@@ -0,0 +1,84 @@
<div class="col">
<div class="row">
<div class="col col-3">
<label id="find-status-lbl">Find in Current File</label>
</div>
<div class="col col-4">
<label id="find-options-lbl">Finding with Options: {{findOptions || "Case Insensitive"}}</label>
</div>
<div class="col col-5 line-height-32px buttons">
<button title="Close Panel"
class="float-end btn btn-sm btn-dark"
(click)="hideSearchReplace()">X
</button>
<button id="whole-word-btn" title="Whole Word"
class="float-end btn btn-sm btn-dark"
(click)="toggleWholeWordSearch($event)">
<img src="resources/imgs/whole-word.png" />
</button>
<button id="only-in-selection-btn" title="Only In Selection"
class="float-end btn btn-sm btn-dark"
(click)="toggleSelectionOnlyScan($event)">
<img src="resources/imgs/only-in-selection.png" />
</button>
<button id="match-case-btn" title="Match Case"
class="float-end btn btn-sm btn-dark"
(click)="toggleCaseSensitive($event)">Aa
</button>
<button id="use-regex-btn" title="Use Regex"
class="float-end btn btn-sm btn-dark"
(click)="toggleRegex($event)">.*
</button>
</div>
</div>
<div class="margin-tb-1em"></div>
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div class="input-group-sm mb-3">
<input #findEntryElm
id="find-entry"
class="form-control"
type="search"
(keyup)="searchForString()"
placeholder="Find in current file..."
aria-label="Find in current file..."
/>
</div>
</div>
<div class="col col-auto">
<button id="find-btn" class="width-8em btn btn-sm btn-dark" (click)="findNextEntry()">Find</button>
<button id="find-all-btn" class="width-8em btn btn-sm btn-dark" (click)="findAllEntries()">Find All</button>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div class="input-group-sm mb-3">
<input #replaceEntryElm
id="replace-entry"
class="form-control"
type="search"
(keyup)="replaceEntry($event)"
title="Replace in current file..."
placeholder="Replace in current file..."
/>
</div>
</div>
<div class="col col-auto">
<button id="replace-btn" class="width-8em btn btn-sm btn-dark" (click)="replaceEntry($event)">Replace</button>
<button id="replace-all-btn" class="width-8em btn btn-sm btn-dark" (click)="replaceAll()">Replace All</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,268 @@
import { Component, ElementRef, HostBinding, Input, ViewChild, inject } from '@angular/core';
import { Subject, takeUntil } from 'rxjs';
import { SearchReplaceService } from '../../common/services/editor/search-replace/search-replace.service';
import { ServiceMessage } from '../../common/types/service-message.type';
@Component({
selector: 'search-replace',
standalone: true,
imports: [
],
templateUrl: './search-replace.component.html',
styleUrl: './search-replace.component.css',
host: {
'class': 'row search-replace',
"(keyup)": "globalSearchReplaceKeyHandler($event)"
}
})
export class SearchReplaceComponent {
private unsubscribe: Subject<void> = new Subject();
private searchReplaceService: SearchReplaceService = inject(SearchReplaceService);
@HostBinding("class.hidden") isHidden: boolean = true;
@ViewChild('findEntryElm') findEntryElm!: ElementRef;
@ViewChild('replaceEntryElm') replaceEntryElm!: ElementRef;
private editor!: any;
@Input() findOptions: string = "";
private useWholeWordSearch: boolean = false;
private searchOnlyInSelection: boolean = false;
private useCaseSensitive: boolean = false;
private useRegex: boolean = false;
private selection: string = "";
private query: string = "";
private toStr: string = "";
private isBackwards: boolean = false;
private isWrap: boolean = true;
private searchTimeoutId: number = -1;
private searchTimeout: number = 400;
constructor() {
}
private ngAfterViewInit(): void {
this.loadSubscribers();
}
private ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
private loadSubscribers() {
this.searchReplaceService.getMessage$().pipe(
takeUntil(this.unsubscribe)
).subscribe((message: ServiceMessage) => {
if (message.action === "toggle-search-replace") {
this.toggleSearchReplace(message);
} else if (message.action === "set-active-editor") {
this.setActiveEditor(message);
}
});
}
private toggleSearchReplace(message: ServiceMessage) {
this.selection = this.editor.getSelectedText();
this.findEntryElm.nativeElement.value = this.selection;
if (this.selection && !this.isHidden) {
this.findEntryElm.nativeElement.focus();
return;
}
this.isHidden = !this.isHidden;
if (this.isHidden) {
this.editor.focus();
return;
}
setTimeout(() => {
this.findEntryElm.nativeElement.focus();
}, 200);
}
private setActiveEditor(message: ServiceMessage) {
if (this.editor == message.rawData) return;
this.editor = message.rawData;
if (this.isHidden) return;
this.searchForString();
}
public hideSearchReplace() {
if (this.selection) {
this.selection = "";
return;
}
this.isHidden = true;
this.editor.focus();
}
public globalSearchReplaceKeyHandler(event: any) {
if (event.ctrlKey && event.key === "f") {
this.hideSearchReplace();
} else if (event.ctrlKey && event.key === "l") {
this.findEntryElm.nativeElement.focus();
} else if (event.ctrlKey && event.key === "r") {
this.replaceEntryElm.nativeElement.focus();
}
}
public toggleWholeWordSearch(event: any) {
let target = event.target;
if (target.nodeName === "IMG")
target = target.parentElement;
this.useWholeWordSearch = !this.useWholeWordSearch;
target.classList.toggle("selected");
this.setFindOptionsLbl();
this.findAllEntries();
}
public toggleSelectionOnlyScan(event: any) {
let target = event.target;
if (target.nodeName === "IMG")
target = target.parentElement;
this.searchOnlyInSelection = !this.searchOnlyInSelection;
target.classList.toggle("selected");
this.setFindOptionsLbl();
this.findAllEntries();
}
public toggleCaseSensitive(event: any) {
this.useCaseSensitive = !this.useCaseSensitive;
event.target.classList.toggle("selected");
this.setFindOptionsLbl();
this.findAllEntries();
}
public toggleRegex(event: any) {
this.useRegex = !this.useRegex;
event.target.classList.toggle("selected");
this.setFindOptionsLbl();
this.findAllEntries();
}
private setFindOptionsLbl() {
let findOptionsStr = "";
if (this.useRegex)
findOptionsStr += "Regex"
findOptionsStr += (findOptionsStr) ? ", " : "";
findOptionsStr += (this.useCaseSensitive) ? "Case Sensitive" : "Case InSensitive";
if (this.searchOnlyInSelection)
findOptionsStr += ", Within Current Selection"
if (this.useWholeWordSearch)
findOptionsStr += ", Whole Word"
this.findOptions = findOptionsStr;
}
public findNextEntry() {
this.editor.findNext();
}
public findAllEntries() {
this.query = this.findEntryElm.nativeElement.value;
if (!this.query) return;
let totalCount = this.editor.findAll(this.query, {
backwards: this.isBackwards,
wrap: this.isWrap,
caseSensitive: this.useCaseSensitive,
wholeWord: this.useWholeWordSearch,
regExp: this.useRegex,
range: this.searchOnlyInSelection
});
}
public findPreviousEntry() {
this.editor.findPrevious();
}
public replaceEntry(event: any) {
if (event instanceof KeyboardEvent) {
if (event.key !== "Enter") {
return;
}
}
let fromStr = this.findEntryElm.nativeElement.value;
let toStr = this.replaceEntryElm.nativeElement.value;
if (!fromStr) return;
let totalCount = this.editor.replace(toStr, fromStr, {
backwards: this.isBackwards,
wrap: this.isWrap,
caseSensitive: this.useCaseSensitive,
wholeWord: this.useWholeWordSearch,
regExp: this.useRegex,
range: this.searchOnlyInSelection
});
this.editor.clearSelection();
this.editor.findNext();
}
public replaceAll() {
let fromStr = this.findEntryElm.nativeElement.value;
let toStr = this.replaceEntryElm.nativeElement.value;
if (!fromStr) return;
let totalCount = this.editor.replaceAll(toStr, fromStr, {
backwards: this.isBackwards,
wrap: this.isWrap,
caseSensitive: this.useCaseSensitive,
wholeWord: this.useWholeWordSearch,
regExp: this.useRegex,
range: this.searchOnlyInSelection
});
}
public searchForString() {
if (event instanceof KeyboardEvent) {
if (event.key !== "Enter") {
return;
}
}
this.query = this.findEntryElm.nativeElement.value;
if (!this.query) return;
if (this.searchTimeoutId) { clearTimeout(this.searchTimeoutId); }
this.searchTimeoutId = setTimeout(() => {
let totalCount = this.editor.find(this.query, {
backwards: this.isBackwards,
wrap: this.isWrap,
caseSensitive: this.useCaseSensitive,
wholeWord: this.useWholeWordSearch,
regExp: this.useRegex,
range: this.searchOnlyInSelection
});
}, this.searchTimeout);
}
}

View File

@@ -3,7 +3,7 @@
/* IDs */ /* IDs */
#ace_settingsmenu, #kbshortcutmenu { #ace_settingsmenu, #kbshortcutmenu {
background-color: rgba(0, 0, 0, 0.0); background-color: rgba(64, 64, 64, 0.84);
color: rgba(255, 255, 255, 1.0); color: rgba(255, 255, 255, 1.0);
box-shadow: -1px 4px 5px rgba(124, 124, 124, 0.64); box-shadow: -1px 4px 5px rgba(124, 124, 124, 0.64);
padding: 1em 0.5em 2em 1em; padding: 1em 0.5em 2em 1em;
@@ -38,6 +38,14 @@
color: rgba(255, 255, 255, 1.0); color: rgba(255, 255, 255, 1.0);
} }
.ace_optionsMenuEntry button {
color: #000;
}
.ace_optionsMenuEntry button[ace_selected_button=true] {
background: #00e877;
}
.ace_print-margin { .ace_print-margin {
width: 1px !important; width: 1px !important;
background-color: rgba(255, 0, 0, 0.84) !important; background-color: rgba(255, 0, 0, 0.84) !important;
@@ -52,4 +60,4 @@
.ace_sb-v, .ace_sb-v,
.ace_sb-h { .ace_sb-h {
width: 0.8em !important; width: 0.8em !important;
} }

View File

@@ -0,0 +1,17 @@
/* TAGS */
html {
background-color: rgba(40, 44, 52, 0.64);
color: rgba(255, 255, 255, 0.64);
}
body {
background-color: rgba(64, 64, 64, 0.0);
overflow: hidden;
}
/* IDs */
/* CLASSES */

View File

@@ -1,25 +1,45 @@
/* TAGS */ /* TAGS */
html {
/*
background-color: rgba(64, 64, 64, 0.64);
background-color: rgb(40, 44, 52);
*/
background-color: rgba(40, 44, 52, 0.64);
color: rgba(255, 255, 255, 0.64);
}
body {
background-color: rgba(64, 64, 64, 0.0);
overflow: hidden;
}
/* IDs */ /* IDs */
/* CLASSES */ /* CLASSES */
.search-replace,
.markdown-preview,
.lsp-manager {
display: inline-block;
position: fixed;
background-color: rgba(64, 64, 64, 0.84);
overflow: auto;
}
.search-replace {
bottom: 2em;
left: 2em;
right: 2em;
z-index: 900;
}
.markdown-preview {
top: 2em;
bottom: 2em;
right: 2em;
z-index: 700;
width: 50vw;
overflow: auto;
}
.lsp-manager {
top: 2em;
bottom: 2em;
left: 2em;
right: 2em;
z-index: 800;
}
.info-bar { .info-bar {
font-size: 0.8em; font-size: 0.8em;
color: rgba(255, 255, 255, 0.84); color: rgba(255, 255, 255, 0.84);
@@ -42,18 +62,12 @@ body {
border: 2px dashed lightblue; border: 2px dashed lightblue;
} }
/* .vr-pane-handle {
.hr-pane-handle { max-width: max-content;
height: 100%;
margin: 0px;
} }
.vr-pane-handle {
transform: rotate(90deg);
}
*/
.vr-pane-handle {
max-width: 0.05em;
}
@@ -68,10 +82,6 @@ body {
} }
.scroller { .scroller {
/*
-webkit-scrollbar-color: #00000084 #ffffff64;
scrollbar-color: #00000084 #ffffff64;
*/
-webkit-scrollbar-color: #00000084 #ffffff06; -webkit-scrollbar-color: #00000084 #ffffff06;
-webkit-scrollbar-width: thin; -webkit-scrollbar-width: thin;
scrollbar-color: #00000084 #ffffff06; scrollbar-color: #00000084 #ffffff06;

3
src/libs/showdown.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -29,6 +29,7 @@ declare global {
openFiles: (arg0) => Promise<string>, openFiles: (arg0) => Promise<string>,
saveFile: (arg0: any, arg1: any) => Promise<string>, saveFile: (arg0: any, arg1: any) => Promise<string>,
saveFileAs: () => Promise<string>, saveFileAs: () => Promise<string>,
chooseFolder: () => Promise<string>,
closeFile: (arg0: any) => Promise<string>, closeFile: (arg0: any) => Promise<string>,
getPathForFile: any, getPathForFile: any,
onLoadFiles: (arg0: any) => Promise<string>, onLoadFiles: (arg0: any) => Promise<string>,

1
src/typings.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
declare var showdown: any;

View File

@@ -13,4 +13,4 @@
"src/polyfills.ts", "src/polyfills.ts",
"src/**/*.d.ts" "src/**/*.d.ts"
] ]
} }

View File

@@ -16,8 +16,11 @@
"declaration": false, "declaration": false,
"skipLibCheck": true, "skipLibCheck": true,
"strict": false, "strict": false,
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true,
} },
"includes": [
"src/typings.d.ts"
]
} }
@@ -53,7 +56,10 @@
"strictInjectionParameters": true, "strictInjectionParameters": true,
"strictInputAccessModifiers": true, "strictInputAccessModifiers": true,
"strictTemplates": true "strictTemplates": true
} },
"includes": [
"src/typings.d.ts"
]
} }
*/ */