mirror of
https://codeberg.org/yeentown/barkey.git
synced 2025-04-30 02:26:56 +00:00
factor out common append-content-warning routine for use in both frontend and backend
This commit is contained in:
parent
7814c6e54e
commit
563e32316f
4 changed files with 219 additions and 12 deletions
62
packages/backend/src/misc/append-content-warning.ts
Normal file
62
packages/backend/src/misc/append-content-warning.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Important Note: this file must be kept in sync with packages/frontend-shared/js/append-content-warning.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends an additional content warning onto an existing one.
|
||||||
|
* The additional value will not be added if it already exists within the original input.
|
||||||
|
* @param original Existing content warning
|
||||||
|
* @param additional Content warning to append
|
||||||
|
* @param reverse If true, then the additional CW will be prepended instead of appended.
|
||||||
|
*/
|
||||||
|
export function appendContentWarning(original: string | null | undefined, additional: string, reverse = false): string {
|
||||||
|
// Easy case - if original is empty, then additional replaces it.
|
||||||
|
if (!original) {
|
||||||
|
return additional;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Easy case - if the additional CW is empty, then don't append it.
|
||||||
|
if (!additional) {
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the additional CW already exists in the input, then we *don't* append another copy!
|
||||||
|
if (includesWholeWord(original, additional)) {
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reverse
|
||||||
|
? `${additional}, ${original}`
|
||||||
|
: `${original}, ${additional}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates a regular expression like /\b(pattern)\b/, but with a raw non-regex pattern.
|
||||||
|
* We're checking to see whether the default CW appears inside the existing CW, but *only* if there's word boundaries on either side.
|
||||||
|
* @param input Input string to search
|
||||||
|
* @param target Target word / phrase to search for
|
||||||
|
*/
|
||||||
|
function includesWholeWord(input: string, target: string): boolean {
|
||||||
|
const parts = input.split(target);
|
||||||
|
|
||||||
|
// The additional string could appear multiple times within the original input.
|
||||||
|
// We need to check each occurrence, since any of them could potentially match.
|
||||||
|
for (let i = 0; i + 1 < parts.length; i++) {
|
||||||
|
const before = parts[i];
|
||||||
|
const after = parts[i + 1];
|
||||||
|
|
||||||
|
// If either the preceding or following tokens are a "word", then this "match" is actually just part of a longer word.
|
||||||
|
// Likewise, if *neither* token is a word, then this is a real match and the CW already exists in the input.
|
||||||
|
if (!/\w$/.test(before) && !/^\w/.test(after)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't match, then there is no existing CW.
|
||||||
|
return false;
|
||||||
|
}
|
92
packages/backend/test/unit/misc/append-content-warning.ts
Normal file
92
packages/backend/test/unit/misc/append-content-warning.ts
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { appendContentWarning } from '@/misc/append-content-warning.js';
|
||||||
|
|
||||||
|
describe(appendContentWarning, () => {
|
||||||
|
it('should return additional when original is null', () => {
|
||||||
|
const result = appendContentWarning(null, 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return additional when original is undefined', () => {
|
||||||
|
const result = appendContentWarning(undefined, 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return additional when original is empty', () => {
|
||||||
|
const result = appendContentWarning('', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return original when additional is empty', () => {
|
||||||
|
const result = appendContentWarning('original', '');
|
||||||
|
|
||||||
|
expect(result).toBe('original');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append additional when it does not exist in original', () => {
|
||||||
|
const result = appendContentWarning('original', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('original, additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append additional when it exists in original but has preceeding word', () => {
|
||||||
|
const result = appendContentWarning('notadditional', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('notadditional, additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append additional when it exists in original but has following word', () => {
|
||||||
|
const result = appendContentWarning('additionalnot', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('additionalnot, additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should append additional when it exists in original multiple times but has preceeding or following word', () => {
|
||||||
|
const result = appendContentWarning('notadditional additionalnot', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('notadditional additionalnot, additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not append additional when it exists in original', () => {
|
||||||
|
const result = appendContentWarning('an additional word', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('an additional word');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not append additional when original starts with it', () => {
|
||||||
|
const result = appendContentWarning('additional word', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('additional word');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not append additional when original ends with it', () => {
|
||||||
|
const result = appendContentWarning('an additional', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('an additional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not append additional when it appears multiple times', () => {
|
||||||
|
const result = appendContentWarning('an additional additional word', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('an additional additional word');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not append additional when it appears multiple times but some have preceeding or following', () => {
|
||||||
|
const result = appendContentWarning('a notadditional additional additionalnot word', 'additional');
|
||||||
|
|
||||||
|
expect(result).toBe('a notadditional additional additionalnot word');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should prepend additional when reverse is true', () => {
|
||||||
|
const result = appendContentWarning('original', 'additional', true);
|
||||||
|
|
||||||
|
expect(result).toBe('additional, original');
|
||||||
|
});
|
||||||
|
});
|
62
packages/frontend-shared/js/append-content-warning.ts
Normal file
62
packages/frontend-shared/js/append-content-warning.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: hazelnoot and other Sharkey contributors
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Important Note: this file must be kept in sync with packages/backend/src/misc/append-content-warning.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends an additional content warning onto an existing one.
|
||||||
|
* The additional value will not be added if it already exists within the original input.
|
||||||
|
* @param original Existing content warning
|
||||||
|
* @param additional Content warning to append
|
||||||
|
* @param reverse If true, then the additional CW will be prepended instead of appended.
|
||||||
|
*/
|
||||||
|
export function appendContentWarning(original: string | null | undefined, additional: string, reverse = false): string {
|
||||||
|
// Easy case - if original is empty, then additional replaces it.
|
||||||
|
if (!original) {
|
||||||
|
return additional;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Easy case - if the additional CW is empty, then don't append it.
|
||||||
|
if (!additional) {
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the additional CW already exists in the input, then we *don't* append another copy!
|
||||||
|
if (includesWholeWord(original, additional)) {
|
||||||
|
return original;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reverse
|
||||||
|
? `${additional}, ${original}`
|
||||||
|
: `${original}, ${additional}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulates a regular expression like /\b(pattern)\b/, but with a raw non-regex pattern.
|
||||||
|
* We're checking to see whether the default CW appears inside the existing CW, but *only* if there's word boundaries on either side.
|
||||||
|
* @param input Input string to search
|
||||||
|
* @param target Target word / phrase to search for
|
||||||
|
*/
|
||||||
|
function includesWholeWord(input: string, target: string): boolean {
|
||||||
|
const parts = input.split(target);
|
||||||
|
|
||||||
|
// The additional string could appear multiple times within the original input.
|
||||||
|
// We need to check each occurrence, since any of them could potentially match.
|
||||||
|
for (let i = 0; i + 1 < parts.length; i++) {
|
||||||
|
const before = parts[i];
|
||||||
|
const after = parts[i + 1];
|
||||||
|
|
||||||
|
// If either the preceding or following tokens are a "word", then this "match" is actually just part of a longer word.
|
||||||
|
// Likewise, if *neither* token is a word, then this is a real match and the CW already exists in the input.
|
||||||
|
if (!/\w$/.test(before) && !/^\w/.test(after)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't match, then there is no existing CW.
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -112,6 +112,7 @@ import * as Misskey from 'misskey-js';
|
||||||
import insertTextAtCursor from 'insert-text-at-cursor';
|
import insertTextAtCursor from 'insert-text-at-cursor';
|
||||||
import { toASCII } from 'punycode.js';
|
import { toASCII } from 'punycode.js';
|
||||||
import { host, url } from '@@/js/config.js';
|
import { host, url } from '@@/js/config.js';
|
||||||
|
import { appendContentWarning } from '@@/js/append-content-warning.js';
|
||||||
import type { MenuItem } from '@/types/menu.js';
|
import type { MenuItem } from '@/types/menu.js';
|
||||||
import type { PostFormProps } from '@/types/post-form.js';
|
import type { PostFormProps } from '@/types/post-form.js';
|
||||||
import MkNoteSimple from '@/components/MkNoteSimple.vue';
|
import MkNoteSimple from '@/components/MkNoteSimple.vue';
|
||||||
|
@ -373,18 +374,8 @@ if ($i.defaultCW) {
|
||||||
if (!cw.value || $i.defaultCWPriority === 'default') {
|
if (!cw.value || $i.defaultCWPriority === 'default') {
|
||||||
cw.value = $i.defaultCW;
|
cw.value = $i.defaultCW;
|
||||||
} else if ($i.defaultCWPriority !== 'parent') {
|
} else if ($i.defaultCWPriority !== 'parent') {
|
||||||
// This is a fancy way of simulating /\bsearch\b/ without a regular expression.
|
const putDefaultFirst = $i.defaultCWPriority === 'defaultParent';
|
||||||
// We're checking to see whether the default CW appears inside the existing CW, but *only* if there's word boundaries.
|
cw.value = appendContentWarning(cw.value, $i.defaultCW, putDefaultFirst);
|
||||||
const parts = cw.value.split($i.defaultCW);
|
|
||||||
const hasExistingDefaultCW = parts.length === 2 && !/\w$/.test(parts[0]) && !/^\w/.test(parts[1]);
|
|
||||||
if (!hasExistingDefaultCW) {
|
|
||||||
// We need to merge the CWs
|
|
||||||
if ($i.defaultCWPriority === 'defaultParent') {
|
|
||||||
cw.value = `${$i.defaultCW}, ${cw.value}`;
|
|
||||||
} else if ($i.defaultCWPriority === 'parentDefault') {
|
|
||||||
cw.value = `${cw.value}, ${$i.defaultCW}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// else { do nothing, because existing CW takes priority. }
|
// else { do nothing, because existing CW takes priority. }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue