@vrcd-community/zhlint
Version:
A linting tool for Chinese language.
98 lines (97 loc) • 4.05 kB
JavaScript
/**
* @fileoverview
*
* This rule is used to check whether there should be a space between
* content.
*
* Options:
* - spaceBetweenHalfwidthContent: boolean | undefined
* - `true`: ensure one space between half-width content (default)
* - `false` or `undefined`: do nothing, just keep the original format
* - noSpaceBetweenFullwidthContent: boolean | undefined
* - `true`: remove the space between full-width content (default)
* - `false` or `undefined`: do nothing, just keep the original format
* - spaceBetweenMixedwidthContent: boolean | undefined
* - `true`: keep one space between width-mixed content (default)
* - `false`: no space between width-mixed content
* - `undefined`: do nothing, just keep the original format
*
* Examples (betweenMixedWidthContent = true):
* - *a*啊 -> *a* 啊
* - *a *啊 -> *a* 啊
* - *啊*a -> *啊* a
* - *啊 *a -> *啊* a
*
* Examples (betweenMixedWidthContent = false):
* - *a* 啊 -> *a*啊
* - *a *啊 -> *a*啊
* - *啊* a -> *啊*a
* - *啊 *a -> *啊*a
*/
import { CharType, isLetterType } from '../parser/index.js';
import { checkSpaceAfter, findVisibleTokenAfter, findWrappersBetween } from './util.js';
import { CONTENT_NOSPACE_FULL_WIDTH, CONTENT_NOSPACE_MIXED_WIDTH, CONTENT_SPACE_HALF_WIDTH, CONTENT_SPACE_MIXED_WIDTH } from './messages.js';
const generateHandler = (options) => {
const onlyOneBetweenHalfwidthContentOption = options === null || options === void 0 ? void 0 : options.spaceBetweenHalfwidthContent;
const noBetweenFullwidthContentOption = options === null || options === void 0 ? void 0 : options.noSpaceBetweenFullwidthContent;
const betweenMixedwidthContentOption = options === null || options === void 0 ? void 0 : options.spaceBetweenMixedwidthContent;
return (token, _, group) => {
// skip non-content tokens
if (!isLetterType(token.type)) {
return;
}
// skip non-content after-tokens
const contentTokenAfter = findVisibleTokenAfter(group, token);
if (!contentTokenAfter || !isLetterType(contentTokenAfter.type)) {
return;
}
// find the space host
const { spaceHost, tokens } = findWrappersBetween(group, token, contentTokenAfter);
// skip if the space host is not found
if (!spaceHost) {
return;
}
// 1. half x half, full x full
// 2. half x full, full x half
if (contentTokenAfter.type === token.type) {
// skip without custom option
if (token.type === CharType.WESTERN_LETTER) {
if (!onlyOneBetweenHalfwidthContentOption) {
return;
}
// skip if half-content x marks x half-content
if (tokens.length > 1 &&
tokens.filter((token) => token.spaceAfter).length === 0) {
return;
}
}
else {
if (!noBetweenFullwidthContentOption) {
return;
}
}
const spaceAfter = token.type === CharType.WESTERN_LETTER ? ' ' : '';
const message = token.type === CharType.WESTERN_LETTER
? CONTENT_SPACE_HALF_WIDTH
: CONTENT_NOSPACE_FULL_WIDTH;
checkSpaceAfter(spaceHost, spaceAfter, message);
}
else {
// skip without custom option
if (typeof betweenMixedwidthContentOption === 'undefined') {
return;
}
const spaceAfter = betweenMixedwidthContentOption ? ' ' : '';
const message = betweenMixedwidthContentOption
? CONTENT_SPACE_MIXED_WIDTH
: CONTENT_NOSPACE_MIXED_WIDTH;
checkSpaceAfter(spaceHost, spaceAfter, message);
}
};
};
export const defaultConfig = {
spaceBetweenHalfWidthContent: true,
noSpaceBetweenFullWidthContent: true,
spaceBetweenMixedWidthContent: true
};
export default generateHandler;