Merge branch 'master' of github.com:bitsocialnet/5chan

This commit is contained in:
Tommaso Casaburi
2026-05-23 17:20:18 +07:00
9 changed files with 294 additions and 16 deletions
@@ -1,8 +1,23 @@
import { describe, expect, it } from 'vitest';
import { getUnsupportedPostOptionsMessage } from '../post-options-utils';
import { getNonokoPendingAccountCommentIndex, getNonokoPendingRouteState, getUnsupportedPostOptionsMessage, hasNonokoOption } from '../post-options-utils';
describe('post-options-utils', () => {
it('rejects additional dice options instead of dropping them', () => {
expect(getUnsupportedPostOptionsMessage('dice+1d6 dice+1d20', 'qst')).toBe('unsupported options: dice+1d20');
});
it('supports nonoko while keeping sage unsupported', () => {
expect(getUnsupportedPostOptionsMessage('nonoko', undefined)).toBeNull();
expect(getUnsupportedPostOptionsMessage('sage', 'b')).toBe('unsupported options: sage');
expect(hasNonokoOption('fortune nonoko')).toBe(true);
expect(hasNonokoOption('nonokosage')).toBe(false);
});
it('reads the nonoko pending account comment index from direct and wrapped route state', () => {
expect(getNonokoPendingRouteState(7)).toEqual({ nonokoPendingAccountCommentIndex: 7 });
expect(getNonokoPendingAccountCommentIndex({ nonokoPendingAccountCommentIndex: 7 })).toBe(7);
expect(getNonokoPendingAccountCommentIndex({ usr: { nonokoPendingAccountCommentIndex: 8 } })).toBe(8);
expect(getNonokoPendingAccountCommentIndex({ nonokoPendingAccountCommentIndex: -1 })).toBeUndefined();
expect(getNonokoPendingAccountCommentIndex({ nonokoPendingAccountCommentIndex: '7' })).toBeUndefined();
});
});
+33
View File
@@ -77,6 +77,10 @@ export const getPostOptionsDirectoryCode = (directory: PostOptionsDirectory | nu
};
const isSupportedPostOption = (option: string, directoryCode: string | undefined): boolean => {
if (option === 'nonoko') {
return true;
}
if (option === 'fortune') {
return !!directoryCode && FORTUNE_DIRECTORY_CODES.has(directoryCode);
}
@@ -106,6 +110,35 @@ export const getUnsupportedPostOptionsMessage = (value: string, directoryCode: s
export const isUnsupportedPostOptionsMessage = (message: string | null): boolean => message?.startsWith('unsupported options:') === true;
export const hasNonokoOption = (value: string): boolean => parsePostOptions(value).includes('nonoko');
const NONOKO_PENDING_ACCOUNT_COMMENT_INDEX_STATE_KEY = 'nonokoPendingAccountCommentIndex';
type NonokoPendingRouteState = {
[NONOKO_PENDING_ACCOUNT_COMMENT_INDEX_STATE_KEY]?: unknown;
usr?: unknown;
};
const getNonokoPendingAccountCommentIndexFromRecord = (state: NonokoPendingRouteState): number | undefined => {
const value = state[NONOKO_PENDING_ACCOUNT_COMMENT_INDEX_STATE_KEY];
return Number.isInteger(value) && (value as number) >= 0 ? (value as number) : undefined;
};
export const getNonokoPendingRouteState = (commentIndex: number) => ({
[NONOKO_PENDING_ACCOUNT_COMMENT_INDEX_STATE_KEY]: commentIndex,
});
export const getNonokoPendingAccountCommentIndex = (state: unknown): number | undefined => {
if (!state || typeof state !== 'object') return undefined;
const directIndex = getNonokoPendingAccountCommentIndexFromRecord(state as NonokoPendingRouteState);
if (directIndex !== undefined) return directIndex;
const wrappedState = (state as NonokoPendingRouteState).usr;
if (!wrappedState || typeof wrappedState !== 'object') return undefined;
return getNonokoPendingAccountCommentIndexFromRecord(wrappedState as NonokoPendingRouteState);
};
const hasFortuneOption = (value: string, directoryCode: string | undefined): boolean =>
!!directoryCode && FORTUNE_DIRECTORY_CODES.has(directoryCode) && parsePostOptions(value).includes('fortune');