Skip to content

Commit

Permalink
Merge branch 'spellcheck-adaptions' into 'main'
Browse files Browse the repository at this point in the history
Spellcheck adaptions

See merge request reportcreator/reportcreator!371
  • Loading branch information
MWedl committed Dec 14, 2023
2 parents 12ac3ce + 55f6e0a commit 60c6e27
Show file tree
Hide file tree
Showing 24 changed files with 191 additions and 116 deletions.
6 changes: 3 additions & 3 deletions api/src/reportcreator_api/api_utils/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,15 @@ def validate_language(self, value):

async def spellcheck(self):
data = self.validated_data
return await self.languagetool_request('/v2/check', {
return await self.languagetool_request('/v2/check', settings.SPELLCHECK_LANGUAGETOOL_CONFIG | {
'language': data['language'],
'data': json.dumps(data['data'], ensure_ascii=False),
'level': 'picky' if settings.SPELLCHECK_MODE_PICKY else 'default',
**({
'preferredVariants': ','.join(self.spellcheck_languages),
} if data['language'] == 'auto' else {}),
})


def validate_singe_word(val):
if ' ' in val:
Expand Down Expand Up @@ -127,4 +128,3 @@ def validate_aes_key(self, value):
except ValueError:
raise serializers.ValidationError('Invalid base64 encoding')


2 changes: 2 additions & 0 deletions api/src/reportcreator_api/conf/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ def __bool__(self):

SPELLCHECK_URL = config('SPELLCHECK_URL', default=None)
SPELLCHECK_DICTIONARY_PER_USER = config('SPELLCHECK_DICTIONARY_PER_USER', cast=bool, default=False)
SPELLCHECK_MODE_PICKY = config('SPELLCHECK_MODE_PICKY', cast=bool, default=False)
SPELLCHECK_LANGUAGETOOL_CONFIG = config('SPELLCHECK_LANGUAGETOOL_CONFIG', cast=json.loads, default='{"disabledRules": "TODO,TO_DO_HYPHEN"}')

BACKUP_KEY = config('BACKUP_KEY', default=None)

Expand Down
13 changes: 12 additions & 1 deletion docs/docs/setup/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,21 @@ Words are added to a global spell check dictionary by default, which is availabl
Using both global and personal dictionaries at the same time is not possible. Words of personal dictionaries are not shared between users. If one user adds an unknown word to their personal dictionary, the spell checker will still detect an error for other users, even when they are working in the same project or finding.


``` title="Example:"
``` title="Spell check dictionary configuration"
SPELLCHECK_DICTIONARY_PER_USER=false
```

The picky mode enables additional spell check rules.

It is also possible to selectively enable and disable rules or rule-categories by passing a LanguageTool configuration as JSON.
See https://languagetool.org/http-api/ for available options on the `/check` request.
See https://community.languagetool.org/rule/list for available rules (note: rule IDs might differ for languages).

``` title="Spell check rule configuration"
SPELLCHECK_PICKY_MODE=true
SPELLCHECK_LANGUAGETOOL_CONFIG='{"disabledRules": "TODO,TO_DO_HYPHEN,PASSIVE_VOICE,PASSIVE_SENTENCE_DE"}'
```

### Languages
Configure which languages are available in the language selection.
By default all languages are shown.
Expand Down
16 changes: 12 additions & 4 deletions frontend/src/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@

<script setup lang="ts">
const route = useRoute();
useHeadExtended({
titleTemplate: title => rootTitleTemplate(title, route),
});
const auth = useAuth();
const localSettings = useLocalSettings();
const apiSettings = useApiSettings();
useHeadExtended({
titleTemplate: title => rootTitleTemplate(title, route),
});
const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)');
const systemThemeIsDark = ref<boolean>(colorSchemeQueryList.matches);
colorSchemeQueryList.addEventListener('change', (event) => {
Expand All @@ -40,4 +40,12 @@ const theme = computed(() => {
return baseTheme;
}
});
const router = useRouter();
watch(router.currentRoute, () => {
// Reset browser-based spellcheck on navigation
if (!apiSettings.settings?.features.spellcheck) {
localSettings.setAllSpellcheckSettings(false);
}
})
</script>
4 changes: 4 additions & 0 deletions frontend/src/components/Design/InputFieldDefinition.vue
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@
@update:model-value="updateProperty('default', $event)"
:definition="{...props.modelValue, label: 'Default Value', required: false, pattern: null} as FieldDefinition"
:lang="props.lang"
v-model:spellcheck-enabled="localSettings.designSpellcheckEnabled"
v-model:markdown-editor-mode="localSettings.designMarkdownEditorMode"
:disabled="props.disabled"
:disable-validation="true"
/>
Expand Down Expand Up @@ -289,6 +291,8 @@ const emit = defineEmits<{
'update:modelValue': [FieldDefinitionWithId];
}>();
const localSettings = useLocalSettings();
const rules = {
id: [
(id: string) => (
Expand Down
11 changes: 10 additions & 1 deletion frontend/src/components/Design/LayoutComponentForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@

<script setup lang="ts">
import pick from "lodash/pick";
import { MarkdownEditorMode } from "~/utils/types";
import type { MarkdownProps } from "~/composables/markdown";
const props = defineProps<{
Expand All @@ -189,7 +190,15 @@ const emit = defineEmits<{
'update:modelValue': [any];
}>();
const markdownProps = computed(() => pick(props, ['disabled', 'lang', 'uploadFile', 'rewriteFileUrl', 'rewriteReferenceLink']));
const localSettings = useLocalSettings();
const markdownProps = computed(() => ({
...pick(props, ['disabled', 'lang', 'uploadFile', 'rewriteFileUrl', 'rewriteReferenceLink']),
spellcheckEnabled: localSettings.designSpellcheckEnabled,
'onUpdate:spellcheckEnabled': (value: boolean) => { localSettings.designSpellcheckEnabled = value },
markdownEditorMode: localSettings.designMarkdownEditorMode,
'onUpdate:markdownEditorMode': (value: MarkdownEditorMode) => { localSettings.designMarkdownEditorMode = value },
}));
const form = ref();
watch(() => props.modelValue, () => {
Expand Down
30 changes: 17 additions & 13 deletions frontend/src/components/Design/PreviewDataForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,7 @@
@update:model-value="updateSectionField(fieldId, $event)"
:id="fieldId"
:definition="props.projectType.report_fields[fieldId]"
:show-field-ids="true"
:upload-file="uploadFile"
:rewrite-file-url="rewriteFileUrl"
:selectable-users="[auth.user.value as UserShortInfo]"
:lang="props.projectType.language"
:disabled="props.disabled"
v-bind="fieldAttrs"
/>
</div>
</template>
Expand All @@ -84,12 +79,7 @@
@update:model-value="updateFindingField(fieldId, $event)"
:id="fieldId"
:definition="props.projectType.finding_fields[fieldId]"
:show-field-ids="true"
:upload-file="uploadFile"
:rewrite-file-url="rewriteFileUrl"
:selectable-users="[auth.user.value as UserShortInfo]"
:lang="props.projectType.language"
:disabled="props.disabled"
v-bind="fieldAttrs"
/>
</div>
</template>
Expand All @@ -100,7 +90,7 @@
<script setup lang="ts">
import Draggable from "vuedraggable";
import { v4 as uuidv4 } from "uuid";
import { FieldDataType } from "~/utils/types";
import { FieldDataType, MarkdownEditorMode } from "~/utils/types";
import { scoreFromVector, levelNumberFromLevelName, levelNumberFromScore } from "~/utils/cvss";
const props = defineProps<{
Expand All @@ -114,6 +104,7 @@ const emit = defineEmits<{
'update:modelValue': [any];
}>();
const localSettings = useLocalSettings();
const auth = useAuth();
const menuSize = ref(20);
Expand Down Expand Up @@ -214,6 +205,19 @@ function riskLevel(finding: any) {
return 'unknown';
}
}
const fieldAttrs = computed(() => ({
showFieldIds: true,
uploadFile: props.uploadFile,
rewriteFileUrl: props.rewriteFileUrl,
selectableUsers: [auth.user.value],
lang: props.projectType.language,
disabled: props.disabled,
spellcheckEnabled: localSettings.designSpellcheckEnabled,
'onUpdate:spellcheckEnabled': (val: boolean) => { localSettings.designSpellcheckEnabled = val },
markdownEditorMode: localSettings.designMarkdownEditorMode,
'onUpdate:markdownEditorMode': (val: MarkdownEditorMode) => { localSettings.designMarkdownEditorMode = val },
}));
</script>

<style lang="scss" scoped>
Expand Down
15 changes: 8 additions & 7 deletions frontend/src/components/DynamicInputField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@
<script setup lang="ts">
import Draggable from 'vuedraggable';
import pick from 'lodash/pick';
import { MarkdownEditorMode } from '~/utils/types';
import type { MarkdownProps } from "~/composables/markdown";
import regexWorkerUrl from '~/workers/regexWorker?worker&url';
Expand All @@ -244,7 +246,9 @@ const props = defineProps<MarkdownProps & {
disableValidation?: boolean;
}>();
const emit = defineEmits<{
(e: 'update:modelValue', value: any): void;
'update:modelValue': [value: any];
'update:spellcheckEnabled': [value: boolean];
'update:markdownEditorMode': [value: MarkdownEditorMode];
}>();
function getInitialValue(fieldDef: FieldDefinition, useDefault = true): any {
Expand Down Expand Up @@ -373,12 +377,9 @@ const attrs = useAttrs();
const fieldAttrs = computed(() => ({
...attrs,
label: label.value,
disabled: props.disabled,
autofocus: props.autofocus,
lang: props.lang,
uploadFile: props.uploadFile,
rewriteFileUrl: props.rewriteFileUrl,
rewriteReferenceLink: props.rewriteReferenceLink,
...pick(props, ['disabled', 'autofocus', 'lang', 'spellcheckEnabled', 'markdownEditorMode', 'uploadFile', 'rewriteFileUrl', 'rewriteReferenceLink']),
'onUpdate:spellcheckEnabled': (v: boolean) => emit('update:spellcheckEnabled', v),
'onUpdate:markdownEditorMode': (v: MarkdownEditorMode) => emit('update:markdownEditorMode', v),
}))
</script>
Expand Down
12 changes: 5 additions & 7 deletions frontend/src/components/Markdown/FieldContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
<v-divider />

<v-row no-gutters class="w-100">
<v-col :cols="localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-show="localSettings.markdownEditorMode !== MarkdownEditorMode.PREVIEW">
<v-col :cols="props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-show="props.markdownEditorMode !== MarkdownEditorMode.PREVIEW">
<div
ref="editorRef"
class="mde-editor"
:class="{'mde-editor-side': localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW}"
:class="{'mde-editor-side': props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW}"
/>
</v-col>
<v-col v-if="localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW">
<v-col v-if="props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW">
<v-divider vertical class="h-100" />
</v-col>
<v-col :cols="localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-if="localSettings.markdownEditorMode !== MarkdownEditorMode.MARKDOWN">
<v-col :cols="props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-if="props.markdownEditorMode !== MarkdownEditorMode.MARKDOWN">
<markdown-preview v-bind="markdownPreviewAttrs" class="preview" />
</v-col>
</v-row>
Expand All @@ -25,16 +25,14 @@
</template>

<script setup lang="ts">
const localSettings = useLocalSettings();
const props = defineProps(makeMarkdownProps({
files: true,
spellcheckSupportedDefault: true,
}));
const emit = defineEmits(makeMarkdownEmits());
const { editorView, markdownToolbarAttrs, markdownStatusbarAttrs, markdownPreviewAttrs, focus, blur } = useMarkdownEditor({
props: computed(() => ({ ...props, spellcheckSupported: true })),
props: computed(() => ({ ...props, spellcheckSupported: true } as any)),
emit,
extensions: markdownEditorDefaultExtensions(),
});
Expand Down
14 changes: 5 additions & 9 deletions frontend/src/components/Markdown/Page.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@

<template #default>
<v-row no-gutters class="w-100 h-100">
<v-col :cols="localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-show="localSettings.markdownEditorMode !== MarkdownEditorMode.PREVIEW" class="h-100">
<v-col :cols="props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-show="props.markdownEditorMode !== MarkdownEditorMode.PREVIEW" class="h-100">
<div
ref="editorRef"
class="mde-editor h-100 overflow-y-auto"
:class="{'mde-editor-side': localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW}"
:class="{'mde-editor-side': props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW}"
/>
</v-col>
<v-col v-if="localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW" class="h-100">
<v-col v-if="props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW" class="h-100">
<v-divider vertical class="h-100" />
</v-col>
<v-col :cols="localSettings.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-if="localSettings.markdownEditorMode !== MarkdownEditorMode.MARKDOWN" class="h-100">
<v-col :cols="props.markdownEditorMode === MarkdownEditorMode.MARKDOWN_AND_PREVIEW ? 6 : undefined" v-if="props.markdownEditorMode !== MarkdownEditorMode.MARKDOWN" class="h-100">
<markdown-preview v-bind="markdownPreviewAttrs" class="preview h-100 overflow-y-scroll" />
</v-col>
</v-row>
Expand All @@ -26,18 +26,14 @@
</template>

<script setup lang="ts">
import { markdownEditorPageExtensions } from "~/composables/markdown";
const localSettings = useLocalSettings();
const props = defineProps(makeMarkdownProps({
files: true,
spellcheckSupportedDefault: true,
}));
const emit = defineEmits(makeMarkdownEmits());
const { editorView, markdownToolbarAttrs, markdownPreviewAttrs, focus, blur } = useMarkdownEditor({
props: computed(() => ({ ...props, spellcheckSupported: true })),
props: computed(() => ({ ...props, spellcheckSupported: true } as any)),
emit,
extensions: markdownEditorPageExtensions(),
});
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Markdown/Preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function rewriteFileSource(imgSrc: string) {
return imgSrc;
}
return absoluteApiUrl(props.rewriteFileUrl(`${imgSrc}?c=${cacheBuster}`));
return absoluteApiUrl(props.rewriteFileUrl(`${imgSrc}?c=${cacheBuster.value}`));
}
const updatePreviewThrottled = throttle(() => {
// Render markdown to HTML
Expand Down
Loading

0 comments on commit 60c6e27

Please sign in to comment.