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

added: new lang detection, handling and support for multiple new languages #8

Merged
merged 28 commits into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
18d512f
added: new lang detection, handling and support for multiple new lang…
scolastico Nov 9, 2024
de87720
fix: installed typescript
scolastico Nov 9, 2024
6f71cc0
added: lib folder to labler
scolastico Nov 9, 2024
69e38a5
fix: missing pointer-events-none in gh badge
scolastico Nov 9, 2024
3b21a00
fix: missing events
scolastico Nov 9, 2024
faf5252
fix: remove now unused build artifacts
scolastico Nov 9, 2024
e51cad6
added: language to db to ensure persistence
scolastico Nov 9, 2024
a5257c0
fix: wrong type interpretation
scolastico Nov 9, 2024
2aee0df
fix: displaying old language state, and only plaintext on loaded content
scolastico Nov 9, 2024
8f90833
added: xml, sql and plaintext language
scolastico Nov 9, 2024
3906ea9
fix: removed hard coded plaintext option
scolastico Nov 9, 2024
70416e9
added: mime type to language info
scolastico Nov 9, 2024
fa54727
fix: removed unused import
scolastico Nov 9, 2024
ed9aa6d
fix: mismatch of scrollbar style
scolastico Nov 9, 2024
78a6dbd
added: custom error page
scolastico Nov 9, 2024
bfee4af
fix: out of bound issues
scolastico Nov 9, 2024
cea4bef
fix: removed unused code
scolastico Nov 9, 2024
ef3d776
fix: tokenizer setup
scolastico Nov 9, 2024
9ca0328
fix: disable module resolution for typescript in monaco
scolastico Nov 9, 2024
77a2ccd
style: added max w to error page info box
scolastico Nov 9, 2024
2bc4f83
style: select none -> img on error page
scolastico Nov 9, 2024
74d07b7
feat: download as file
scolastico Nov 10, 2024
ecf81fe
style: fix nav entry styling
scolastico Nov 10, 2024
a06e9c8
ci: optimize build pipeline
scolastico Nov 10, 2024
6e43966
feat: added share dialog if auto copy does not work
scolastico Nov 10, 2024
dfb2065
feat: reworked share handler to be more dynamic
scolastico Nov 10, 2024
727bd42
feat: share overview
scolastico Nov 11, 2024
0f8776b
fix: not allowed return false in docker false
scolastico Nov 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ components: components/**
server: server/**
pages: pages/**
public: public/**
lib: lib/**
11 changes: 11 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ jobs:
username: ${{github.actor}}
password: ${{secrets.GITHUB_TOKEN}}

- name: Install node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install pnpm
run: npm install -g pnpm
- name: Install dependencies
run: pnpm install
- name: Prebuild static files
run: pnpm generate && mv .output .output-prebuild

- uses: mr-smithers-excellent/docker-build-push@v6
id: docker_build
with:
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ jobs:
username: ${{github.actor}}
password: ${{secrets.GITHUB_TOKEN}}

- name: Install node
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install pnpm
run: npm install -g pnpm
- name: Install dependencies
run: pnpm install
- name: Prebuild static files
run: pnpm generate && mv .output .output-prebuild

- uses: mr-smithers-excellent/docker-build-push@v6
id: docker_build
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ logs
!.env.example

db.sqlite
.output-prebuild
10 changes: 2 additions & 8 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,10 @@ ENV NUXT_APP_BASE_URL=$NUXT_APP_BASE_URL
RUN pnpm build
RUN cp -rL .output /app/SERVER_OUTPUT

RUN pnpm generate
RUN test -d .output-prebuilt || pnpm generate
RUN test -d .output-prebuilt && rm .output && mv .output-prebuilt .output || true
RUN cp -rL .output/public /app/CLIENT_OUTPUT

RUN mkdir /app/SERVER_OUTPUT/public/node_modules && \
mkdir /app/CLIENT_OUTPUT/node_modules && \
cp -rL node_modules/monaco-editor-workers /app/SERVER_OUTPUT/public/node_modules/monaco-editor-workers && \
cp -rL node_modules/monaco-editor /app/SERVER_OUTPUT/public/node_modules/monaco-editor && \
cp -rL node_modules/monaco-editor-workers /app/CLIENT_OUTPUT/node_modules/monaco-editor-workers && \
cp -rL node_modules/monaco-editor /app/CLIENT_OUTPUT/node_modules/monaco-editor

### Production Image
FROM node:20-alpine
LABEL maintainer="Joschua Becker EDV <support@scolasti.co>"
Expand Down
28 changes: 28 additions & 0 deletions assets/css/scrollbar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

* {
--sb-track-color: #000;
--sb-thumb-color: #fff;
--sb-size: 8px;
}

*::-webkit-scrollbar {
width: var(--sb-size)
}

*::-webkit-scrollbar-track {
background: var(--sb-track-color);
border-radius: 0;
}

*::-webkit-scrollbar-thumb {
background: var(--sb-thumb-color);
border-radius: 0;

}

@supports not selector(::-webkit-scrollbar) {
body {
scrollbar-color: var(--sb-thumb-color)
var(--sb-track-color);
}
}
127 changes: 98 additions & 29 deletions components/editor.vue
Original file line number Diff line number Diff line change
@@ -1,60 +1,129 @@
<template>
<div ref="container" class="w-full h-full" />
<div ref="container" class="w-full flex-grow" />
</template>

<script lang="ts" setup>
const container = ref(null) as any as Ref<HTMLDivElement>;
import { ref, watch, onMounted, onBeforeUnmount, type Ref } from 'vue';
import * as monaco from 'monaco-editor';
import { buildWorkerDefinition } from 'monaco-editor-workers';
import type { EditorEvents, LanguageInfo } from '~/lib/monaco/types';
import { detectLanguageFromContent, debounce } from '~/lib/monaco/utils';
import { setupMonaco } from '~/lib/monaco/setup';
import { languageDefinitions } from '~/lib/monaco/languages';

const props = defineProps<{
const props = withDefaults(defineProps<{
modelValue: string;
readonly?: boolean;
}>();
theme?: string;
forcedLanguage?: string|null;
}>(), {
readonly: false,
theme: 'vs-dark'
});

const emit = defineEmits<EditorEvents>();
const container = ref(null) as any as Ref<HTMLDivElement>;
let editor: monaco.editor.IStandaloneCodeEditor | null = null;

const emit = defineEmits(['update:modelValue', 'loaded', 'save', 'duplicate', 'new']);
const currentLanguage = ref<string>('plaintext');

let editor: any = null;
const setEditorLanguage = (languageId: string) => {
if (currentLanguage.value === languageId) return;
if (editor && editor.getModel()) {
console.log('Setting language:', languageId);
currentLanguage.value = languageId;
monaco.editor.setModelLanguage(editor.getModel()!, languageId);
}
};

const updateLanguage = debounce((content: string) => {
if (editor) {
const detectedLanguage = detectLanguageFromContent(content);
emit('language-detected', detectedLanguage);
if (!props.forcedLanguage) setEditorLanguage(detectedLanguage);
}
}, 500);

onMounted(async () => {
const [monaco, worker] = await Promise.all([
import('monaco-editor'),
import('monaco-editor-workers'),
]);
worker.buildWorkerDefinition(
buildWorkerDefinition(
'../node_modules/monaco-editor-workers/dist/workers',
import.meta.url,
false
);
const ed = monaco.editor.create(container.value, {
value: props.modelValue + '',
language: 'javascript',
theme: 'vs-dark',
readOnly: !!props.readonly,

await setupMonaco();

const availableLanguages = languageDefinitions.map(lang => ({
id: lang.id,
extensions: lang.extensions,
aliases: lang.aliases || [],
mimeTypes: lang.mimeTypes || [],
} as LanguageInfo));
emit('loaded-languages', availableLanguages);

const initialDetectedLanguage = detectLanguageFromContent(props.modelValue);
emit('language-detected', initialDetectedLanguage);
const initialLanguage = props.forcedLanguage || initialDetectedLanguage;
currentLanguage.value = initialLanguage;
const model = monaco.editor.createModel(props.modelValue, initialLanguage);

editor = monaco.editor.create(container.value, {
model,
theme: props.theme,
readOnly: props.readonly,
automaticLayout: true,
minimap: { enabled: true },
scrollBeyondLastLine: false,
fontSize: 14,
tabSize: 2,
wordWrap: 'on',
lineNumbers: 'on',
});
editor = ed;
ed.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, async () => {

// Register keyboard shortcuts
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
emit('save');
});
ed.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyD, async () => {
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyD, () => {
emit('duplicate');
});
ed.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyN, async () => {
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyN, () => {
emit('new');
});
ed.onDidChangeModelContent(async () => {
setTimeout(() => {
emit('update:modelValue', ed.getValue());
}, 1);
// emit('update:modelValue', ed.getValue());

// Handle content changes
editor.onDidChangeModelContent(() => {
const value = editor?.getValue() || '';
emit('update:modelValue', value);
updateLanguage(value);
});

emit('loaded');
});

onBeforeUnmount(() => {
editor?.dispose();
});

// Watch for prop changes
watch(() => props.readonly, (value) => {
editor.updateOptions({ readOnly: !!value });
editor?.updateOptions({ readOnly: !!value });
});

watch(() => props.modelValue, (newValue, oldValue) => {
if (newValue === oldValue || newValue === editor?.getValue()) return;
editor?.setValue(newValue);
console.log('Model value updated:', newValue);
updateLanguage(newValue);
});

watch(() => props.theme, (newTheme) => {
editor?.updateOptions({ theme: newTheme });
});

watch(() => props.modelValue, (n, o) => {
if (n === o || n === editor.getValue()) return;
editor.setValue(n);
watch(() => props.forcedLanguage, (newLanguage) => {
if (!editor) return;
if (newLanguage) setEditorLanguage(newLanguage);
else setEditorLanguage(detectLanguageFromContent(editor.getValue()));
});
</script>
4 changes: 2 additions & 2 deletions components/gh-badge.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="fixed top-0 right-0 translate-x-1/2 -translate-y-1/2 z-50">
<div class="fixed top-0 right-0 translate-x-1/2 -translate-y-1/2 z-50 pointer-events-none">
<div
class="bg-white shadow-md p-2 select-none hover:opacity-100 opacity-40 transition-opacity duration-300"
class="bg-white shadow-md p-2 select-none hover:opacity-100 opacity-40 transition-opacity duration-300 pointer-events-auto"
:class="{
'cursor-pointer': props.to !== undefined,
}"
Expand Down
Loading
Loading