2026-01-05 13:03:55 +08:00
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __create = Object . create ;
var __defProp = Object . defineProperty ;
var __getOwnPropDesc = Object . getOwnPropertyDescriptor ;
var __getOwnPropNames = Object . getOwnPropertyNames ;
var __getProtoOf = Object . getPrototypeOf ;
var __hasOwnProp = Object . prototype . hasOwnProperty ;
var __commonJS = ( cb , mod ) => function __require () {
return mod || ( 0 , cb [ __getOwnPropNames ( cb )[ 0 ]])(( mod = { exports : {} }). exports , mod ), mod . exports ;
};
var __export = ( target , all ) => {
for ( var name in all )
__defProp ( target , name , { get : all [ name ], enumerable : true });
};
var __copyProps = ( to , from , except , desc ) => {
if ( from && typeof from === "object" || typeof from === "function" ) {
for ( let key of __getOwnPropNames ( from ))
if ( ! __hasOwnProp . call ( to , key ) && key !== except )
__defProp ( to , key , { get : () => from [ key ], enumerable : ! ( desc = __getOwnPropDesc ( from , key )) || desc . enumerable });
}
return to ;
};
var __toESM = ( mod , isNodeMode , target ) => ( target = mod != null ? __create ( __getProtoOf ( mod )) : {}, __copyProps ( isNodeMode || ! mod || ! mod . __esModule ? __defProp ( target , "default" , { value : mod , enumerable : true }) : target , mod ));
var __toCommonJS = ( mod ) => __copyProps ( __defProp ({}, "__esModule" , { value : true }), mod );
// node_modules/sprintf-js/src/sprintf.js
var require_sprintf = __commonJS ({
"node_modules/sprintf-js/src/sprintf.js" ( exports ) {
! function () {
"use strict" ;
var re = {
not_string : /[^s]/ ,
not_bool : /[^t]/ ,
not_type : /[^T]/ ,
not_primitive : /[^v]/ ,
number : /[diefg]/ ,
numeric_arg : /[bcdiefguxX]/ ,
json : /[j]/ ,
not_json : /[^j]/ ,
text : /^[^\x25]+/ ,
modulo : /^\x25{2}/ ,
placeholder : /^\x25(?:([1-9]\d*)\$|\(([^)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/ ,
key : /^([a-z_][a-z_\d]*)/i ,
key_access : /^\.([a-z_][a-z_\d]*)/i ,
index_access : /^\[(\d+)\]/ ,
sign : /^[+-]/
};
function sprintf2 ( key ) {
return sprintf_format ( sprintf_parse ( key ), arguments );
}
function vsprintf ( fmt , argv ) {
return sprintf2 . apply ( null , [ fmt ]. concat ( argv || []));
}
function sprintf_format ( parse_tree , argv ) {
var cursor = 1 , tree_length = parse_tree . length , arg , output = "" , i , k , ph , pad , pad_character , pad_length , is_positive , sign ;
for ( i = 0 ; i < tree_length ; i ++ ) {
if ( typeof parse_tree [ i ] === "string" ) {
output += parse_tree [ i ];
} else if ( typeof parse_tree [ i ] === "object" ) {
ph = parse_tree [ i ];
if ( ph . keys ) {
arg = argv [ cursor ];
for ( k = 0 ; k < ph . keys . length ; k ++ ) {
if ( arg == void 0 ) {
throw new Error ( sprintf2 ( '[sprintf] Cannot access property "%s" of undefined value "%s"' , ph . keys [ k ], ph . keys [ k - 1 ]));
}
arg = arg [ ph . keys [ k ]];
}
} else if ( ph . param_no ) {
arg = argv [ ph . param_no ];
} else {
arg = argv [ cursor ++ ];
}
if ( re . not_type . test ( ph . type ) && re . not_primitive . test ( ph . type ) && arg instanceof Function ) {
arg = arg ();
}
if ( re . numeric_arg . test ( ph . type ) && ( typeof arg !== "number" && isNaN ( arg ))) {
throw new TypeError ( sprintf2 ( "[sprintf] expecting number but found %T" , arg ));
}
if ( re . number . test ( ph . type )) {
is_positive = arg >= 0 ;
}
switch ( ph . type ) {
case "b" :
arg = parseInt ( arg , 10 ). toString ( 2 );
break ;
case "c" :
arg = String . fromCharCode ( parseInt ( arg , 10 ));
break ;
case "d" :
case "i" :
arg = parseInt ( arg , 10 );
break ;
case "j" :
arg = JSON . stringify ( arg , null , ph . width ? parseInt ( ph . width ) : 0 );
break ;
case "e" :
arg = ph . precision ? parseFloat ( arg ). toExponential ( ph . precision ) : parseFloat ( arg ). toExponential ();
break ;
case "f" :
arg = ph . precision ? parseFloat ( arg ). toFixed ( ph . precision ) : parseFloat ( arg );
break ;
case "g" :
arg = ph . precision ? String ( Number ( arg . toPrecision ( ph . precision ))) : parseFloat ( arg );
break ;
case "o" :
arg = ( parseInt ( arg , 10 ) >>> 0 ). toString ( 8 );
break ;
case "s" :
arg = String ( arg );
arg = ph . precision ? arg . substring ( 0 , ph . precision ) : arg ;
break ;
case "t" :
arg = String ( !! arg );
arg = ph . precision ? arg . substring ( 0 , ph . precision ) : arg ;
break ;
case "T" :
arg = Object . prototype . toString . call ( arg ). slice ( 8 , - 1 ). toLowerCase ();
arg = ph . precision ? arg . substring ( 0 , ph . precision ) : arg ;
break ;
case "u" :
arg = parseInt ( arg , 10 ) >>> 0 ;
break ;
case "v" :
arg = arg . valueOf ();
arg = ph . precision ? arg . substring ( 0 , ph . precision ) : arg ;
break ;
case "x" :
arg = ( parseInt ( arg , 10 ) >>> 0 ). toString ( 16 );
break ;
case "X" :
arg = ( parseInt ( arg , 10 ) >>> 0 ). toString ( 16 ). toUpperCase ();
break ;
}
if ( re . json . test ( ph . type )) {
output += arg ;
} else {
if ( re . number . test ( ph . type ) && ( ! is_positive || ph . sign )) {
sign = is_positive ? "+" : "-" ;
arg = arg . toString (). replace ( re . sign , "" );
} else {
sign = "" ;
}
pad_character = ph . pad_char ? ph . pad_char === "0" ? "0" : ph . pad_char . charAt ( 1 ) : " " ;
pad_length = ph . width - ( sign + arg ). length ;
pad = ph . width ? pad_length > 0 ? pad_character . repeat ( pad_length ) : "" : "" ;
output += ph . align ? sign + arg + pad : pad_character === "0" ? sign + pad + arg : pad + sign + arg ;
}
}
}
return output ;
}
var sprintf_cache = /* @__PURE__ */ Object . create ( null );
function sprintf_parse ( fmt ) {
if ( sprintf_cache [ fmt ]) {
return sprintf_cache [ fmt ];
}
var _fmt = fmt , match , parse_tree = [], arg_names = 0 ;
while ( _fmt ) {
if (( match = re . text . exec ( _fmt )) !== null ) {
parse_tree . push ( match [ 0 ]);
} else if (( match = re . modulo . exec ( _fmt )) !== null ) {
parse_tree . push ( "%" );
} else if (( match = re . placeholder . exec ( _fmt )) !== null ) {
if ( match [ 2 ]) {
arg_names |= 1 ;
var field_list = [], replacement_field = match [ 2 ], field_match = [];
if (( field_match = re . key . exec ( replacement_field )) !== null ) {
field_list . push ( field_match [ 1 ]);
while (( replacement_field = replacement_field . substring ( field_match [ 0 ]. length )) !== "" ) {
if (( field_match = re . key_access . exec ( replacement_field )) !== null ) {
field_list . push ( field_match [ 1 ]);
} else if (( field_match = re . index_access . exec ( replacement_field )) !== null ) {
field_list . push ( field_match [ 1 ]);
} else {
throw new SyntaxError ( "[sprintf] failed to parse named argument key" );
}
}
} else {
throw new SyntaxError ( "[sprintf] failed to parse named argument key" );
}
match [ 2 ] = field_list ;
} else {
arg_names |= 2 ;
}
if ( arg_names === 3 ) {
throw new Error ( "[sprintf] mixing positional and named placeholders is not (yet) supported" );
}
parse_tree . push ({
placeholder : match [ 0 ],
param_no : match [ 1 ],
keys : match [ 2 ],
sign : match [ 3 ],
pad_char : match [ 4 ],
align : match [ 5 ],
width : match [ 6 ],
precision : match [ 7 ],
type : match [ 8 ]
});
} else {
throw new SyntaxError ( "[sprintf] unexpected placeholder" );
}
_fmt = _fmt . substring ( match [ 0 ]. length );
}
return sprintf_cache [ fmt ] = parse_tree ;
}
if ( typeof exports !== "undefined" ) {
exports [ "sprintf" ] = sprintf2 ;
exports [ "vsprintf" ] = vsprintf ;
}
if ( typeof window !== "undefined" ) {
window [ "sprintf" ] = sprintf2 ;
window [ "vsprintf" ] = vsprintf ;
if ( typeof define === "function" && define [ "amd" ]) {
define ( function () {
return {
"sprintf" : sprintf2 ,
"vsprintf" : vsprintf
};
});
}
}
}();
}
});
// src/main.ts
var main_exports = {};
__export ( main_exports , {
default : () => EasyTypingPlugin
});
module . exports = __toCommonJS ( main_exports );
2026-08-21 15:44:03 +08:00
var import_obsidian9 = require ( "obsidian" );
var import_state6 = require ( "@codemirror/state" );
2026-01-05 13:03:55 +08:00
// src/core.ts
var import_obsidian = require ( "obsidian" );
// src/utils.ts
2026-08-21 15:44:03 +08:00
var import_state = require ( "@codemirror/state" );
2026-01-05 13:03:55 +08:00
var DEBUG = false ;
var print = ( message , ... optionalParams ) => {
if ( DEBUG ) {
console . log ( message , ... optionalParams );
}
};
function setDebug ( value ) {
DEBUG = value ;
}
function offsetToPos ( doc , offset ) {
let line = doc . lineAt ( offset );
return { line : line . number - 1 , ch : offset - line . from };
}
function getTypeStrOfTransac ( tr ) {
2026-08-21 15:44:03 +08:00
const event = tr . annotation ( import_state . Transaction . userEvent );
return event != null ? event : "unknown" ;
2026-01-05 13:03:55 +08:00
}
function string2pairstring ( s ) {
let cursorIdx = findFirstPipeNotPrecededByBackslash ( s );
let left = s . substring ( 0 , cursorIdx );
let _left = isRegexp ( left ) ? left : convertEscapeChar ( left );
let right = s . substring ( cursorIdx + 1 );
let _right = isRegexp ( right ) ? right : convertEscapeChar ( right );
return { left : _left , right : _right };
}
function isRegexp ( s ) {
return s . startsWith ( "r/" ) && s . endsWith ( "/" );
}
function convertEscapeChar ( s ) {
return s . replace ( /\\\|/g , "|" ). replace ( /\\n/g , "\n" ). replace ( /\\r/g , "\r" ). replace ( /\\t/g , " " ). replace ( /\\\n/g , "\\n" ). replace ( /\\\r/g , "\\r" ). replace ( /\\\t/g , "\\t" ). replace ( /\\\\/g , "\\" );
}
function findFirstPipeNotPrecededByBackslash ( s ) {
let regex = /^r\/[^]*?\/\|/ ;
let regMatch = s . match ( regex );
if ( regMatch )
return regMatch [ 0 ]. length - 1 ;
const match = s . match ( /((^|[^\\])(\\\\)*)\|/ );
return match ? s . indexOf ( match [ 0 ]) + match [ 1 ]. length : - 1 ;
}
function stringDeleteAt ( str , index ) {
return str . substring ( 0 , index ) + str . substring ( index + 1 );
}
function stringInsertAt ( str , index , s ) {
return str . substring ( 0 , index ) + s + str . substring ( index );
}
function isParamDefined ( param ) {
return typeof param !== "undefined" ;
}
function taboutCursorInPairedString ( input , cursorPosition , symbolPairs ) {
2026-08-21 15:44:03 +08:00
const sortedPairs = [... symbolPairs ]. sort (( a , b ) => b . left . length - a . left . length );
2026-01-05 13:03:55 +08:00
let stack = [];
let fail = { isSuccess : false , newPosition : 0 };
for ( let i = 0 ; i < cursorPosition ; i ++ ) {
2026-08-21 15:44:03 +08:00
for ( const { left : open , right : close } of sortedPairs ) {
2026-01-05 13:03:55 +08:00
if ( input . startsWith ( open , i ) && ( open !== close || stack . lastIndexOf ( open ) === - 1 )) {
stack . push ( open );
i += open . length - 1 ;
2026-08-21 15:44:03 +08:00
break ;
2026-01-05 13:03:55 +08:00
} else if ( input . startsWith ( close , i ) && stack . length > 0 ) {
const lastOpenIndex = stack . lastIndexOf ( open );
if ( lastOpenIndex !== - 1 ) {
stack = stack . slice ( 0 , lastOpenIndex );
2026-08-21 15:44:03 +08:00
i += close . length - 1 ;
break ;
2026-01-05 13:03:55 +08:00
}
}
}
}
if ( stack . length === 0 ) {
return fail ;
}
let tempStack = [];
for ( let i = cursorPosition ; i < input . length ; i ++ ) {
2026-08-21 15:44:03 +08:00
for ( const { left : open , right : close } of sortedPairs ) {
2026-01-05 13:03:55 +08:00
if ( input . startsWith ( open , i ) && ( open !== close || stack . lastIndexOf ( open ) === - 1 && tempStack . lastIndexOf ( open ) === - 1 )) {
tempStack . push ( open );
i += open . length - 1 ;
2026-08-21 15:44:03 +08:00
break ;
2026-01-05 13:03:55 +08:00
} else if ( input . startsWith ( close , i )) {
const lastOpenIndex = tempStack . lastIndexOf ( open );
if ( lastOpenIndex === - 1 && stack . lastIndexOf ( open ) !== - 1 ) {
return { isSuccess : true , newPosition : cursorPosition === i ? i + close . length : i };
} else if ( lastOpenIndex !== - 1 ) {
tempStack = tempStack . slice ( 0 , lastOpenIndex );
2026-08-21 15:44:03 +08:00
i += close . length - 1 ;
break ;
2026-01-05 13:03:55 +08:00
}
}
}
}
return fail ;
}
// src/core.ts
var import_language = require ( "@codemirror/language" );
2026-08-21 15:44:03 +08:00
// src/formatting/script_category.ts
var SCRIPT_CHAR_CLASSES = {
[ "chinese" /* Chinese */ ] : "\\u4e00-\\u9fff\\u3400-\\u4dbf" ,
[ "japanese" /* Japanese */ ] : "\\u3040-\\u309f\\u30a0-\\u30ff\\u31f0-\\u31ff" ,
[ "korean" /* Korean */ ] : "\\uac00-\\ud7af\\u1100-\\u11ff\\u3130-\\u318f" ,
[ "cjk" /* CJK */ ] : "\\u4e00-\\u9fff\\u3400-\\u4dbf\\u3040-\\u309f\\u30a0-\\u30ff\\u31f0-\\u31ff\\uac00-\\ud7af\\u1100-\\u11ff\\u3130-\\u318f" ,
[ "english" /* English */ ] : "A-Za-z" ,
[ "digit" /* Digit */ ] : "0-9" ,
[ "russian" /* Russian */ ] : "\\u0400-\\u04ff" ,
[ "unknown" /* Unknown */ ] : ""
};
function classifyChar ( ch ) {
if ( ! ch || ch . length === 0 )
return "unknown" /* Unknown */ ;
const code = ch . charCodeAt ( 0 );
if ( code >= 19968 && code <= 40959 || code >= 13312 && code <= 19903 ) {
return "chinese" /* Chinese */ ;
}
if ( code >= 12352 && code <= 12447 || code >= 12448 && code <= 12543 || code >= 12784 && code <= 12799 ) {
return "japanese" /* Japanese */ ;
}
if ( code >= 44032 && code <= 55215 || code >= 4352 && code <= 4607 || code >= 12592 && code <= 12687 ) {
return "korean" /* Korean */ ;
}
if ( code >= 65 && code <= 90 || code >= 97 && code <= 122 ) {
return "english" /* English */ ;
}
if ( code >= 48 && code <= 57 ) {
return "digit" /* Digit */ ;
}
if ( code >= 1024 && code <= 1279 ) {
return "russian" /* Russian */ ;
}
return "unknown" /* Unknown */ ;
}
function resolveCharClass ( cat , customCategories ) {
if ( cat in SCRIPT_CHAR_CLASSES ) {
return SCRIPT_CHAR_CLASSES [ cat ];
}
if ( customCategories ) {
const custom = customCategories . find (( c ) => c . name === cat );
if ( custom )
return custom . pattern ;
}
return "" ;
}
function buildPairRegexps ( a , b , customCategories ) {
const classA = resolveCharClass ( a , customCategories );
const classB = resolveCharClass ( b , customCategories );
if ( ! classA || ! classB )
return [];
const regAB = new RegExp ( `([ ${ classA } ])([ ${ classB } ])` , "g" );
const regBA = new RegExp ( `([ ${ classB } ])([ ${ classA } ])` , "g" );
return [ regAB , regBA ];
}
// src/formatting/text_formatter.ts
function capitalizeFirstLetter ( ctx , isFirstPart , isCursorInPart ) {
if ( ! isFirstPart )
return ctx ;
const { content , prevCh , curCh } = ctx ;
const regFirstSentence = /^\s*(?:\- (?:\[[x ]\] )?)?"?(?:\*{1,3}|_{1,3}|==|~~)?[a-z\u0401\u0451\u0410-\u044f]/g ;
const regHeaderSentence = /^(?:#+ |>+ ?|")(?:\*{1,3}|_{1,3}|==|~~)?[a-z\u0401\u0451\u0410-\u044f]/g ;
let textcopy = content ;
let match = regFirstSentence . exec ( textcopy );
let matchHeader = regHeaderSentence . exec ( textcopy );
let dstCharIndex = - 1 ;
if ( match ) {
dstCharIndex = regFirstSentence . lastIndex - 1 ;
} else if ( matchHeader ) {
dstCharIndex = regHeaderSentence . lastIndex - 1 ;
}
if ( isParamDefined ( prevCh ) && ! isCursorInPart ) {
return ctx ;
}
if ( ! ( isParamDefined ( prevCh ) && dstCharIndex >= prevCh && dstCharIndex < curCh )) {
dstCharIndex = - 1 ;
}
if ( dstCharIndex !== - 1 ) {
const newContent = textcopy . substring ( 0 , dstCharIndex ) + textcopy . charAt ( dstCharIndex ). toUpperCase () + textcopy . substring ( dstCharIndex + 1 );
return { ... ctx , content : newContent };
}
return ctx ;
}
function capitalizeMidSentence ( ctx ) {
let { content , curCh , prevCh , offset } = ctx ;
const reg = /(?:[.?!]\s+|[。!?]\s*)(?:\*{1,3}|_{1,3}|==|~~)?[a-z\u0401\u0451\u0410-\u044f]/g ;
while ( true ) {
const match = reg . exec ( content );
if ( ! match )
break ;
const tempIndex = reg . lastIndex - 1 ;
const isSpaceDot = tempIndex - 2 < 0 || content . substring ( tempIndex - 2 , tempIndex ) === " ." ;
if ( isParamDefined ( prevCh ) && tempIndex >= prevCh - offset && tempIndex < curCh - offset && ! isSpaceDot ) {
content = content . substring ( 0 , tempIndex ) + content . charAt ( tempIndex ). toUpperCase () + content . substring ( reg . lastIndex );
}
}
return { ... ctx , content };
}
function isCJKContext ( ch ) {
const cat = classifyChar ( ch );
if ( cat === "chinese" /* Chinese */ || cat === "japanese" /* Japanese */ || cat === "korean" /* Korean */ ) {
return true ;
}
if ( ch . length > 0 ) {
const code = ch . charCodeAt ( 0 );
if ( code >= 12288 && code <= 12351 || code >= 65281 && code <= 65295 || code >= 65306 && code <= 65312 || code >= 65339 && code <= 65344 || code >= 65371 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 65072 && code <= 65103 ) {
return true ;
}
}
return false ;
}
function findTokenBounds ( content , pos ) {
pos = Math . max ( 0 , Math . min ( pos , content . length ));
let refIdx = pos > 0 ? pos - 1 : 0 ;
if ( refIdx >= content . length )
refIdx = content . length - 1 ;
if ( refIdx < 0 )
return [ 0 , 0 ];
const refIsCJK = isCJKContext ( content . charAt ( refIdx ));
let left = pos ;
while ( left > 0 && ! /[\s\0]/ . test ( content . charAt ( left - 1 ))) {
const ch = content . charAt ( left - 1 );
const isCJK = isCJKContext ( ch );
if ( ! isCJK && ! /\w/ . test ( ch ))
break ;
if ( isCJK !== refIsCJK )
break ;
left -- ;
}
let right = pos ;
while ( right < content . length && ! /[\s\0]/ . test ( content . charAt ( right ))) {
const ch = content . charAt ( right );
const isCJK = isCJKContext ( ch );
if ( ! isCJK && ! /\w/ . test ( ch ))
break ;
if ( isCJK !== refIsCJK )
break ;
right ++ ;
}
return [ left , right ];
}
function extractToken ( content , left , right ) {
return content . substring ( left , right ). replace ( /\0/g , "" );
}
function extendCursorTokenForDict ( content , seedL , seedR , prefixDict , usePrefix ) {
const seedToken = extractToken ( content , seedL , seedR );
let runL = seedL ;
while ( runL > 0 ) {
const ch = content . charAt ( runL - 1 );
if ( /[\s\0]/ . test ( ch ) || ! /\w/ . test ( ch ) && ! isCJKContext ( ch ))
break ;
runL -- ;
}
let runR = seedR ;
while ( runR < content . length ) {
const ch = content . charAt ( runR );
if ( /[\s\0]/ . test ( ch ) || ! /\w/ . test ( ch ) && ! isCJKContext ( ch ))
break ;
runR ++ ;
}
let bestL = seedL , bestR = seedR , bestToken = seedToken ;
let bestMatched = prefixDict . shouldSuppressSpace ( seedToken , usePrefix );
let bestSpan = bestMatched ? seedR - seedL : - 1 ;
for ( let l = seedL ; l >= runL ; l -- ) {
for ( let r = seedR ; r <= runR ; r ++ ) {
if ( l === seedL && r === seedR )
continue ;
const token = extractToken ( content , l , r );
if ( prefixDict . shouldSuppressSpace ( token , usePrefix )) {
const span = r - l ;
if ( span > bestSpan ) {
bestL = l ;
bestR = r ;
bestToken = token ;
bestMatched = true ;
bestSpan = span ;
}
}
}
}
if ( ! bestMatched ) {
return { left : seedL , right : seedR , token : seedToken };
}
return { left : bestL , right : bestR , token : bestToken };
}
function collectAllBoundaries ( content , languagePairs , customCategories ) {
const positions = /* @__PURE__ */ new Set ();
for ( const pair of languagePairs ) {
const regexps = buildPairRegexps ( pair . a , pair . b , customCategories );
for ( const reg of regexps ) {
reg . lastIndex = 0 ;
while ( true ) {
const match = reg . exec ( content );
if ( ! match )
break ;
positions . add ( reg . lastIndex - 1 );
}
}
}
return positions ;
}
var FORMATTING_CHARS_RE = /[*_~`^]/ ;
function isFormattingChar ( ch ) {
return FORMATTING_CHARS_RE . test ( ch );
}
function collectFormattingSeparatedBoundaries ( content , languagePairs , customCategories ) {
const positions = /* @__PURE__ */ new Set ();
if ( ! FORMATTING_CHARS_RE . test ( content ))
return positions ;
const pairTests = [];
for ( const pair of languagePairs ) {
const classA = resolveCharClass ( pair . a , customCategories );
const classB = resolveCharClass ( pair . b , customCategories );
if ( ! classA || ! classB )
continue ;
const regA = new RegExp ( `^[ ${ classA } ]$` );
const regB = new RegExp ( `^[ ${ classB } ]$` );
pairTests . push ({
test ( a , b ) {
return regA . test ( a ) && regB . test ( b ) || regA . test ( b ) && regB . test ( a );
}
});
}
if ( pairTests . length === 0 )
return positions ;
const len = content . length ;
let i = 0 ;
while ( i < len ) {
if ( ! isFormattingChar ( content [ i ])) {
i ++ ;
continue ;
}
let blockStart = i ;
while ( blockStart > 0 && isFormattingChar ( content [ blockStart - 1 ])) {
blockStart -- ;
}
let blockEnd = i ;
while ( blockEnd < len - 1 && isFormattingChar ( content [ blockEnd + 1 ])) {
blockEnd ++ ;
}
i = blockEnd + 1 ;
let leftIdx = blockStart - 1 ;
while ( leftIdx >= 0 && ( isFormattingChar ( content [ leftIdx ]) || content [ leftIdx ] === "\0" )) {
leftIdx -- ;
}
if ( leftIdx < 0 )
continue ;
let rightIdx = blockEnd + 1 ;
while ( rightIdx < len && ( isFormattingChar ( content [ rightIdx ]) || content [ rightIdx ] === "\0" )) {
rightIdx ++ ;
}
if ( rightIdx >= len )
continue ;
const leftChar = content [ leftIdx ];
const rightChar = content [ rightIdx ];
let pairMatched = false ;
for ( const pt of pairTests ) {
if ( pt . test ( leftChar , rightChar )) {
pairMatched = true ;
break ;
}
}
if ( ! pairMatched )
continue ;
const fmtChar = content [ blockStart ];
let matchedLeftDist = - 1 ;
let matchedRightDist = - 1 ;
for ( let j = blockStart - 1 ; j >= 0 ; j -- ) {
if ( content [ j ] === fmtChar ) {
matchedLeftDist = blockStart - j ;
break ;
}
if ( /[\s\0]/ . test ( content [ j ]))
break ;
}
for ( let j = blockEnd + 1 ; j < len ; j ++ ) {
if ( content [ j ] === fmtChar ) {
matchedRightDist = j - blockEnd ;
break ;
}
if ( /[\s\0]/ . test ( content [ j ]))
break ;
}
if ( matchedLeftDist >= 0 && ( matchedRightDist < 0 || matchedLeftDist <= matchedRightDist )) {
positions . add ( blockEnd + 1 );
} else if ( matchedRightDist >= 0 ) {
positions . add ( blockStart );
} else {
if ( isCJKContext ( leftChar ))
positions . add ( blockStart );
if ( isCJKContext ( rightChar ))
positions . add ( blockEnd + 1 );
}
}
return positions ;
}
function applyLanguagePairSpacing ( ctx , languagePairs , prefixDict , customCategories , debug ) {
let { content , curCh , prevCh , offset } = ctx ;
if ( ! isParamDefined ( prevCh ))
return ctx ;
const cursorInContent = curCh - offset ;
const allBoundaries = collectAllBoundaries ( content , languagePairs , customCategories );
const fmtBoundaries = collectFormattingSeparatedBoundaries ( content , languagePairs , customCategories );
for ( const pos of fmtBoundaries ) {
allBoundaries . add ( pos );
}
if ( allBoundaries . size === 0 )
return ctx ;
let [ tokLeft , tokRight ] = findTokenBounds ( content , cursorInContent );
let cursorToken = extractToken ( content , tokLeft , tokRight );
let tokenIsFinalized = false ;
if ( cursorToken . length === 0 && cursorInContent > 0 ) {
let searchPos = cursorInContent - 1 ;
while ( searchPos >= 0 && /[\s\0]/ . test ( content . charAt ( searchPos ))) {
searchPos -- ;
}
if ( searchPos >= 0 ) {
[ tokLeft , tokRight ] = findTokenBounds ( content , searchPos );
cursorToken = extractToken ( content , tokLeft , tokRight );
tokenIsFinalized = true ;
}
}
const isActivelyTyping = curCh !== prevCh ;
const usePrefix = isActivelyTyping && ! tokenIsFinalized ;
const extended = extendCursorTokenForDict ( content , tokLeft , tokRight , prefixDict , usePrefix );
let tokLeftExt = extended . left ;
let tokRightExt = extended . right ;
let cursorTokenExt = extended . token ;
const cursorTokenSuppressed = prefixDict . shouldSuppressSpace ( cursorTokenExt , usePrefix );
let protectedUpTo = - 1 ;
if ( cursorTokenSuppressed ) {
protectedUpTo = cursorTokenExt . length ;
} else {
const matchLen = prefixDict . findLongestMatchFromStart ( cursorTokenExt );
if ( matchLen > 0 && matchLen < cursorTokenExt . length ) {
const lastCharOfMatch = cursorTokenExt . charAt ( matchLen - 1 );
const firstCharAfterMatch = cursorTokenExt . charAt ( matchLen );
if ( classifyChar ( lastCharOfMatch ) !== classifyChar ( firstCharAfterMatch )) {
protectedUpTo = matchLen ;
}
}
}
if ( debug ) {
console . log ( "[LangPairSpacing] content:" , JSON . stringify ( content ), "curCh:" , curCh , "prevCh:" , prevCh , "offset:" , offset , "cursorInContent:" , cursorInContent , "boundaries:" , Array . from ( allBoundaries ), "tokenBounds:" , [ tokLeft , tokRight ], "cursorToken:" , JSON . stringify ( cursorToken ), "tokenBoundsExt:" , [ tokLeftExt , tokRightExt ], "cursorTokenExt:" , JSON . stringify ( cursorTokenExt ), "suppressed:" , cursorTokenSuppressed , "protectedUpTo:" , protectedUpTo );
}
const toInsert = [];
const prevChInContent = prevCh - offset ;
let prefixDictExpired = false ;
if ( ! cursorTokenSuppressed ) {
if ( isActivelyTyping && prevChInContent > tokLeftExt ) {
const prevToken = cursorTokenExt . substring ( 0 , prevChInContent - tokLeftExt );
prefixDictExpired = prefixDict . shouldSuppressSpace ( prevToken , true );
} else if ( ! isActivelyTyping || tokenIsFinalized ) {
prefixDictExpired = prefixDict . shouldSuppressSpace ( cursorTokenExt , true );
}
}
for ( const pos of allBoundaries ) {
const inCursorToken = pos >= tokLeftExt && pos < tokRightExt ;
if ( inCursorToken ) {
const posInToken = pos - tokLeftExt ;
if ( posInToken > 0 && posInToken < protectedUpTo ) {
continue ;
}
if ( pos >= prevChInContent && pos < cursorInContent || prefixDictExpired ) {
toInsert . push ( pos );
}
} else {
if ( pos >= prevChInContent && pos < cursorInContent ) {
const [ seedL , seedR ] = findTokenBounds ( content , pos );
const ext = extendCursorTokenForDict ( content , seedL , seedR , prefixDict , false );
if ( ! prefixDict . shouldSuppressSpace ( ext . token , false )) {
toInsert . push ( pos );
}
}
}
}
if ( toInsert . length === 0 )
return ctx ;
toInsert . sort (( a , b ) => a - b );
for ( let i = toInsert . length - 1 ; i >= 0 ; i -- ) {
content = content . substring ( 0 , toInsert [ i ]) + " " + content . substring ( toInsert [ i ]);
}
let shift = 0 ;
for ( const pos of toInsert ) {
if ( pos < cursorInContent )
shift ++ ;
}
curCh += shift ;
return { ... ctx , content , curCh };
}
function detectBoundarySpaceState ( content , leftSymbols , rightSymbols ) {
const builtInBothSymbols = `"'` ;
const builtInLeftSoftSymbols = `\u3010\u3011\uFF08\uFF09\u300A\u300B\uFF0C\u3002\u3001\uFF1F\uFF1A\uFF1B\u2018\u2019\u201C\u201D\u300C\u300E\u300F\u300D\uFF01 ${ builtInBothSymbols } [({` ;
const builtInRightSoftSymbols = `\u3010\u3011\uFF08\uFF09\u300A\u300B\uFF0C\u3002\u3001\uFF1F\uFF1A\uFF1B\u2018\u2019\u201C\u201D\u300C\u300E\u300F\u300D\uFF01 ${ builtInBothSymbols } ,.?!:;])}` ;
const escapedStart = escapeForCharClass ( rightSymbols + builtInRightSoftSymbols );
const escapedEnd = escapeForCharClass ( leftSymbols + builtInLeftSoftSymbols );
const regStrictSpaceStart = /^\0?\s/ ;
const regStrictSpaceEnd = /\s\0?$/ ;
const regStartWithSpace = new RegExp ( `^\\0?[\\s ${ escapedStart } ]` );
const regEndWithSpace = new RegExp ( `[\\s ${ escapedEnd } ]\\0?$` );
let start = 0 /* none */ ;
let end = 0 /* none */ ;
if ( regStartWithSpace . test ( content ) || content . startsWith ( "<br>" )) {
start = regStrictSpaceStart . test ( content ) ? 2 /* strict */ : 1 /* soft */ ;
}
if ( regEndWithSpace . test ( content ) || content . endsWith ( "<br>" )) {
end = regStrictSpaceEnd . test ( content ) ? 2 /* strict */ : 1 /* soft */ ;
}
return { start , end };
}
function escapeForCharClass ( symbols ) {
return symbols . replace ( /[\\\]^-]/g , "\\$&" );
}
// src/formatting/inline_spacing.ts
function shouldInsertSpaceBetweenParts ( prevType , curType , prevTextEndSpaceState , prevPartRightSpaceRequire , curPartLeftSpaceRequire , settings ) {
if ( prevType === "none" /* none */ )
return false ;
const modeOf = ( type ) => {
switch ( type ) {
case "code" /* code */ :
return settings . InlineCodeSpaceMode ;
case "formula" /* formula */ :
return settings . InlineFormulaSpaceMode ;
case "wikilink" /* wikilink */ :
case "mdlink" /* mdlink */ :
return settings . InlineLinkSpaceMode ;
default :
return 0 /* none */ ;
}
};
if ( prevType === "text" /* text */ ) {
if ( curType === "user-defined" /* user */ ) {
return curPartLeftSpaceRequire > prevTextEndSpaceState ;
}
const curMode2 = modeOf ( curType );
return curMode2 > prevTextEndSpaceState ;
}
if ( prevType === "user-defined" /* user */ ) {
if ( curType === "text" /* text */ ) {
return prevPartRightSpaceRequire > 0 /* none */ ;
}
if ( curType === "user-defined" /* user */ ) {
return curPartLeftSpaceRequire > 0 /* none */ && prevPartRightSpaceRequire > 0 /* none */ ;
}
const curMode2 = modeOf ( curType );
return curMode2 > 0 /* none */ && prevPartRightSpaceRequire > 0 /* none */ ;
}
const prevMode = modeOf ( prevType );
const curMode = modeOf ( curType );
if ( curType === "user-defined" /* user */ ) {
return prevMode > 0 /* none */ && curPartLeftSpaceRequire > 0 /* none */ ;
}
return prevMode > 0 /* none */ || curMode > 0 /* none */ ;
}
function shouldPrependSpaceToText ( prevType , txtStartSpaceState , prevPartRightSpaceRequire , settings ) {
switch ( prevType ) {
case "none" /* none */ :
return false ;
case "code" /* code */ :
return settings . InlineCodeSpaceMode > txtStartSpaceState ;
case "formula" /* formula */ :
return settings . InlineFormulaSpaceMode > txtStartSpaceState ;
case "wikilink" /* wikilink */ :
case "mdlink" /* mdlink */ :
if ( ! settings . InlineLinkSmartSpace ) {
return settings . InlineLinkSpaceMode > txtStartSpaceState ;
}
return false ;
case "user-defined" /* user */ :
return prevPartRightSpaceRequire > txtStartSpaceState ;
default :
return false ;
}
}
// src/formatting/prefix_dictionary.ts
var PrefixDictionary = class {
constructor ( raw ) {
this . literalWords = [];
this . regexEntries = [];
if ( ! raw || raw . trim () === "" )
return ;
const tokenPattern = /\/(?:[^/\\]|\\.)+\/[gimsuy]*|[^\s,]+/g ;
let match ;
while (( match = tokenPattern . exec ( raw )) !== null ) {
const token = match [ 0 ];
const regexMatch = /^\/(.+)\/([gimsuy]*)$/ . exec ( token );
if ( regexMatch ) {
try {
this . regexEntries . push ( new RegExp ( regexMatch [ 1 ], regexMatch [ 2 ]));
} catch ( e ) {
console . warn ( "PrefixDictionary: invalid regex:" , token , e );
}
} else {
this . literalWords . push ( token );
}
}
}
isExactMatch ( token ) {
for ( const word of this . literalWords ) {
if ( word === token )
return true ;
}
for ( const re of this . regexEntries ) {
re . lastIndex = 0 ;
const anchored = new RegExp ( `^(?: ${ re . source } )$` , re . flags );
if ( anchored . test ( token ))
return true ;
}
return false ;
}
isPrefixOfWord ( token ) {
if ( token . length === 0 )
return false ;
for ( const word of this . literalWords ) {
if ( word . length > token . length && word . startsWith ( token )) {
return true ;
}
}
return false ;
}
shouldSuppressSpace ( token , isAtCursor ) {
if ( this . isExactMatch ( token ))
return true ;
if ( isAtCursor && this . isPrefixOfWord ( token ))
return true ;
return false ;
}
findLongestMatchFromStart ( token ) {
let maxLen = - 1 ;
for ( const word of this . literalWords ) {
if ( token . startsWith ( word ) && word . length > maxLen ) {
maxLen = word . length ;
}
}
for ( const re of this . regexEntries ) {
const anchored = new RegExp ( `^(?: ${ re . source } )` , re . flags . replace ( "g" , "" ));
const match = anchored . exec ( token );
if ( match && match [ 0 ]. length > maxLen ) {
maxLen = match [ 0 ]. length ;
}
}
return maxLen ;
}
};
// src/core.ts
2026-01-05 13:03:55 +08:00
var LineFormater = class {
constructor () {
}
syntaxTreeNodeNameType ( name ) {
if ( name . contains ( "code" ) && ! name . contains ( "link" )) {
return "code" /* code */ ;
} else if ( name . contains ( "math" )) {
return "formula" /* formula */ ;
} else {
return "text" /* text */ ;
}
}
parseLineWithSyntaxTree ( state , lineNum , regRegExp ) {
let linePartsOfTxtCodeFormula = [];
let line = state . doc . line ( lineNum );
const tree = ( 0 , import_language . syntaxTree )( state );
let pos = line . from ;
let prevNodeType = "none" /* none */ ;
let prevBeginIdx = 0 ;
while ( pos < line . to ) {
let node = tree . resolve ( pos , 1 );
let curNodeType = this . syntaxTreeNodeNameType ( node . name );
if ( prevNodeType == "none" /* none */ ) {
prevNodeType = curNodeType ;
prevBeginIdx = 0 ;
} else if ( prevNodeType == curNodeType ) {
} else {
linePartsOfTxtCodeFormula . push ({
content : line . text . substring ( prevBeginIdx , pos - line . from ),
type : prevNodeType ,
begin : prevBeginIdx ,
end : pos - line . from ,
leftSpaceRequire : 0 /* none */ ,
rightSpaceRequire : 0 /* none */
});
prevNodeType = curNodeType ;
prevBeginIdx = pos - line . from ;
}
if ( curNodeType == "text" /* text */ ) {
pos ++ ;
} else {
pos = node . to ;
}
if ( pos == line . to ) {
linePartsOfTxtCodeFormula . push ({
content : line . text . substring ( prevBeginIdx , pos - line . from ),
type : prevNodeType ,
begin : prevBeginIdx ,
end : pos - line . from ,
leftSpaceRequire : 0 /* none */ ,
rightSpaceRequire : 0 /* none */
});
}
}
let retArray = [];
for ( let i = 0 ; i < linePartsOfTxtCodeFormula . length ; i ++ ) {
if ( linePartsOfTxtCodeFormula [ i ]. type != "text" /* text */ ) {
retArray . push ( linePartsOfTxtCodeFormula [ i ]);
} else {
let tempArray ;
if ( isParamDefined ( regRegExp ))
tempArray = splitTextWithLinkAndUserDefined ( linePartsOfTxtCodeFormula [ i ]. content , regRegExp );
else
tempArray = splitTextWithLinkAndUserDefined ( linePartsOfTxtCodeFormula [ i ]. content );
tempArray . forEach (( item ) => {
item . begin += linePartsOfTxtCodeFormula [ i ]. begin ;
item . end += linePartsOfTxtCodeFormula [ i ]. begin ;
retArray . push ( item );
});
}
}
return retArray ;
}
formatLineOfDoc ( state , settings , fromB , toB , insertedStr ) {
let doc = state . doc ;
let line = doc . lineAt ( fromB ). text ;
let res = null ;
if ( insertedStr . contains ( "\n" )) {
res = this . formatLine ( state , doc . lineAt ( fromB ). number , settings , offsetToPos ( doc , fromB ). ch , offsetToPos ( doc , fromB ). ch );
} else {
res = this . formatLine ( state , doc . lineAt ( fromB ). number , settings , offsetToPos ( doc , toB ). ch , offsetToPos ( doc , fromB ). ch );
}
if ( res === null || res [ 2 ]. length == 0 )
return null ;
let newline = stringInsertAt ( res [ 0 ], res [ 1 ], "|" );
let changes = [];
let offset = doc . lineAt ( fromB ). from ;
for ( let changeItem of res [ 2 ]) {
changes . push ({
changes : { from : offset + changeItem . begin , to : offset + changeItem . end , insert : changeItem . text },
userEvent : "EasyTyping.change"
});
}
if ( insertedStr . contains ( "\n" )) {
2026-08-21 15:44:03 +08:00
print ( "insertStr" , insertedStr );
2026-01-05 13:03:55 +08:00
res [ 1 ] += insertedStr . length ;
}
return [ changes , { selection : { anchor : offset + res [ 1 ] }, userEvent : "EasyTyping.change" }];
}
formatLine ( state , lineNum , settings , curCh , prevCh ) {
let line = state . doc . line ( lineNum ). text ;
let regNull = /^\s*$/g ;
if ( regNull . test ( line ))
return [ line , curCh , []];
let lineParts = settings . UserDefinedRegSwitch ? this . parseLineWithSyntaxTree ( state , lineNum , settings . UserDefinedRegExp ) : this . parseLineWithSyntaxTree ( state , lineNum );
if ( settings . debug )
console . log ( "line parts\n" , lineParts );
let linePartsOrigin = JSON . parse ( JSON . stringify ( lineParts ));
let inlineChangeList = [];
let cursorLinePartIndex = - 1 ;
let cursorRelativeIndex = - 1 ;
let resultCursorCh = 0 ;
for ( let i = 0 ; i < lineParts . length ; i ++ ) {
if ( curCh > lineParts [ i ]. begin && curCh <= lineParts [ i ]. end ) {
cursorLinePartIndex = i ;
cursorRelativeIndex = curCh - lineParts [ i ]. begin ;
if ( lineParts [ i ]. type === "text" /* text */ ) {
lineParts [ i ]. content = stringInsertAt ( lineParts [ i ]. content , cursorRelativeIndex , "\0" );
}
break ;
}
}
2026-08-21 15:44:03 +08:00
const prefixDict = new PrefixDictionary ( settings . PrefixDictionary );
2026-01-05 13:03:55 +08:00
let resultLine = "" ;
let offset = 0 ;
let prevPartType = "none" /* none */ ;
let prevTextEndSpaceState = 0 /* none */ ;
for ( let i = 0 ; i < lineParts . length ; i ++ ) {
2026-08-21 15:44:03 +08:00
if ( lineParts [ i ]. type === "text" /* text */ ) {
let content = lineParts [ i ]. content ;
let ctx = { content , curCh , prevCh , offset };
if ( settings . AutoCapital ) {
if ( i === 0 ) {
ctx = capitalizeFirstLetter ( ctx , true , cursorLinePartIndex === 0 );
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
ctx = capitalizeMidSentence ( ctx );
content = ctx . content ;
curCh = ctx . curCh ;
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
if ( settings . languagePairs && settings . languagePairs . length > 0 ) {
ctx = { ... ctx , content , curCh };
ctx = applyLanguagePairSpacing ( ctx , settings . languagePairs , prefixDict , settings . customScriptCategories , settings . debug );
content = ctx . content ;
curCh = ctx . curCh ;
}
lineParts [ i ]. content = content ;
const boundary = detectBoundarySpaceState ( content , settings . SoftSpaceLeftSymbols || "" , settings . SoftSpaceRightSymbols || "" );
if ( prevPartType !== "none" /* none */ ) {
if ( prevPartType === "wikilink" /* wikilink */ || prevPartType === "mdlink" /* mdlink */ ) {
if ( ! settings . InlineLinkSmartSpace && settings . InlineLinkSpaceMode > boundary . start ) {
lineParts [ i ]. content = " " + lineParts [ i ]. content ;
2026-01-05 13:03:55 +08:00
content = lineParts [ i ]. content ;
2026-08-21 15:44:03 +08:00
} else if ( settings . InlineLinkSmartSpace && boundary . start === 0 /* none */ ) {
const charAtTextBegin = content . charAt ( 0 ) === "\0" ? content . charAt ( 1 ) : content . charAt ( 0 );
const regMdLinkEnd = /\]/ ;
const charAtLinkEndIndex = lineParts [ i - 1 ]. content . search ( regMdLinkEnd ) - 1 ;
const charAtLinkEnd = lineParts [ i - 1 ]. content . charAt ( charAtLinkEndIndex );
if ( charAtLinkEnd !== "[" ) {
const twoNeighborChars = charAtLinkEnd + charAtTextBegin ;
const regNotNeedSpace = /[\u4e00-\u9fa5,。?:;""''\-) }][\u4e00-\u9fa5]/g ;
2026-01-05 13:03:55 +08:00
if ( ! regNotNeedSpace . test ( twoNeighborChars )) {
2026-08-21 15:44:03 +08:00
lineParts [ i ]. content = " " + lineParts [ i ]. content ;
2026-01-05 13:03:55 +08:00
content = lineParts [ i ]. content ;
}
}
2026-08-21 15:44:03 +08:00
}
} else if ( shouldPrependSpaceToText ( prevPartType , boundary . start , i > 0 ? lineParts [ i - 1 ]. rightSpaceRequire : 0 /* none */ , settings )) {
lineParts [ i ]. content = " " + lineParts [ i ]. content ;
content = lineParts [ i ]. content ;
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
}
if ( i === cursorLinePartIndex ) {
const n = content . search ( "\0" );
resultCursorCh = offset + n ;
lineParts [ i ]. content = stringDeleteAt ( content , n );
}
resultLine += lineParts [ i ]. content ;
offset += lineParts [ i ]. content . length ;
prevPartType = "text" /* text */ ;
prevTextEndSpaceState = boundary . end ;
} else {
if ( lineParts [ i ]. type === "formula" /* formula */ && lineParts [ i ]. content === "$\\qquad$" ) {
2026-01-05 13:03:55 +08:00
prevPartType = "text" /* text */ ;
2026-08-21 15:44:03 +08:00
prevTextEndSpaceState = 2 /* strict */ ;
2026-01-05 13:03:55 +08:00
resultLine += lineParts [ i ]. content ;
offset += lineParts [ i ]. content . length ;
2026-08-21 15:44:03 +08:00
continue ;
}
if (( lineParts [ i ]. type === "wikilink" /* wikilink */ || lineParts [ i ]. type === "mdlink" /* mdlink */ ) && prevPartType === "text" /* text */ ) {
const prevEnd = prevTextEndSpaceState ;
if ( prevEnd >= settings . InlineLinkSpaceMode && ! settings . InlineLinkSmartSpace ) {
} else if ( prevEnd === 2 /* strict */ && settings . InlineLinkSpaceMode === 2 /* strict */ ) {
} else if ( settings . InlineLinkSpaceMode === 2 /* strict */ && prevEnd < 2 /* strict */ ) {
lineParts [ i - 1 ]. content += " " ;
resultLine += " " ;
offset += 1 ;
} else if ( settings . InlineLinkSmartSpace && lineParts [ i - 1 ]. content . endsWith ( " " )) {
let charAtLinkBegin = this . getLinkBeginChar ( lineParts [ i ]);
if ( charAtLinkBegin ) {
const tempContent = lineParts [ i - 1 ]. content + charAtLinkBegin ;
const regRevertSpace = /[\u4e00-\u9fa5] [\u4e00-\u9fa5]$/ ;
if ( regRevertSpace . test ( tempContent )) {
lineParts [ i - 1 ]. content = lineParts [ i - 1 ]. content . substring ( 0 , lineParts [ i - 1 ]. content . length - 1 );
resultLine = resultLine . substring ( 0 , resultLine . length - 1 );
offset -= 1 ;
}
}
} else if ( settings . InlineLinkSmartSpace && prevEnd === 0 /* none */ ) {
const charAtTextEnd = lineParts [ i - 1 ]. content . charAt ( lineParts [ i - 1 ]. content . length - 1 );
const charAtLinkBegin = this . getLinkBeginChar ( lineParts [ i ]);
if ( charAtLinkBegin ) {
const regNoNeedSpace = /[\u4e00-\u9fa5][\u4e00-\u9fa5]/g ;
const twoNeighborChars = charAtTextEnd + charAtLinkBegin ;
if ( ! regNoNeedSpace . test ( twoNeighborChars )) {
2026-01-05 13:03:55 +08:00
lineParts [ i - 1 ]. content += " " ;
resultLine += " " ;
offset += 1 ;
}
2026-08-21 15:44:03 +08:00
}
} else if ( ! settings . InlineLinkSmartSpace && settings . InlineLinkSpaceMode > prevEnd ) {
lineParts [ i - 1 ]. content += " " ;
resultLine += " " ;
offset += 1 ;
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
} else if ( prevPartType === "text" /* text */ ) {
if ( shouldInsertSpaceBetweenParts ( "text" /* text */ , lineParts [ i ]. type , prevTextEndSpaceState , i > 0 ? lineParts [ i - 1 ]. rightSpaceRequire : 0 /* none */ , lineParts [ i ]. leftSpaceRequire , settings )) {
lineParts [ i - 1 ]. content += " " ;
resultLine += " " ;
offset += 1 ;
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
} else if ( prevPartType !== "none" /* none */ ) {
if ( shouldInsertSpaceBetweenParts ( prevPartType , lineParts [ i ]. type , prevTextEndSpaceState , i > 0 ? lineParts [ i - 1 ]. rightSpaceRequire : 0 /* none */ , lineParts [ i ]. leftSpaceRequire , settings )) {
inlineChangeList . push ({
text : " " ,
begin : lineParts [ i ]. begin ,
end : lineParts [ i ]. begin ,
origin : ""
});
resultLine += " " ;
offset += 1 ;
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
}
if ( i === cursorLinePartIndex ) {
resultCursorCh = offset + cursorRelativeIndex ;
}
resultLine += lineParts [ i ]. content ;
offset += lineParts [ i ]. content . length ;
prevPartType = lineParts [ i ]. type ;
prevTextEndSpaceState = 0 /* none */ ;
2026-01-05 13:03:55 +08:00
}
}
for ( let i = 0 ; i < lineParts . length ; i ++ ) {
if ( lineParts [ i ]. type === "text" /* text */ && lineParts [ i ]. content != linePartsOrigin [ i ]. content ) {
inlineChangeList . push ({
text : lineParts [ i ]. content ,
begin : linePartsOrigin [ i ]. begin ,
end : linePartsOrigin [ i ]. end ,
origin : linePartsOrigin [ i ]. content
});
}
}
inlineChangeList = inlineChangeList . sort (( a , b ) => a . begin - b . begin );
return [ resultLine , resultCursorCh , inlineChangeList ];
}
2026-08-21 15:44:03 +08:00
getLinkBeginChar ( part ) {
if ( part . type === "wikilink" /* wikilink */ ) {
const regAlias = /\|/ ;
const charOfAliasBegin = part . content . search ( regAlias );
let beginIndex = 2 ;
if ( part . content . charAt ( 0 ) === "!" )
beginIndex = 3 ;
if ( charOfAliasBegin !== - 1 ) {
beginIndex = charOfAliasBegin + 1 ;
} else if ( part . content . charAt ( beginIndex ) === "#" ) {
beginIndex += 1 ;
}
const ch = part . content . charAt ( beginIndex );
return ch === "]" ? null : ch ;
} else {
const regMdLinkBegin = /\[/ ;
const charAtLinkBeginIndex = part . content . search ( regMdLinkBegin ) + 1 ;
const ch = part . content . charAt ( charAtLinkBeginIndex );
return ch === "]" ? null : ch ;
}
}
2026-01-05 13:03:55 +08:00
};
function matchWithReg ( text , regExp , type , inlineTypeArray , checkArray = false , leftSpaceRe = 0 /* none */ , rightSpaceRe = 0 /* none */ ) {
let retArray = inlineTypeArray ;
let matchArray = [];
retArray = retArray . sort (( a , b ) => a . begin - b . begin );
while ( true ) {
let match = regExp . exec ( text );
if ( ! match )
break ;
let valid = true ;
if ( checkArray ) {
for ( let i = 0 ; i < retArray . length ; i ++ ) {
if ( regExp . lastIndex > retArray [ i ]. begin && retArray [ i ]. end > match . index ) {
valid = false ;
break ;
}
}
}
if ( ! valid )
continue ;
matchArray . push ({
content : match [ 0 ],
type ,
begin : match . index ,
end : regExp . lastIndex ,
leftSpaceRequire : leftSpaceRe ,
rightSpaceRequire : rightSpaceRe
});
}
retArray = retArray . concat ( matchArray );
return retArray ;
}
function splitTextWithLinkAndUserDefined ( text , regExps ) {
let retArray = [];
let regWikiLink = /\!{0,2}\[\[[^\[\]]*?\]\]/g ;
let regMdLink = /\!{0,2}\[[^\[\]]*?\]\([^\s]*\)/g ;
retArray = matchWithReg ( text , regWikiLink , "wikilink" /* wikilink */ , retArray );
retArray = matchWithReg ( text , regMdLink , "mdlink" /* mdlink */ , retArray );
let regExpList = [];
let leftSRequireList = [];
let rightSRequireList = [];
let regNull = /^\s*$|^\/\//g ;
let regSRequire = /\|[\-=\+][\-=\+]$/ ;
if ( regExps ) {
let regs = regExps . split ( "\n" );
for ( let i = 0 ; i < regs . length ; i ++ ) {
if ( regNull . test ( regs [ i ]))
continue ;
if ( ! regSRequire . test ( regs [ i ]) || regs [ i ]. length <= 3 ) {
new import_obsidian . Notice ( "EasyTyping: \u7B2C" + String ( i ) + "\u884C\u81EA\u5B9A\u4E49\u6B63\u5219\u4E0D\u7B26\u5408\u89C4\u8303\n" + regs [ i ]);
continue ;
}
let regItem = regs [ i ]. substring ( 0 , regs [ i ]. length - 3 );
let spaceReqString = regs [ i ]. substring ( regs [ i ]. length - 3 );
let isValidReg = true ;
try {
let regTemp = new RegExp ( regItem , "g" );
} catch ( error ) {
isValidReg = false ;
console . error ( "EasyTyping: Invalid RegExp:" , regItem , error );
}
if ( isValidReg ) {
regExpList . push ( new RegExp ( regItem , "g" ));
leftSRequireList . push ( str2SpaceState ( spaceReqString . charAt ( 1 )));
rightSRequireList . push ( str2SpaceState ( spaceReqString . charAt ( 2 )));
}
}
let regLen = regExpList . length ;
for ( let i = 0 ; i < regLen ; i ++ ) {
retArray = matchWithReg ( text , regExpList [ i ], "user-defined" /* user */ , retArray , true , leftSRequireList [ i ], rightSRequireList [ i ]);
}
}
retArray = retArray . sort (( a , b ) => a . begin - b . begin );
let textArray = [];
let textBegin = 0 ;
let textEnd = 0 ;
for ( let i = 0 ; i < retArray . length ; i ++ ) {
if ( textBegin < retArray [ i ]. begin ) {
textEnd = retArray [ i ]. begin ;
textArray . push ({
content : text . substring ( textBegin , textEnd ),
type : "text" /* text */ ,
begin : textBegin ,
end : textEnd ,
leftSpaceRequire : 0 /* none */ ,
rightSpaceRequire : 0 /* none */
});
}
textBegin = retArray [ i ]. end ;
}
if ( textBegin != text . length ) {
textArray . push ({
content : text . substring ( textBegin , text . length ),
type : "text" /* text */ ,
begin : textBegin ,
end : text . length ,
leftSpaceRequire : 0 /* none */ ,
rightSpaceRequire : 0 /* none */
});
}
retArray = retArray . concat ( textArray );
retArray = retArray . sort (( a , b ) => a . begin - b . begin );
return retArray ;
}
2026-08-21 15:44:03 +08:00
function isCursorInUserDefinedRegexBlock ( lineText , column , regExps ) {
const parts = splitTextWithLinkAndUserDefined ( lineText , regExps );
for ( const part of parts ) {
if ( part . type === "user-defined" /* user */ && column >= part . begin && column < part . end ) {
return true ;
}
}
return false ;
}
2026-01-05 13:03:55 +08:00
function str2SpaceState ( s ) {
switch ( s ) {
case "+" :
return 2 /* strict */ ;
case "=" :
return 1 /* soft */ ;
case "-" :
default :
return 0 /* none */ ;
}
}
function string2SpaceState ( s ) {
if ( Number ( s ) == 0 /* none */ )
return 0 /* none */ ;
if ( Number ( s ) == 1 /* soft */ )
return 1 /* soft */ ;
if ( Number ( s ) == 2 /* strict */ )
return 2 /* strict */ ;
return 0 /* none */ ;
}
function getPosLineType ( state , pos ) {
const line = state . doc . lineAt ( pos );
let line_number = line . number ;
const tree = ( 0 , import_language . ensureSyntaxTree )( state , line . to );
2026-08-21 15:44:03 +08:00
if ( ! tree )
return "text" /* text */ ;
2026-01-05 13:03:55 +08:00
const token = tree . resolve ( line . from , 1 ). name ;
if ( token . contains ( "table" )) {
return "table" /* table */ ;
}
if ( token . contains ( "hmd-frontmatter" )) {
return "frontmatter" /* frontmatter */ ;
}
if ( token . contains ( "math" )) {
for ( let p = line . from + 1 ; p < line . to ; p += 1 ) {
if ( ! tree . resolve ( p , 1 ). name . contains ( "math" )) {
return "text" /* text */ ;
}
}
return "formula" /* formula */ ;
} else if ( token . contains ( "code" ) && token . contains ( "block" )) {
for ( let p = line . from + 1 ; p < line . to ; p += 1 ) {
let t = tree . resolve ( p , 1 ). name ;
if ( ! ( t . contains ( "code" ) && t . contains ( "block" ))) {
return "text" /* text */ ;
}
}
return "codeblock" /* codeblock */ ;
} else if ( token . contains ( "quote" ) && ! token . contains ( "callout" )) {
let callout_start_line = - 1 ;
for ( let l = line_number - 1 ; l >= 1 ; l -= 1 ) {
let l_line = state . doc . line ( l );
let l_token = tree . resolve ( l_line . from , 1 ). name ;
if ( ! l_token . contains ( "quote" )) {
break ;
}
if ( l_token . contains ( "callout" )) {
callout_start_line = l ;
break ;
}
}
if ( callout_start_line == - 1 )
return "text" /* text */ ;
let is_code_block = false ;
let reset = false ;
let reg_code_begin = /^>+ ```/ ;
let reg_code_end = /^>+ ```$/ ;
for ( let l = callout_start_line + 1 ; l <= line_number ; l += 1 ) {
let l_line = state . doc . line ( l );
if ( reset ) {
is_code_block = false ;
reset = false ;
}
if ( is_code_block && reg_code_end . test ( l_line . text )) {
is_code_block = true ;
reset = true ;
} else if ( ! is_code_block && reg_code_begin . test ( l_line . text )) {
is_code_block = true ;
}
}
if ( is_code_block ) {
return "codeblock" /* codeblock */ ;
} else
return "text" /* text */ ;
} else if ( token . contains ( "list" )) {
for ( let p = line . from + 1 ; p < line . to ; p += 1 ) {
let t = tree . resolve ( p , 1 ). name ;
if ( t . contains ( "code" ) && t . contains ( "block" )) {
return "codeblock" /* codeblock */ ;
}
}
}
return "text" /* text */ ;
}
function getPosLineType2 ( state , pos ) {
const line = state . doc . lineAt ( pos );
const tree = ( 0 , import_language . syntaxTree )( state );
const token = tree . resolve ( line . from , 1 ). name ;
if ( token . contains ( "hmd-frontmatter" )) {
return "frontmatter" /* frontmatter */ ;
}
if ( token . contains ( "math" )) {
for ( let p = line . from + 1 ; p < line . to ; p += 1 ) {
if ( ! tree . resolve ( p , 1 ). name . contains ( "math" )) {
return "text" /* text */ ;
}
}
return "formula" /* formula */ ;
} else if ( token . contains ( "code" ) && token . contains ( "block" )) {
for ( let p = line . from + 1 ; p < line . to ; p += 1 ) {
let t = tree . resolve ( p , 1 ). name ;
if ( ! ( t . contains ( "code" ) && t . contains ( "block" ))) {
return "text" /* text */ ;
}
}
return "codeblock" /* codeblock */ ;
}
for ( let p = line . from ; p < line . to ; p += 1 ) {
if ( tree . resolve ( p , 1 ). name . contains ( "list" )) {
return "list" /* list */ ;
} else if ( tree . resolve ( p , 1 ). name . contains ( "callout" )) {
return "callout_title" /* callout_title */ ;
}
}
if ( token . contains ( "quote" )) {
return "quote" /* quote */ ;
}
return "text" /* text */ ;
}
2026-08-21 15:44:03 +08:00
// src/settings/settings_types.ts
var DEFAULT_SETTINGS = {
Tabout : true ,
SmartPaste : true ,
BetterCodeEdit : true ,
BetterBackspace : true ,
AutoFormat : true ,
AutoFormatPaste : true ,
ExcludeFiles : "" ,
AutoCapital : false ,
languagePairs : [
{ a : "chinese" /* Chinese */ , b : "english" /* English */ },
{ a : "chinese" /* Chinese */ , b : "digit" /* Digit */ },
{ a : "digit" /* Digit */ , b : "english" /* English */ }
],
PrefixDictionary : "n8n, /[1234][dD]/\npython3, Python3" ,
SoftSpaceLeftSymbols : "-" ,
SoftSpaceRightSymbols : "-" ,
customScriptCategories : [],
InlineCodeSpaceMode : 1 /* soft */ ,
InlineFormulaSpaceMode : 1 /* soft */ ,
InlineLinkSpaceMode : 1 /* soft */ ,
InlineLinkSmartSpace : true ,
UserDefinedRegSwitch : true ,
UserDefinedRegExp : "{{.*?}}|++\n<.*?>|--\n\\[\\!.*?\\][-+]{0,1}|-+\n(file:///|https?://|ftp://|obsidian://|zotero://|www.)[^\\s\uFF08\uFF09\u300A\u300B\u3002,\uFF0C\uFF01\uFF1F;\uFF1B\uFF1A\u201C\u201D\u2018\u2019\\)\\(\\[\\]\\{\\}']+|--\n\n[a-zA-Z0-9_\\-.]+@[a-zA-Z0-9_\\-.]+|++\n// Tags in Obsidian//(?<!#)#[\\u4e00-\\u9fa5\\w-\\/]+|++" ,
UserRulesRespectUserDefinedRegexBlocks : false ,
debug : false ,
StrictModeEnter : false ,
StrictLineMode : "enter_twice" /* EnterTwice */ ,
EnhanceModA : false ,
TryFixChineseIM : true ,
FixMacOSContextMenu : false ,
TryFixMSIME : false ,
CollapsePersistentEnter : false ,
deletedBuiltinRuleIds : [],
rulesStoragePath : ""
};
// src/settings/easy_typing_settings_tab.ts
var import_obsidian5 = require ( "obsidian" );
// src/lang/locale/index.ts
2026-01-05 13:03:55 +08:00
var import_obsidian2 = require ( "obsidian" );
// src/lang/locale/en-US.ts
var locale = {
settings : {
2026-08-21 15:44:03 +08:00
smartPaste : {
name : "Smart Paste in Lists & Quotes" ,
desc : "In lists or quote blocks, paste content automatically with proper indentation and list/quote markers."
2026-01-05 13:03:55 +08:00
},
codeblockEdit : {
2026-08-21 15:44:03 +08:00
name : "Enhance Codeblock Edit" ,
2026-01-05 13:03:55 +08:00
desc : "Improve editing in codeblocks (Tab, delete, paste, Cmd/Ctrl+A select)."
},
backspaceEdit : {
2026-08-21 15:44:03 +08:00
name : "Smart Backspace" ,
desc : "Improve backspace feature for empty list item or empty quote line."
2026-01-05 13:03:55 +08:00
},
tabOut : {
2026-08-21 15:44:03 +08:00
name : "Tab Out of Paired Symbols" ,
desc : "Press Tab to move cursor outside paired symbols like \u3010\u3011, \uFF08\uFF09, \u300A\u300B, quotes, or inline code."
2026-01-05 13:03:55 +08:00
},
autoFormatting : {
name : "Auto formatting when typing" ,
desc : "Toggle auto-formatting of text while editing the document."
},
2026-08-21 15:44:03 +08:00
autoFormatPaste : {
name : "Auto formatting on paste" ,
desc : "Toggle auto-formatting when pasting. CMD/CTRL+SHIFT+V (paste without formatting) will not trigger this."
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
languagePairSpacing : {
name : "Language Pair Spacing" ,
desc : "Define which language/symbol pairs should have automatic spacing"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
prefixDictionary : {
name : "Prefix Dictionary" ,
desc : "Separate entries by commas, spaces, or newlines. Supports words and /regex/. Matching tokens won't have spaces inserted; prefixes being typed are also suppressed"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
softSpaceSymbols : {
leftName : "Custom Extra Left Soft Space Symbols" ,
leftDesc : `Common full-width punctuation, quotes (' ") and opening brackets ([ ( {) are built in. Add extra left-side symbols here (such as -).` ,
rightName : "Custom Extra Right Soft Space Symbols" ,
rightDesc : `Common full-width punctuation, quotes (' "), closing brackets (] ) }) and half-width punctuation (. , ? ! : ;) are built in. Add extra right-side symbols here (such as -).`
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
customScriptCategories : {
name : "Custom Script Categories" ,
desc : "Add custom language or symbol sets for spacing strategies" ,
namePlaceholder : "Name" ,
patternPlaceholder : "Char class pattern"
2026-01-05 13:03:55 +08:00
},
capitalizeFirstLetter : {
name : "Capitalize the first letter of every sentence" ,
desc : "Capitalize the first letter of each sentence in English."
},
spaceStrategyInlineCode : {
name : "Space strategy between inline code and text" ,
2026-08-21 15:44:03 +08:00
desc : "Define the spacing strategy between inline code and text."
2026-01-05 13:03:55 +08:00
},
spaceStrategyInlineFormula : {
name : "Space strategy between inline formula and text" ,
desc : "Define the spacing strategy between inline formulas and text."
},
spaceStrategyLinkText : {
name : "Space strategy between link and text" ,
desc : "Define the spacing strategy between [[wikilink]] [mdlink](...) and text."
},
userDefinedRegexpSwitch : {
name : "User Defined RegExp Switch" ,
desc : "Toggle custom regular expressions, preventing formatting and setting space strategy between matched content and other text."
},
userDefinedRegexp : {
name : "User-defined Regular Expression, one expression per line" ,
2026-08-21 15:44:03 +08:00
desc : "User-defined regular expression, matched to the content is not formatted, one expression per line, do not feel free to add spaces at the end of the line.The end of each line of three characters fixed as | and two space strategy symbols, space strategy symbols for - = +, respectively, on behalf of not requiring spaces (-), soft spaces (=), strict spaces (+).These two space strategy symbols are the space strategy for the left and right sides of the matching block respectively. Lines starting with // are treated as comments"
},
userRulesRespectUserDefinedRegexBlocks : {
name : "User rules respect custom regex blocks" ,
desc : "When enabled, text matched by custom regex blocks will not trigger auto user rules."
2026-01-05 13:03:55 +08:00
},
excludeFoldersFiles : {
name : "Exclude Folders/Files" ,
desc : "This plugin will parse each line as an exclude folder or file. For example: DailyNote/, DailyNote/WeekNotes/, DailyNote/test.md"
},
fixMacOSContextMenu : {
name : "Fix MacOS context-menu cursor position (Need to restart Obsidian)" ,
desc : "Fix the issue where the cursor jumps to the next line when the context menu is invoked on MacOS (requires restarting Obsidian)."
},
fixMicrosoftIME : {
name : "Fix Microsoft Input Method Issue" ,
desc : "Adapt for older versions of Microsoft Input Method."
},
strictLineBreaks : {
name : "Strict Line breaks Mode" ,
desc : "In strict line breaks mode, pressing Enter once in normal text lines will produce two line breaks or two spaces and Enter."
},
enhanceModA : {
name : "Enhance Mod+A selection in text" ,
desc : "First select the current line, second select the current text block, third select the entire text."
},
collapsePersistentEnter : {
2026-08-21 15:44:03 +08:00
name : "Keep Collapsed on Enter" ,
desc : "Pressing Enter on a collapsed heading inserts a same-level heading below without expanding the fold."
2026-01-05 13:03:55 +08:00
},
printDebugInfo : {
name : "Print debug info in console" ,
desc : "Print debug information in the console."
},
2026-08-21 15:44:03 +08:00
rulesStoragePath : {
name : "Rules Storage Path" ,
desc : "Set the storage path for rule files (relative to vault root). Select default to store in the plugin directory" ,
defaultOption : "Default (plugin directory)" ,
migrateButton : "Migrate" ,
migrateDesc : "Migrate rule files from the previously loaded path to the current path" ,
migrateSuccess : "Rule files migrated successfully"
},
2026-01-05 13:03:55 +08:00
selectionReplaceRule : {
name : "Selection Replace Rule" ,
desc : "User defined Selection Replace Rule"
},
deleteRule : {
name : "Delete Rule" ,
desc : "Rule: Use | to indicate the cursor position. Tips: Using | to indicate the cursor position."
},
convertRule : {
name : "Convert Rule" ,
desc : "Rule: Use | to indicate the cursor position. Tips: Using | to indicate the cursor position."
},
trigger : {
name : "Trigger"
},
left : {
name : "Left"
},
right : {
name : "Right"
},
oldPattern : {
name : "Old Pattern"
},
newPattern : {
name : "New Pattern"
2026-08-21 15:44:03 +08:00
},
ruleEditModal : {
addTitle : "Add Rule" ,
editTitle : "Edit Rule" ,
fieldType : "Type" ,
fieldTrigger : "Match Before Cursor" ,
fieldTriggerSelectKey : "Trigger Key" ,
fieldTriggerRight : "Match After Cursor" ,
hintTriggerEscape : "\\\\: backslash, \\n: newline, \\t: tab" ,
fieldReplacement : "Replacement" ,
fieldReplacementDescSelectKey : "${SEL}: selected text, ${0:${SEL}}: select the text." ,
fieldReplacementDescInputDelete : "[[0]]: 0th left capture group, [[R1]]: 1st right capture group." ,
fieldIsRegex : "Use Regex Matching" ,
fieldTriggerMode : "Trigger Mode" ,
fieldScope : "Scope" ,
fieldScopeLanguage : "Language (optional)" ,
fieldRegexFlags : "Regex Flags" ,
fieldRegexFlagsDesc : "Supports i / m / u only, e.g. im" ,
fieldPriority : "Priority" ,
fieldPriorityDesc : "Lower number = higher priority, default 100" ,
fieldDescription : "Description" ,
buttonSave : "Save" ,
invalidRegex : "Invalid regex" ,
fieldIsFunction : "Use Function Replacement" ,
functionHintInputDelete : "Args: leftMatches (string[]), rightMatches (string[]). Return string or undefined to skip." ,
functionHintSelectKey : "Args: selectionText (string), key (string). Return string or undefined to skip." ,
hintTabstop : "$0: cursor position, $1/$2: Tab jump positions, ${1:text}: jump and select text." ,
functionPlaceholder : "// Example:\nconst d = new Date();\nreturn d.toISOString().slice(0,10) + '$0';" ,
groupMatch : "Match" ,
groupReplacement : "Replacement" ,
groupOther : "Other"
},
ruleType : {
input : "Input" ,
delete : "Delete" ,
selectKey : "SelectKey"
2026-01-05 13:03:55 +08:00
}
},
2026-08-21 15:44:03 +08:00
commands : {
formatArticle : "Format current article" ,
formatSelection : "Format selected text or current line" ,
deleteBlankLine : "Delete blank lines of the selected or whole article" ,
insertCodeblock : "Insert code block w/wo selection" ,
switchAutoformat : "Switch autoformat" ,
pasteWithoutFormat : "Paste without format" ,
toggleComment : "Toggle comment" ,
gotoNewLine : "Go to new line after current line" ,
selectBlock : "Select current text block"
},
2026-01-05 13:03:55 +08:00
headers : {
main : "Obsidian EasyTyping Plugin" ,
githubDetail : "More detail is in Github: " ,
enhancedEditing : "Enhanced Editing Setting" ,
customizeEditRule : "Customize Edit Convertion Rule" ,
autoformatSetting : "Autoformat Setting" ,
2026-08-21 15:44:03 +08:00
detailedSetting : "Spacing Between Inline Elements" ,
2026-01-05 13:03:55 +08:00
customRegexpBlock : "Custom regular expressions block" ,
excludeFoldersFiles : "Exclude Folders/Files" ,
experimentalFeatures : "Experimental Features" ,
2026-08-21 15:44:03 +08:00
languagePairSection : "Language Pair Spacing" ,
addLanguagePair : "Add New Language/Symbol Pair:" ,
prefixDictSection : "Prefix Dictionary" ,
softSpaceSection : "Soft Space Symbols" ,
customScriptSection : "Custom Script Categories" ,
spaceStrategyIntro : "Spacing Strategy:\nNo Require: No space requirement between this category block and the surrounding text.\nSoft Space: Only requires a soft space between this category block and the surrounding blocks (e.g., if adjacent text is punctuation, no real space is added).\nStrict Space: Strictly add real spaces between the current block and the adjacent text." ,
2026-01-05 13:03:55 +08:00
aboutRegexp : {
header : "For knowledge about regular expressions, see " ,
text : "Yifeng Nguyen: A Concise Tutorial on Regular Expressions"
},
customizeSelectionRule : "Customize Selection Replace Rule" ,
customizeDeleteRule : "Customize Delete Rule" ,
customizeConvertRule : "Customize Convert Rule" ,
2026-08-21 15:44:03 +08:00
editSelectionReplaceRule : "Edit Selection Replace Rule" ,
builtinRulesSection : "Built-in Rules" ,
userRulesSection : "User Rules" ,
deletedRulesSection : "Deleted Built-in Rules" ,
tabs : {
editEnhance : "Edit Enhance" ,
autoFormat : "Auto Format" ,
builtinRules : "Built-in Rules" ,
userRules : "User Rules" ,
other : "Other"
}
2026-01-05 13:03:55 +08:00
},
dropdownOptions : {
enterTwice : "Enter Twice" ,
twoSpace : "Two Space" ,
mixMode : "Mix Mode" ,
noRequire : "No Require" ,
softSpace : "Soft Space" ,
strictSpace : "Strict Space" ,
dummy : "Dummy" ,
2026-08-21 15:44:03 +08:00
smart : "Smart" ,
scopeAll : "All" ,
scopeText : "Text" ,
scopeFormula : "Formula" ,
scopeCode : "Code" ,
triggerModeAuto : "Auto" ,
triggerModeTab : "Tab" ,
ruleTypeInput : "Input" ,
ruleTypeDelete : "Delete" ,
ruleTypeSelectKey : "SelectKey"
2026-01-05 13:03:55 +08:00
},
toolTip : {
switch : "Switch" ,
editRule : "Edit rule" ,
removeRule : "Remove rule" ,
2026-08-21 15:44:03 +08:00
addRule : "Add Rule" ,
enableRule : "Enable/Disable rule" ,
restoreRule : "Restore this rule" ,
resetAllRules : "Reset all built-in rules" ,
resetSuccess : "Built-in rules reset successfully" ,
exportRules : "Export Rules" ,
importRules : "Import Rules" ,
noRulesToExport : "No user rules to export" ,
importSuccess : "Imported %d rules, skipped %d duplicates" ,
importInvalidJson : "Invalid file: not valid JSON" ,
importNoRules : "No importable rules found in file"
2026-01-05 13:03:55 +08:00
},
placeHolder : {
triggerSymbol : "Trigger Symbol" ,
newLeftSideString : "New Left Side String" ,
newRightSideString : "New Right Side String" ,
addRule : "Add Rule" ,
noticeInvaidTrigger : "Inlvalid trigger, trigger must be a symbol of length 1 or symbol \u2014\u2014, \u2026\u2026" ,
noticeWarnTriggerExists : "warning! Trigger %s is already exist!" ,
noticeMissingInput : "missing input" ,
beforeDelete : "Before Delete" ,
newPattern : "New Pattern" ,
noticeInvaidTriggerPatternContainSymbol : "Inlvalid trigger, pattern must contain symbol | which indicate cursor position" ,
beforeConvert : "Before Convert" ,
noticeInvalidPatternString : "Invalid pattern string!"
},
button : {
update : "Update"
2026-08-21 15:44:03 +08:00
},
scriptCategoryLabels : {
chinese : "Chinese" ,
japanese : "Japanese" ,
korean : "Korean" ,
cjk : "CJK" ,
english : "English" ,
digit : "Digit" ,
russian : "Russian" ,
unknown : "Unknown"
},
builtinRuleDescriptions : {
"builtin-autopair-input" : "Auto-complete paired full-width brackets/quotes" ,
"builtin-autopair-jump" : "Skip over closing paired symbol to avoid duplicates" ,
"builtin-autopair-delete" : "Delete both sides of full-width bracket/quote pairs" ,
"builtin-conv-backtick" : "Double middle dot \xB7\xB7 converts to inline code" ,
"builtin-conv-codeblock" : "Type \xB7 inside inline code to upgrade to code block" ,
"builtin-conv-formula" : "\uFFE5/$ combinations convert to inline or block formula" ,
"builtin-conv-linestart" : "\u300B at line start \u2192 blockquote, \u3001 at line start \u2192 slash" ,
"builtin-conv-hw2fw" : "Convert half-width punctuation to full-width after CJK characters" ,
"builtin-fw2hw-double" : "Double identical full-width punctuation converts to half-width" ,
"builtin-del-inline-formula" : "Delete inline formula $...$ pair" ,
"builtin-del-highlight" : "Delete highlight ==...== pair" ,
"builtin-del-block-formula" : "Delete block formula $$...$$ pair" ,
"builtin-del-codeblock" : "Quickly delete empty code block" ,
"builtin-del-wikilink" : "Quickly delete wikilink and embed (![[]])" ,
"builtin-sel-wrap-backtick" : "Wrap selection with backticks using \xB7" ,
"builtin-sel-wrap-symbols" : "Wrap selection with []/$ using \u3010/\xA5/\uFFE5" ,
"builtin-sel-wrap-quotes" : "Wrap selection with paired full-width quotes" ,
"builtin-sel-wrap-cjk-brackets" : "Wrap selection with \u300A\u300B or \uFF08\uFF09 brackets" ,
"builtin-quote-convert" : "Convert > or \u300B to Markdown blockquote marker" ,
"builtin-quote-space" : "Auto-insert space after blockquote marker >"
2026-01-05 13:03:55 +08:00
}
};
var en_US_default = locale ;
// src/lang/locale/zh-CN.ts
var locale2 = {
settings : {
2026-08-21 15:44:03 +08:00
smartPaste : {
name : "\u667A\u80FD\u7C98\u8D34" ,
desc : "\u5728\u5217\u8868\u6216\u5F15\u7528\u5757\u4E2D\u7C98\u8D34\u65F6\uFF0C\u81EA\u52A8\u6DFB\u52A0\u7F29\u8FDB\u548C\u5217\u8868/\u5F15\u7528\u7B26\u53F7"
2026-01-05 13:03:55 +08:00
},
codeblockEdit : {
name : "\u589E\u5F3A\u4EE3\u7801\u5757\u7F16\u8F91" ,
desc : "\u589E\u5F3A\u4EE3\u7801\u5757\u5185\u7684\u7F16\u8F91\uFF08Cmd/Ctrl+A \u9009\u4E2D\u3001Tab\u3001\u5220\u9664\u3001\u7C98\u8D34\uFF09"
},
backspaceEdit : {
2026-08-21 15:44:03 +08:00
name : "\u667A\u80FD\u9000\u683C\u952E" ,
2026-01-05 13:03:55 +08:00
desc : "\u589E\u5F3A\u5220\u9664\u7A7A\u5217\u8868\u9879\u6216\u7A7A\u5F15\u7528\u884C\u7684\u529F\u80FD"
},
tabOut : {
2026-08-21 15:44:03 +08:00
name : "Tab \u8DF3\u51FA\u914D\u5BF9\u7B26\u53F7" ,
desc : "\u6309 Tab \u952E\u8DF3\u51FA\u914D\u5BF9\u7B26\u53F7\uFF0C\u5982\u3010\u3011\u3001\uFF08\uFF09\u3001\u300A\u300B\u3001\u5F15\u53F7\u3001\u884C\u5185\u4EE3\u7801\u7B49"
2026-01-05 13:03:55 +08:00
},
autoFormatting : {
name : "\u8F93\u5165\u65F6\u81EA\u52A8\u683C\u5F0F\u5316" ,
desc : "\u662F\u5426\u5728\u7F16\u8F91\u6587\u6863\u65F6\u81EA\u52A8\u683C\u5F0F\u5316\u6587\u672C\uFF0C\u81EA\u52A8\u683C\u5F0F\u5316\u7684\u603B\u5F00\u5173"
},
2026-08-21 15:44:03 +08:00
autoFormatPaste : {
name : "\u7C98\u8D34\u65F6\u81EA\u52A8\u683C\u5F0F\u5316" ,
desc : "\u7C98\u8D34\u65F6\u662F\u5426\u81EA\u52A8\u683C\u5F0F\u5316\uFF0CCMD/CTRL+SHIFT+V \u65E0\u683C\u5F0F\u7C98\u8D34\u65F6\u4E0D\u89E6\u53D1\u3002"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
languagePairSpacing : {
name : "\u8BED\u8A00\u95F4\u7A7A\u683C\u7B56\u7565" ,
desc : "\u5B9A\u4E49\u4E0D\u540C\u8BED\u8A00/\u7B26\u53F7\u7C7B\u578B\u4E4B\u95F4\u662F\u5426\u81EA\u52A8\u6DFB\u52A0\u7A7A\u683C"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
prefixDictionary : {
name : "\u524D\u7F00\u8BCD\u5178" ,
desc : "\u7528\u9017\u53F7\u3001\u7A7A\u683C\u6216\u6362\u884C\u5206\u9694\uFF0C\u652F\u6301\u8BCD\u6216 /\u6B63\u5219/\u3002\u5339\u914D\u7684 token \u4E0D\u4F1A\u88AB\u63D2\u5165\u7A7A\u683C\uFF0C\u6B63\u5728\u8F93\u5165\u7684\u524D\u7F00\u4E5F\u4F1A\u6682\u4E0D\u63D2\u5165\u7A7A\u683C"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
softSpaceSymbols : {
leftName : "\u81EA\u5B9A\u4E49\u5DE6\u4FA7\u8F6F\u7A7A\u683C\u989D\u5916\u7B26\u53F7" ,
leftDesc : `\u5E38\u89C1\u7684\u5168\u89D2\u6807\u70B9\u3001\u82F1\u6587\u5F15\u53F7\uFF08' "\uFF09\u548C\u5DE6\u62EC\u53F7\uFF08[ ( {\uFF09\u5DF2\u5185\u7F6E\u652F\u6301\u3002\u5728\u6B64\u6DFB\u52A0\u989D\u5916\u7684\u5DE6\u4FA7\u7B26\u53F7\uFF08\u5982 -\uFF09` ,
rightName : "\u81EA\u5B9A\u4E49\u53F3\u4FA7\u8F6F\u7A7A\u683C\u989D\u5916\u7B26\u53F7" ,
rightDesc : `\u5E38\u89C1\u7684\u5168\u89D2\u6807\u70B9\u3001\u82F1\u6587\u5F15\u53F7\uFF08' "\uFF09\u3001\u53F3\u62EC\u53F7\uFF08] ) }\uFF09\u4EE5\u53CA\u82F1\u6587\u534A\u89D2\u6807\u70B9\uFF08. , ? ! : ;\uFF09\u5DF2\u5185\u7F6E\u4E3A\u53F3\u8F6F\u7A7A\u683C\u7B26\u53F7\u3002\u5728\u6B64\u6DFB\u52A0\u989D\u5916\u7684\u53F3\u4FA7\u7B26\u53F7\uFF08\u5982 -\uFF09`
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
customScriptCategories : {
name : "\u81EA\u5B9A\u4E49\u8BED\u8A00/\u7B26\u53F7\u96C6" ,
desc : "\u6DFB\u52A0\u81EA\u5B9A\u4E49\u8BED\u8A00\u6216\u7B26\u53F7\u96C6\u7528\u4E8E\u7A7A\u683C\u7B56\u7565" ,
namePlaceholder : "\u540D\u79F0" ,
patternPlaceholder : "\u5B57\u7B26\u7C7B\u6A21\u5F0F"
2026-01-05 13:03:55 +08:00
},
capitalizeFirstLetter : {
name : "\u53E5\u9996\u5B57\u6BCD\u5927\u5199" ,
desc : "\u82F1\u6587\u6BCF\u4E2A\u53E5\u9996\u5B57\u6BCD\u5927\u5199\uFF0C\u53EF\u64A4\u9500"
},
spaceStrategyInlineCode : {
name : "\u884C\u5185\u4EE3\u7801\u548C\u6587\u672C\u4E4B\u95F4\u7684\u7A7A\u683C\u7B56\u7565" ,
2026-08-21 15:44:03 +08:00
desc : "\u5B9A\u4E49\u884C\u5185\u4EE3\u7801\u548C\u6587\u672C\u4E4B\u95F4\u7684\u7A7A\u683C\u7B56\u7565"
2026-01-05 13:03:55 +08:00
},
spaceStrategyInlineFormula : {
name : "\u884C\u5185\u516C\u5F0F\u548C\u6587\u672C\u4E4B\u95F4\u7684\u7A7A\u683C\u7B56\u7565" ,
desc : "\u5B9A\u4E49\u884C\u5185\u516C\u5F0F\u548C\u6587\u672C\u4E4B\u95F4\u7684\u7A7A\u683C\u7B56\u7565"
},
spaceStrategyLinkText : {
name : "\u94FE\u63A5\u548C\u6587\u672C\u4E4B\u95F4\u7684\u7A7A\u683C\u7B56\u7565" ,
desc : "\u5B9A\u4E49 [[wikilink]] [mdlink](...) \u548C\u6587\u672C\u4E4B\u95F4\u7684\u7A7A\u683C\u7B56\u7565"
},
userDefinedRegexpSwitch : {
name : "\u7528\u6237\u5B9A\u4E49\u7684\u6B63\u5219\u8868\u8FBE\u5F0F\u5F00\u5173" ,
desc : "\u81EA\u5B9A\u4E49\u6B63\u5219\u8868\u8FBE\u5F0F\u5F00\u5173\uFF0C\u5339\u914D\u5230\u7684\u5185\u5BB9\u4E0D\u8FDB\u884C\u683C\u5F0F\u5316\uFF0C\u4E14\u53EF\u4EE5\u8BBE\u7F6E\u5339\u914D\u5230\u7684\u5185\u5BB9\u5757\u4E0E\u5176\u4ED6\u5185\u5BB9\u4E4B\u95F4\u7684\u7A7A\u683C\u7B56\u7565"
},
userDefinedRegexp : {
name : "\u7528\u6237\u5B9A\u4E49\u7684\u6B63\u5219\u8868\u8FBE\u5F0F" ,
2026-08-21 15:44:03 +08:00
desc : "\u7528\u6237\u81EA\u5B9A\u4E49\u6B63\u5219\u8868\u8FBE\u5F0F\uFF0C\u5339\u914D\u5230\u7684\u5185\u5BB9\u4E0D\u8FDB\u884C\u683C\u5F0F\u5316\uFF0C\u6BCF\u884C\u4E00\u4E2A\u8868\u8FBE\u5F0F\uFF0C\u884C\u5C3E\u4E0D\u8981\u968F\u610F\u52A0\u7A7A\u683C\u3002\u6BCF\u884C\u672B\u5C3E3\u4E2A\u5B57\u7B26\u7684\u56FA\u5B9A\u4E3A|\u548C\u4E24\u4E2A\u7A7A\u683C\u7B56\u7565\u7B26\u53F7\uFF0C\u7A7A\u683C\u7B56\u7565\u7B26\u53F7\u4E3A-=+\uFF0C\u5206\u522B\u4EE3\u8868\u4E0D\u8981\u6C42\u7A7A\u683C(-)\uFF0C\u8F6F\u7A7A\u683C(=)\uFF0C\u4E25\u683C\u7A7A\u683C(+)\u3002\u8FD9\u4E24\u4E2A\u7A7A\u683C\u7B56\u7565\u7B26\u53F7\u5206\u522B\u4E3A\u5339\u914D\u533A\u5757\u7684\u5DE6\u53F3\u4E24\u8FB9\u7684\u7A7A\u683C\u7B56\u7565\u3002\u4EE5 // \u5F00\u5934\u7684\u884C\u4F5C\u4E3A\u6CE8\u91CA"
},
userRulesRespectUserDefinedRegexBlocks : {
name : "\u81EA\u5B9A\u4E49\u6B63\u5219\u533A\u5757\u540C\u65F6\u963B\u6B62\u7528\u6237\u89C4\u5219" ,
desc : "\u542F\u7528\u540E\uFF0C\u547D\u4E2D\u81EA\u5B9A\u4E49\u6B63\u5219\u533A\u5757\u7684\u6587\u672C\u5C06\u4E0D\u4F1A\u89E6\u53D1\u81EA\u52A8\u7528\u6237\u89C4\u5219\u3002"
2026-01-05 13:03:55 +08:00
},
excludeFoldersFiles : {
name : "\u6392\u9664\u6587\u4EF6\u5939/\u6587\u4EF6" ,
desc : "\u8BE5\u63D2\u4EF6\u5C06\u6BCF\u884C\u89E3\u6790\u4E3A\u4E00\u4E2A\u6392\u9664\u6587\u4EF6\u5939\u6216\u6587\u4EF6\u3002\u4F8B\u5982\uFF1ADailyNote/, DailyNote/WeekNotes/, DailyNote/test.md"
},
fixMacOSContextMenu : {
name : "\u4FEE\u590D MacOS \u53F3\u952E\u83DC\u5355\u5149\u6807\u4F4D\u7F6E" ,
desc : "\u4FEE\u590D MacOS \u9F20\u6807\u53F3\u952E\u547C\u51FA\u83DC\u5355\u65F6\u5149\u6807\u8DF3\u5230\u4E0B\u4E00\u884C\u7684\u95EE\u9898 (\u9700\u8981\u91CD\u542F Obsidian \u751F\u6548)"
},
fixMicrosoftIME : {
name : "\u4FEE\u590D\u5FAE\u8F6F\u8F93\u5165\u6CD5\u95EE\u9898" ,
desc : "\u9002\u914D\u65E7\u7248\u5FAE\u8F6F\u8F93\u5165\u6CD5"
},
strictLineBreaks : {
name : "\u4E25\u683C\u6362\u884C\u6A21\u5F0F\u56DE\u8F66\u589E\u5F3A" ,
desc : "\u4E25\u683C\u6362\u884C\u7684\u8BBE\u7F6E\u4E0B\uFF0C\u5728\u666E\u901A\u6587\u672C\u884C\u8FDB\u884C\u4E00\u6B21\u56DE\u8F66\u4F1A\u6839\u636E\u6A21\u5F0F\u4EA7\u751F\u4E24\u4E2A\u6362\u884C\u7B26\u6216\u8005\u4E24\u4E2A\u7A7A\u683C\u548C\u56DE\u8F66"
},
enhanceModA : {
name : "\u589E\u5F3A Ctrl/Cmd+A \u529F\u80FD" ,
desc : "\u7B2C\u4E00\u6B21\u9009\u4E2D\u5F53\u524D\u884C\uFF0C\u7B2C\u4E8C\u6B21\u9009\u4E2D\u5F53\u524D\u6587\u672C\u5757\uFF0C\u7B2C\u4E09\u6B21\u9009\u4E2D\u5168\u6587\u3002"
},
collapsePersistentEnter : {
2026-08-21 15:44:03 +08:00
name : "\u6298\u53E0\u6807\u9898\u56DE\u8F66\u4E0D\u5C55\u5F00" ,
desc : "\u5728\u6298\u53E0\u7684\u6807\u9898\u884C\u6309\u56DE\u8F66\u65F6\uFF0C\u4E0D\u5C55\u5F00\u6298\u53E0\u5185\u5BB9\uFF0C\u76F4\u63A5\u5728\u4E0B\u65B9\u6DFB\u52A0\u540C\u7EA7\u6807\u9898\u884C"
2026-01-05 13:03:55 +08:00
},
printDebugInfo : {
name : "\u5728\u63A7\u5236\u53F0\u8F93\u51FA\u8C03\u8BD5\u4FE1\u606F" ,
desc : "\u5728\u63A7\u5236\u53F0\u8F93\u51FA\u8C03\u8BD5\u4FE1\u606F"
},
2026-08-21 15:44:03 +08:00
rulesStoragePath : {
name : "\u89C4\u5219\u6587\u4EF6\u5B58\u50A8\u8DEF\u5F84" ,
desc : "\u8BBE\u7F6E\u89C4\u5219\u6587\u4EF6\u7684\u5B58\u50A8\u8DEF\u5F84\uFF08\u76F8\u5BF9\u4E8E\u5E93\u6839\u76EE\u5F55\uFF09\uFF0C\u9009\u62E9\u9ED8\u8BA4\u5219\u5B58\u50A8\u5728\u63D2\u4EF6\u76EE\u5F55\u5185" ,
defaultOption : "\u9ED8\u8BA4\uFF08\u63D2\u4EF6\u76EE\u5F55\uFF09" ,
migrateButton : "\u8FC1\u79FB" ,
migrateDesc : "\u5C06\u89C4\u5219\u6587\u4EF6\u4ECE\u4E0A\u6B21\u52A0\u8F7D\u7684\u8DEF\u5F84\u8FC1\u79FB\u5230\u5F53\u524D\u8BBE\u7F6E\u7684\u8DEF\u5F84" ,
migrateSuccess : "\u89C4\u5219\u6587\u4EF6\u8FC1\u79FB\u6210\u529F"
},
2026-01-05 13:03:55 +08:00
selectionReplaceRule : {
name : "\u9009\u4E2D\u66FF\u6362\u89C4\u5219" ,
desc : "\u7528\u6237\u5B9A\u4E49\u7684\u9009\u62E9\u66FF\u6362\u89C4\u5219"
},
deleteRule : {
name : "\u5220\u9664\u89C4\u5219" ,
desc : "\u89C4\u5219\uFF1A\u7528 | \u4EE3\u8868\u5149\u6807\u4F4D\u7F6E\uFF0C\u5FC5\u987B\u5305\u542B\u5149\u6807\u3002\u63D0\u793A\uFF1A\u4F7F\u7528 | \u8868\u793A\u5149\u6807\u4F4D\u7F6E\u3002"
},
convertRule : {
name : "\u8F6C\u6362\u89C4\u5219" ,
desc : "\u89C4\u5219\uFF1A\u7528 | \u4EE3\u8868\u5149\u6807\u4F4D\u7F6E\uFF0C\u5FC5\u987B\u5305\u542B\u5149\u6807\u3002\u63D0\u793A\uFF1A\u4F7F\u7528 | \u8868\u793A\u5149\u6807\u4F4D\u7F6E\u3002"
},
trigger : {
name : "\u89E6\u53D1\u5668"
},
left : {
name : "\u5DE6"
},
right : {
name : "\u53F3"
},
oldPattern : {
name : "\u65E7\u6A21\u5F0F"
},
newPattern : {
name : "\u65B0\u6A21\u5F0F"
2026-08-21 15:44:03 +08:00
},
ruleEditModal : {
addTitle : "\u6DFB\u52A0\u89C4\u5219" ,
editTitle : "\u7F16\u8F91\u89C4\u5219" ,
fieldType : "\u7C7B\u578B" ,
fieldTrigger : "\u5149\u6807\u524D\u5339\u914D" ,
fieldTriggerSelectKey : "\u89E6\u53D1\u6309\u952E\u5B57\u7B26" ,
fieldTriggerRight : "\u5149\u6807\u540E\u5339\u914D" ,
hintTriggerEscape : "\\\\\uFF1A\u53CD\u659C\u6760\uFF0C\\n\uFF1A\u6362\u884C\uFF0C\\t\uFF1A\u5236\u8868\u7B26" ,
fieldReplacement : "\u66FF\u6362\u5185\u5BB9" ,
fieldReplacementDescSelectKey : "${SEL}\uFF1A\u9009\u4E2D\u7684\u6587\u672C\u5185\u5BB9\uFF0C${0:${SEL}}\uFF1A\u5149\u6807\u7EE7\u7EED\u9009\u4E2D\u3002" ,
fieldReplacementDescInputDelete : "[[0]]\uFF1A\u5DE6\u4FA7\u7B2C0\u6355\u83B7\u7EC4\uFF0C[[R1]]\uFF1A\u53F3\u4FA7\u7B2C1\u6355\u83B7\u7EC4\u3002" ,
fieldIsRegex : "\u4F7F\u7528\u6B63\u5219\u8868\u8FBE\u5F0F\u5339\u914D" ,
fieldTriggerMode : "\u89E6\u53D1\u65B9\u5F0F" ,
fieldScope : "\u4F5C\u7528\u57DF" ,
fieldScopeLanguage : "\u8BED\u8A00\uFF08\u53EF\u9009\uFF09" ,
fieldRegexFlags : "\u6B63\u5219\u6807\u5FD7" ,
fieldRegexFlagsDesc : "\u4EC5\u652F\u6301 i / m / u\uFF0C\u4F8B\u5982 im" ,
fieldPriority : "\u4F18\u5148\u7EA7" ,
fieldPriorityDesc : "\u6570\u503C\u8D8A\u5C0F\uFF0C\u4F18\u5148\u7EA7\u8D8A\u9AD8\uFF0C\u9ED8\u8BA4 100" ,
fieldDescription : "\u63CF\u8FF0" ,
buttonSave : "\u4FDD\u5B58" ,
invalidRegex : "\u6B63\u5219\u8868\u8FBE\u5F0F\u65E0\u6548" ,
fieldIsFunction : "\u4F7F\u7528\u51FD\u6570\u5F0F\u66FF\u6362" ,
functionHintInputDelete : "\u53C2\u6570\uFF1AleftMatches (string[])\u3001rightMatches (string[])\u3002\u8FD4\u56DE\u5B57\u7B26\u4E32\u6216 undefined \u8DF3\u8FC7\u3002" ,
functionHintSelectKey : "\u53C2\u6570\uFF1AselectionText (string)\u3001key (string)\u3002\u8FD4\u56DE\u5B57\u7B26\u4E32\u6216 undefined \u8DF3\u8FC7\u3002" ,
hintTabstop : "$0\uFF1A\u5149\u6807\u4F4D\u7F6E\uFF0C$1/$2\uFF1A\u6309 Tab \u8DF3\u8F6C\u7684\u4F4D\u7F6E\uFF0C${1:text}\uFF1A\u8DF3\u8F6C\u5E76\u9009\u4E2D text\u3002" ,
functionPlaceholder : "// \u793A\u4F8B\uFF1A\nconst d = new Date();\nreturn d.toISOString().slice(0,10) + '$0';" ,
groupMatch : "\u5339\u914D\u6761\u4EF6" ,
groupReplacement : "\u66FF\u6362" ,
groupOther : "\u5176\u4ED6"
},
ruleType : {
input : "\u8F93\u5165" ,
delete : "\u5220\u9664" ,
selectKey : "\u9009\u4E2D\u66FF\u6362"
2026-01-05 13:03:55 +08:00
}
},
2026-08-21 15:44:03 +08:00
commands : {
formatArticle : "\u683C\u5F0F\u5316\u5168\u6587" ,
formatSelection : "\u683C\u5F0F\u5316\u9009\u4E2D\u90E8\u5206/\u5F53\u524D\u884C" ,
deleteBlankLine : "\u522A\u9664\u9009\u4E2D\u90E8\u5206/\u5168\u6587\u7684\u591A\u4F59\u7A7A\u767D\u884C" ,
insertCodeblock : "\u63D2\u5165\u4EE3\u7801\u5757" ,
switchAutoformat : "\u5207\u6362\u81EA\u52A8\u683C\u5F0F\u5316\u5F00\u5173" ,
pasteWithoutFormat : "\u65E0\u683C\u5F0F\u5316\u7C98\u8D34" ,
toggleComment : "\u5207\u6362\u6CE8\u91CA" ,
gotoNewLine : "\u8DF3\u5230\u5F53\u524D\u884C\u540E\u65B0\u884C" ,
selectBlock : "\u9009\u62E9\u5F53\u524D\u6587\u672C\u5757"
},
2026-01-05 13:03:55 +08:00
headers : {
main : "Obsidian EasyTyping \u63D2\u4EF6" ,
githubDetail : "\u8BE6\u60C5\u89C1 Github\uFF1A" ,
enhancedEditing : "\u589E\u5F3A\u7F16\u8F91\u8BBE\u7F6E" ,
customizeEditRule : "\u81EA\u5B9A\u4E49\u7F16\u8F91\u8F6C\u6362\u89C4\u5219" ,
autoformatSetting : "\u81EA\u52A8\u683C\u5F0F\u5316\u8BBE\u7F6E" ,
2026-08-21 15:44:03 +08:00
detailedSetting : "\u884C\u5185\u5143\u7D20\u95F4\u7A7A\u683C" ,
2026-01-05 13:03:55 +08:00
customRegexpBlock : "\u81EA\u5B9A\u4E49\u6B63\u5219\u533A\u5757" ,
excludeFoldersFiles : "\u6307\u5B9A\u6587\u4EF6\u4E0D\u81EA\u52A8\u683C\u5F0F\u5316" ,
experimentalFeatures : "\u5B9E\u9A8C\u529F\u80FD" ,
2026-08-21 15:44:03 +08:00
languagePairSection : "\u8BED\u8A00\u95F4\u7A7A\u683C\u7B56\u7565" ,
addLanguagePair : "\u6DFB\u52A0\u65B0\u8BED\u8A00/\u7B26\u53F7\u5BF9\uFF1A" ,
prefixDictSection : "\u524D\u7F00\u8BCD\u5178" ,
softSpaceSection : "\u81EA\u5B9A\u4E49\u8F6F\u7A7A\u683C\u7B26\u53F7" ,
customScriptSection : "\u81EA\u5B9A\u4E49\u8BED\u8A00/\u7B26\u53F7\u96C6" ,
spaceStrategyIntro : "\u7A7A\u683C\u7B56\u7565\u8BF4\u660E\uFF1A\n\u65E0\u8981\u6C42\uFF1A\u5BF9\u76F8\u5173\u533A\u5757\u4E0E\u5DE6\u53F3\u6587\u672C\u6CA1\u6709\u7A7A\u683C\u8981\u6C42\u3002\n\u8F6F\u7A7A\u683C\uFF1A\u5BF9\u76F8\u5173\u533A\u5757\u4E0E\u5468\u56F4\u533A\u5757\u53EA\u8981\u6C42\u6709\u8F6F\u7A7A\u683C\uFF08\u4F8B\u5982\u5F53\u524D\u5757\u5DE6\u53F3\u4E34\u8FD1\u6587\u672C\u4E3A\u6807\u70B9\u7B26\u53F7\u65F6\uFF0C\u4E0D\u9700\u8981\u518D\u63D2\u5165\u771F\u5B9E\u7A7A\u683C\uFF09\u3002\n\u4E25\u683C\u7A7A\u683C\uFF1A\u5F53\u524D\u5757\u4E0E\u4E34\u8FD1\u6587\u672C\u4E4B\u95F4\u4E25\u683C\u6DFB\u52A0\u771F\u5B9E\u7A7A\u683C\u3002" ,
2026-01-05 13:03:55 +08:00
aboutRegexp : {
header : "\u6B63\u5219\u8868\u8FBE\u5F0F\u76F8\u5173\u77E5\u8BC6\uFF0C\u89C1 " ,
text : "\u300A\u962E\u4E00\u5CF0\uFF1A\u6B63\u5219\u8868\u8FBE\u5F0F\u7B80\u660E\u6559\u7A0B\u300B"
},
customizeSelectionRule : "\u81EA\u5B9A\u4E49\u9009\u4E2D\u6587\u672C\u7F16\u8F91\u589E\u5F3A\u89C4\u5219" ,
customizeDeleteRule : "\u81EA\u5B9A\u4E49\u5220\u9664\u7F16\u8F91\u589E\u5F3A\u89C4\u5219" ,
customizeConvertRule : "\u81EA\u5B9A\u4E49\u7F16\u8F91\u8F6C\u6362\u89C4\u5219" ,
2026-08-21 15:44:03 +08:00
editSelectionReplaceRule : "\u7F16\u8F91\u9009\u4E2D\u66FF\u6362\u89C4\u5219" ,
builtinRulesSection : "\u5185\u7F6E\u89C4\u5219" ,
userRulesSection : "\u7528\u6237\u89C4\u5219" ,
deletedRulesSection : "\u5DF2\u5220\u9664\u7684\u5185\u7F6E\u89C4\u5219" ,
tabs : {
editEnhance : "\u7F16\u8F91\u589E\u5F3A" ,
autoFormat : "\u81EA\u52A8\u683C\u5F0F\u5316" ,
builtinRules : "\u5185\u7F6E\u89C4\u5219" ,
userRules : "\u81EA\u5B9A\u4E49\u89C4\u5219" ,
other : "\u5176\u4ED6\u8BBE\u7F6E"
}
2026-01-05 13:03:55 +08:00
},
dropdownOptions : {
enterTwice : "\u4E24\u6B21\u56DE\u8F66" ,
twoSpace : "\u52A0\u4E24\u4E2A\u7A7A\u683C" ,
mixMode : "\u6DF7\u5408\u6A21\u5F0F" ,
noRequire : "\u65E0\u8981\u6C42" ,
softSpace : "\u8F6F\u7A7A\u683C" ,
strictSpace : "\u4E25\u683C\u7A7A\u683C" ,
dummy : "\u5446\u7A7A\u683C" ,
2026-08-21 15:44:03 +08:00
smart : "\u667A\u80FD\u7A7A\u683C" ,
scopeAll : "\u5168\u90E8" ,
scopeText : "\u6587\u672C" ,
scopeFormula : "\u516C\u5F0F" ,
scopeCode : "\u4EE3\u7801" ,
triggerModeAuto : "\u81EA\u52A8" ,
triggerModeTab : "Tab \u952E" ,
ruleTypeInput : "\u8F93\u5165" ,
ruleTypeDelete : "\u5220\u9664" ,
ruleTypeSelectKey : "\u9009\u4E2D\u66FF\u6362"
2026-01-05 13:03:55 +08:00
},
toolTip : {
switch : "\u529F\u80FD\u5F00\u5173" ,
editRule : "\u7F16\u8F91\u89C4\u5219" ,
removeRule : "\u5220\u9664\u89C4\u5219" ,
2026-08-21 15:44:03 +08:00
addRule : "\u6DFB\u52A0\u89C4\u5219" ,
enableRule : "\u542F\u7528/\u7981\u7528\u89C4\u5219" ,
restoreRule : "\u6062\u590D\u6B64\u89C4\u5219" ,
resetAllRules : "\u91CD\u7F6E\u5185\u7F6E\u89C4\u5219" ,
resetSuccess : "\u5185\u7F6E\u89C4\u5219\u5DF2\u91CD\u7F6E" ,
exportRules : "\u5BFC\u51FA\u89C4\u5219" ,
importRules : "\u5BFC\u5165\u89C4\u5219" ,
noRulesToExport : "\u6CA1\u6709\u53EF\u5BFC\u51FA\u7684\u7528\u6237\u89C4\u5219" ,
importSuccess : "\u5BFC\u5165\u4E86 %d \u6761\u89C4\u5219\uFF0C\u8DF3\u8FC7 %d \u6761\u91CD\u590D\u89C4\u5219" ,
importInvalidJson : "\u6587\u4EF6\u683C\u5F0F\u9519\u8BEF\uFF1A\u4E0D\u662F\u6709\u6548\u7684 JSON" ,
importNoRules : "\u6587\u4EF6\u4E2D\u6CA1\u6709\u53EF\u5BFC\u5165\u7684\u89C4\u5219"
2026-01-05 13:03:55 +08:00
},
placeHolder : {
triggerSymbol : "\u89E6\u53D1\u7B26" ,
newLeftSideString : "\u5DE6\u8FB9\u7B26\u53F7" ,
newRightSideString : "\u53F3\u8FB9\u7B26\u53F7" ,
addRule : "\u6DFB\u52A0\u89C4\u5219" ,
noticeInvaidTrigger : "\u65E0\u6548\u7684\u89E6\u53D1\u7B26, \u89E6\u53D1\u7B26\u5FC5\u987B\u662F\u5355\u5B57\u7B26\u6216\u8005\u662F \u2014\u2014\u3001\u2026\u2026" ,
noticeWarnTriggerExists : "\u65E0\u6548\u89C4\u5219! \u89E6\u53D1\u7B26 %s \u5DF2\u5B58\u5728" ,
noticeMissingInput : "missing input" ,
beforeDelete : "\u5220\u9664\u524D|" ,
newPattern : "\u89E6\u53D1\u89C4\u5219\u540E\u5B57\u7B26\u4E32\u6A21\u5F0F" ,
noticeInvaidTriggerPatternContainSymbol : "\u65E0\u6548\u89C4\u5219, \u8F6C\u6362\u524D\u6A21\u5F0F\u5FC5\u987B\u5305\u542B\u4EE3\u8868\u5149\u6807\u4F4D\u7F6E\u7684\u7B26\u53F7 |" ,
beforeConvert : "\u8F6C\u6362\u524D|" ,
noticeInvalidPatternString : "Invalid pattern string!"
},
button : {
update : "\u66F4\u65B0"
2026-08-21 15:44:03 +08:00
},
scriptCategoryLabels : {
chinese : "\u4E2D\u6587" ,
japanese : "\u65E5\u6587" ,
korean : "\u97E9\u6587" ,
cjk : "\u4E2D\u65E5\u97E9" ,
english : "\u82F1\u6587" ,
digit : "\u6570\u5B57" ,
russian : "\u4FC4\u6587" ,
unknown : "\u672A\u77E5"
},
builtinRuleDescriptions : {
"builtin-autopair-input" : "\u8F93\u5165\u5168\u89D2\u62EC\u53F7/\u5F15\u53F7\u65F6\u81EA\u52A8\u8865\u5168\u914D\u5BF9" ,
"builtin-autopair-jump" : "\u8F93\u5165\u53F3\u4FA7\u914D\u5BF9\u7B26\u53F7\u65F6\u81EA\u52A8\u8DF3\u8FC7\uFF0C\u907F\u514D\u91CD\u590D\u63D2\u5165" ,
"builtin-autopair-delete" : "\u5220\u9664\u5168\u89D2\u62EC\u53F7/\u5F15\u53F7\u65F6\u540C\u65F6\u5220\u9664\u914D\u5BF9" ,
"builtin-conv-backtick" : "\u8FDE\u7EED\u4E2D\u6587\u95F4\u9694\u53F7 \xB7\xB7 \u8F6C\u884C\u5185\u4EE3\u7801" ,
"builtin-conv-codeblock" : "\u884C\u5185\u4EE3\u7801\u4E2D\u7EE7\u7EED\u8F93\u5165 \xB7 \u5347\u7EA7\u4E3A\u4EE3\u7801\u5757" ,
"builtin-conv-formula" : "\uFFE5/$ \u7B26\u53F7\u7EC4\u5408\u8F6C\u884C\u5185\u6216\u5757\u7EA7\u516C\u5F0F" ,
"builtin-conv-linestart" : "\u884C\u9996 \u300B \u8F6C\u5F15\u7528\u6807\u8BB0\u3001\u884C\u9996 \u3001 \u8F6C\u659C\u6760" ,
"builtin-conv-hw2fw" : "CJK\u5B57\u7B26\u540E\u534A\u89D2\u6807\u70B9\u8F6C\u5168\u89D2" ,
"builtin-fw2hw-double" : "\u8FDE\u7EED\u8F93\u5165\u4E24\u4E2A\u76F8\u540C\u5168\u89D2\u6807\u70B9\u8F6C\u5BF9\u5E94\u534A\u89D2" ,
"builtin-del-inline-formula" : "\u5220\u9664\u884C\u5185\u516C\u5F0F $...$ \u914D\u5BF9" ,
"builtin-del-highlight" : "\u5220\u9664\u9AD8\u4EAE ==...== \u914D\u5BF9" ,
"builtin-del-block-formula" : "\u5220\u9664\u5757\u7EA7\u516C\u5F0F $$...$$ \u914D\u5BF9" ,
"builtin-del-codeblock" : "\u5FEB\u901F\u5220\u9664\u7A7A\u4EE3\u7801\u5757" ,
"builtin-del-wikilink" : "\u5FEB\u901F\u5220\u9664\u53CC\u94FE\u53CA\u5D4C\u5165\uFF08![[]]\uFF09" ,
"builtin-sel-wrap-symbols" : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165 \u3010/\xA5/\uFFE5 \u5305\u88F9\u4E3A []/$$" ,
"builtin-sel-wrap-backtick" : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165 \xB7 \u5305\u88F9\u4E3A\u884C\u5185\u4EE3\u7801" ,
"builtin-sel-wrap-quotes" : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165\u5168\u89D2\u5F15\u53F7\uFF0C\u914D\u5BF9\u5F15\u53F7\u5305\u88F9" ,
"builtin-sel-wrap-cjk-brackets" : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165\u300A\uFF08\uFF0C\u914D\u5BF9\u62EC\u53F7\u5305\u88F9" ,
"builtin-quote-convert" : "\u8F93\u5165 > \u6216 \u300B \u8F6C\u4E3A Markdown \u5F15\u7528\u6807\u8BB0" ,
"builtin-quote-space" : "\u5F15\u7528\u6807\u8BB0 > \u540E\u81EA\u52A8\u8865\u7A7A\u683C"
2026-01-05 13:03:55 +08:00
}
};
var zh_CN_default = locale2 ;
2026-08-21 15:44:03 +08:00
// src/lang/locale/zh-TW.ts
2026-01-05 13:03:55 +08:00
var locale3 = {
settings : {
2026-08-21 15:44:03 +08:00
smartPaste : {
name : "\u667A\u6167\u7C98\u8CBC" ,
desc : "\u5728\u5217\u8868\u6216\u5F15\u7528\u584A\u4E2D\u7C98\u8CBC\u6642\uFF0C\u81EA\u52D5\u6DFB\u52A0\u7E2E\u9032\u548C\u5217\u8868/\u5F15\u7528\u7B26\u865F"
2026-01-05 13:03:55 +08:00
},
codeblockEdit : {
name : "\u589E\u5F3A\u4EE3\u78BC\u584A\u7DE8\u8F2F" ,
desc : "\u589E\u5F3A\u4EE3\u78BC\u584A\u5167\u7684\u7DE8\u8F2F\uFF08Cmd/Ctrl+A \u9078\u4E2D\u3001Tab\u3001\u522A\u9664\u3001\u7C98\u8CBC\uFF09"
},
backspaceEdit : {
2026-08-21 15:44:03 +08:00
name : "\u667A\u6167\u9000\u683C\u9375" ,
2026-01-05 13:03:55 +08:00
desc : "\u589E\u5F37\u522A\u9664\u7A7A\u5217\u8868\u9805\u6216\u7A7A\u5F15\u7528\u884C\u7684\u529F\u80FD"
},
tabOut : {
2026-08-21 15:44:03 +08:00
name : "Tab \u8DF3\u51FA\u914D\u5C0D\u7B26\u865F" ,
desc : "\u6309 Tab \u9375\u8DF3\u51FA\u914D\u5C0D\u7B26\u865F\uFF0C\u5982\u3010\u3011\u3001\uFF08\uFF09\u3001\u300A\u300B\u3001\u5F15\u865F\u3001\u884C\u5167\u4EE3\u78BC\u7B49"
2026-01-05 13:03:55 +08:00
},
autoFormatting : {
name : "\u8F38\u5165\u6642\u81EA\u52D5\u683C\u5F0F\u5316" ,
desc : "\u662F\u5426\u5728\u7DE8\u8F2F\u6587\u6A94\u6642\u81EA\u52D5\u683C\u5F0F\u5316\u6587\u672C\uFF0C\u81EA\u52D5\u683C\u5F0F\u5316\u7684\u7E3D\u958B\u95DC"
},
2026-08-21 15:44:03 +08:00
autoFormatPaste : {
name : "\u7C98\u8CBC\u6642\u81EA\u52D5\u683C\u5F0F\u5316" ,
desc : "\u7C98\u8CBC\u6642\u662F\u5426\u81EA\u52D5\u683C\u5F0F\u5316\uFF0CCMD/CTRL+SHIFT+V \u7121\u683C\u5F0F\u7C98\u8CBC\u6642\u4E0D\u89F8\u767C\u3002"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
languagePairSpacing : {
name : "\u8A9E\u8A00\u9593\u7A7A\u683C\u7B56\u7565" ,
desc : "\u5B9A\u7FA9\u4E0D\u540C\u8A9E\u8A00/\u7B26\u865F\u985E\u578B\u4E4B\u9593\u662F\u5426\u81EA\u52D5\u6DFB\u52A0\u7A7A\u683C"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
prefixDictionary : {
name : "\u524D\u7DB4\u8A5E\u5178" ,
desc : "\u7528\u9017\u865F\u3001\u7A7A\u683C\u6216\u63DB\u884C\u5206\u9694\uFF0C\u652F\u63F4\u8A5E\u6216 /\u6B63\u5247/\u3002\u5339\u914D\u7684 token \u4E0D\u6703\u88AB\u63D2\u5165\u7A7A\u683C\uFF0C\u6B63\u5728\u8F38\u5165\u7684\u524D\u7DB4\u4E5F\u6703\u66AB\u4E0D\u63D2\u5165\u7A7A\u683C"
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
softSpaceSymbols : {
leftName : "\u81EA\u5B9A\u7FA9\u5DE6\u5074\u8EDF\u7A7A\u683C\u984D\u5916\u7B26\u865F" ,
leftDesc : `\u5E38\u898B\u7684\u5168\u89D2\u6A19\u9EDE\u3001\u82F1\u6587\u5F15\u865F\uFF08' "\uFF09\u548C\u5DE6\u62EC\u865F\uFF08[ ( {\uFF09\u5DF2\u5167\u7F6E\u652F\u6301\u3002\u5728\u6B64\u6DFB\u52A0\u984D\u5916\u7684\u5DE6\u5074\u7B26\u865F\uFF08\u5982 -\uFF09` ,
rightName : "\u81EA\u5B9A\u7FA9\u53F3\u5074\u8EDF\u7A7A\u683C\u984D\u5916\u7B26\u865F" ,
rightDesc : `\u5E38\u898B\u7684\u5168\u89D2\u6A19\u9EDE\u3001\u82F1\u6587\u5F15\u865F\uFF08' "\uFF09\u3001\u53F3\u62EC\u865F\uFF08] ) }\uFF09\u4EE5\u53CA\u82F1\u6587\u534A\u89D2\u6A19\u9EDE\uFF08. , ? ! : ;\uFF09\u5DF2\u5167\u7F6E\u70BA\u53F3\u5074\u8EDF\u7A7A\u683C\u7B26\u865F\u3002\u5728\u6B64\u6DFB\u52A0\u984D\u5916\u7684\u53F3\u5074\u7B26\u865F\uFF08\u5982 -\uFF09`
2026-01-05 13:03:55 +08:00
},
2026-08-21 15:44:03 +08:00
customScriptCategories : {
name : "\u81EA\u5B9A\u7FA9\u8A9E\u8A00/\u7B26\u865F\u96C6" ,
desc : "\u6DFB\u52A0\u81EA\u5B9A\u7FA9\u8A9E\u8A00\u6216\u7B26\u865F\u96C6\u7528\u65BC\u7A7A\u683C\u7B56\u7565" ,
namePlaceholder : "\u540D\u7A31" ,
patternPlaceholder : "\u5B57\u5143\u985E\u6A21\u5F0F"
2026-01-05 13:03:55 +08:00
},
capitalizeFirstLetter : {
name : "\u53E5\u9996\u5B57\u6BCD\u5927\u5BEB" ,
desc : "\u82F1\u6587\u6BCF\u500B\u53E5\u9996\u5B57\u6BCD\u5927\u5BEB\uFF0C\u53EF\u53D6\u6D88"
},
textPunctuationSpace : {
name : "\u6587\u672C\u548C\u6A19\u9EDE\u9593\u7A7A\u683C" ,
desc : "\u5728\u6587\u672C\u548C\u6A19\u9EDE\u4E4B\u9593\u667A\u80FD\u63D2\u5165\u7A7A\u683C"
},
spaceStrategyInlineCode : {
name : "\u884C\u5167\u4EE3\u78BC\u548C\u6587\u672C\u4E4B\u9593\u7684\u7A7A\u683C\u7B56\u7565" ,
2026-08-21 15:44:03 +08:00
desc : "\u5B9A\u7FA9\u884C\u5167\u4EE3\u78BC\u548C\u6587\u672C\u4E4B\u9593\u7684\u7A7A\u683C\u7B56\u7565"
2026-01-05 13:03:55 +08:00
},
spaceStrategyInlineFormula : {
name : "\u884C\u5167\u516C\u5F0F\u548C\u6587\u672C\u4E4B\u9593\u7684\u7A7A\u683C\u7B56\u7565" ,
desc : "\u5B9A\u7FA9\u884C\u5167\u516C\u5F0F\u548C\u6587\u672C\u4E4B\u9593\u7684\u7A7A\u683C\u7B56\u7565"
},
spaceStrategyLinkText : {
name : "\u9023\u7D50\u548C\u6587\u672C\u4E4B\u9593\u7684\u7A7A\u683C\u7B56\u7565" ,
desc : "\u5B9A\u7FA9 [[wikilink]] [mdlink](...) \u548C\u6587\u672C\u4E4B\u9593\u7684\u7A7A\u683C\u7B56\u7565"
},
userDefinedRegexpSwitch : {
name : "\u7528\u6236\u5B9A\u7FA9\u7684\u6B63\u5247\u8868\u9054\u5F0F\u958B\u95DC" ,
desc : "\u81EA\u5B9A\u7FA9\u6B63\u5247\u8868\u9054\u5F0F\u958B\u95DC\uFF0C\u5339\u914D\u5230\u7684\u5167\u5BB9\u4E0D\u9032\u884C\u683C\u5F0F\u5316\uFF0C\u4E14\u53EF\u4EE5\u8A2D\u7F6E\u5339\u914D\u5230\u7684\u5167\u5BB9\u584A\u8207\u5176\u4ED6\u5167\u5BB9\u4E4B\u9593\u7684\u7A7A\u683C\u7B56\u7565"
},
userDefinedRegexp : {
name : "\u7528\u6236\u5B9A\u7FA9\u7684\u6B63\u5247\u8868\u9054\u5F0F" ,
2026-08-21 15:44:03 +08:00
desc : "\u7528\u6236\u81EA\u5B9A\u7FA9\u6B63\u5247\u8868\u9054\u5F0F\uFF0C\u5339\u914D\u5230\u7684\u5167\u5BB9\u4E0D\u9032\u884C\u683C\u5F0F\u5316\uFF0C\u6BCF\u884C\u4E00\u500B\u8868\u9054\u5F0F\uFF0C\u884C\u5C3E\u4E0D\u8981\u96A8\u610F\u52A0\u7A7A\u683C\u3002\u6BCF\u884C\u672B\u5C3E3\u500B\u5B57\u7B26\u7684\u56FA\u5B9A\u70BA|\u548C\u5169\u500B\u7A7A\u683C\u7B56\u7565\u7B26\u865F\uFF0C\u7A7A\u683C\u7B56\u7565\u7B26\u865F\u70BA-=+\uFF0C\u5206\u5225\u4EE3\u8868\u4E0D\u8981\u6C42\u7A7A\u683C(-)\uFF0C\u8EDF\u7A7A\u683C(=)\uFF0C\u56B4\u683C\u7A7A\u683C(+)\u3002\u9019\u5169\u500B\u7A7A\u683C\u7B56\u7565\u7B26\u865F\u5206\u5225\u70BA\u5339\u914D\u5340\u584A\u7684\u5DE6\u53F3\u5169\u908A\u7684\u7A7A\u683C\u7B56\u7565\u3002\u4EE5 // \u958B\u982D\u7684\u884C\u4F5C\u70BA\u8A3B\u91CB"
},
userRulesRespectUserDefinedRegexBlocks : {
name : "\u81EA\u5B9A\u7FA9\u6B63\u5247\u5340\u584A\u540C\u6642\u963B\u6B62\u7528\u6236\u898F\u5247" ,
desc : "\u555F\u7528\u5F8C\uFF0C\u547D\u4E2D\u81EA\u5B9A\u7FA9\u6B63\u5247\u5340\u584A\u7684\u6587\u672C\u5C07\u4E0D\u6703\u89F8\u767C\u81EA\u52D5\u7528\u6236\u898F\u5247\u3002"
2026-01-05 13:03:55 +08:00
},
excludeFoldersFiles : {
name : "\u6392\u9664\u6587\u4EF6\u593E/\u6587\u4EF6" ,
desc : "\u8A72\u63D2\u4EF6\u5C07\u6BCF\u884C\u89E3\u6790\u70BA\u4E00\u500B\u6392\u9664\u6587\u4EF6\u593E\u6216\u6587\u4EF6\u3002\u4F8B\u5982\uFF1ADailyNote/, DailyNote/WeekNotes/, DailyNote/test.md"
},
fixMacOSContextMenu : {
name : "\u4FEE\u5FA9 MacOS \u53F3\u9375\u83DC\u55AE\u5149\u6A19\u4F4D\u7F6E" ,
desc : "\u4FEE\u5FA9 MacOS \u9F20\u6A19\u53F3\u9375\u547C\u51FA\u83DC\u55AE\u6642\u5149\u6A19\u8DF3\u5230\u4E0B\u4E00\u884C\u7684\u554F\u984C (\u9700\u8981\u91CD\u555F Obsidian \u751F\u6548)"
},
fixMicrosoftIME : {
name : "\u4FEE\u5FA9\u5FAE\u8EDF\u8F38\u5165\u6CD5\u554F\u984C" ,
desc : "\u9069\u914D\u820A\u7248\u5FAE\u8EDF\u8F38\u5165\u6CD5"
},
strictLineBreaks : {
name : "\u56B4\u683C\u63DB\u884C\u6A21\u5F0F\u56DE\u8ECA\u589E\u5F37" ,
desc : "\u56B4\u683C\u63DB\u884C\u7684\u8A2D\u7F6E\u4E0B\uFF0C\u5728\u666E\u901A\u6587\u672C\u884C\u9032\u884C\u4E00\u6B21\u56DE\u8ECA\u6703\u6839\u64DA\u6A21\u5F0F\u7522\u751F\u5169\u500B\u63DB\u884C\u7B26\u6216\u8005\u5169\u500B\u7A7A\u683C\u548C\u56DE\u8ECA"
},
enhanceModA : {
name : "\u589E\u5F37 Mod+A \u529F\u80FD" ,
desc : "\u7B2C\u4E00\u6B21\u9078\u4E2D\u7576\u524D\u884C\uFF0C\u7B2C\u4E8C\u6B21\u9078\u4E2D\u7576\u524D\u6587\u672C\u584A\uFF0C\u7B2C\u4E09\u6B21\u9078\u4E2D\u5168\u6587\u3002"
},
collapsePersistentEnter : {
2026-08-21 15:44:03 +08:00
name : "\u6298\u758A\u6A19\u984C\u56DE\u8ECA\u4E0D\u5C55\u958B" ,
desc : "\u5728\u6298\u758A\u7684\u6A19\u984C\u884C\u6309\u56DE\u8ECA\u6642\uFF0C\u4E0D\u5C55\u958B\u6298\u758A\u5167\u5BB9\uFF0C\u76F4\u63A5\u5728\u4E0B\u65B9\u6DFB\u52A0\u540C\u7D1A\u6A19\u984C\u884C"
2026-01-05 13:03:55 +08:00
},
printDebugInfo : {
name : "\u5728\u63A7\u5236\u53F0\u8F38\u51FA\u8ABF\u8A66\u8CC7\u8A0A" ,
desc : "\u5728\u63A7\u5236\u53F0\u8F38\u51FA\u8ABF\u8A66\u8CC7\u8A0A"
},
2026-08-21 15:44:03 +08:00
rulesStoragePath : {
name : "\u898F\u5247\u6A94\u6848\u5132\u5B58\u8DEF\u5F91" ,
desc : "\u8A2D\u5B9A\u898F\u5247\u6A94\u6848\u7684\u5132\u5B58\u8DEF\u5F91\uFF08\u76F8\u5C0D\u65BC\u5EAB\u6839\u76EE\u9304\uFF09\uFF0C\u9078\u64C7\u9810\u8A2D\u5247\u5132\u5B58\u5728\u5916\u639B\u76EE\u9304\u5167" ,
defaultOption : "\u9810\u8A2D\uFF08\u5916\u639B\u76EE\u9304\uFF09" ,
migrateButton : "\u9077\u79FB" ,
migrateDesc : "\u5C07\u898F\u5247\u6A94\u6848\u5F9E\u4E0A\u6B21\u8F09\u5165\u7684\u8DEF\u5F91\u9077\u79FB\u5230\u7576\u524D\u8A2D\u5B9A\u7684\u8DEF\u5F91" ,
migrateSuccess : "\u898F\u5247\u6A94\u6848\u9077\u79FB\u6210\u529F"
},
2026-01-05 13:03:55 +08:00
selectionReplaceRule : {
name : "\u9078\u4E2D\u66FF\u63DB\u898F\u5247" ,
desc : "\u7528\u6236\u5B9A\u7FA9\u7684\u9078\u4E2D\u66FF\u63DB\u898F\u5247"
},
deleteRule : {
name : "\u522A\u9664\u898F\u5247" ,
desc : "\u898F\u5247\uFF1A\u7528 | \u4EE3\u8868\u5149\u6A19\u4F4D\u7F6E\uFF0C\u5FC5\u9808\u5305\u542B\u5149\u6A19\u3002\u63D0\u793A\uFF1A\u4F7F\u7528 | \u8868\u793A\u5149\u6A19\u4F4D\u7F6E\u3002"
},
convertRule : {
name : "\u8F49\u63DB\u898F\u5247" ,
desc : "\u898F\u5247\uFF1A\u7528 | \u4EE3\u8868\u5149\u6A19\u4F4D\u7F6E\uFF0C\u5FC5\u9808\u5305\u542B\u5149\u6A19\u3002\u63D0\u793A\uFF1A\u4F7F\u7528 | \u8868\u793A\u5149\u6A19\u4F4D\u7F6E\u3002"
},
trigger : {
name : "\u89F8\u767C\u5668"
},
left : {
name : "\u5DE6"
},
right : {
name : "\u53F3"
},
oldPattern : {
name : "\u820A\u6A21\u5F0F"
},
newPattern : {
name : "\u65B0\u6A21\u5F0F"
2026-08-21 15:44:03 +08:00
},
ruleEditModal : {
addTitle : "\u65B0\u589E\u898F\u5247" ,
editTitle : "\u7DE8\u8F2F\u898F\u5247" ,
fieldType : "\u985E\u578B" ,
fieldTrigger : "\u6E38\u6A19\u524D\u5339\u914D" ,
fieldTriggerSelectKey : "\u89F8\u767C\u6309\u9375\u5B57\u7B26" ,
fieldTriggerRight : "\u6E38\u6A19\u5F8C\u5339\u914D" ,
hintTriggerEscape : "\\\\\uFF1A\u53CD\u659C\u7DDA\uFF0C\\n\uFF1A\u63DB\u884C\uFF0C\\t\uFF1A\u5236\u8868\u7B26" ,
fieldReplacement : "\u66FF\u63DB\u5167\u5BB9" ,
fieldReplacementDescSelectKey : "${SEL}\uFF1A\u9078\u4E2D\u7684\u6587\u672C\u5167\u5BB9\uFF0C${0:${SEL}}\uFF1A\u6E38\u6A19\u7E7C\u7E8C\u9078\u4E2D\u3002" ,
fieldReplacementDescInputDelete : "[[0]]\uFF1A\u5DE6\u5074\u7B2C0\u6355\u7372\u7D44\uFF0C[[R1]]\uFF1A\u53F3\u5074\u7B2C1\u6355\u7372\u7D44\u3002" ,
fieldIsRegex : "\u4F7F\u7528\u6B63\u5247\u8868\u9054\u5F0F\u5339\u914D" ,
fieldTriggerMode : "\u89F8\u767C\u65B9\u5F0F" ,
fieldScope : "\u4F5C\u7528\u57DF" ,
fieldScopeLanguage : "\u8A9E\u8A00\uFF08\u53EF\u9078\uFF09" ,
fieldRegexFlags : "\u6B63\u5247\u6A19\u8A8C" ,
fieldRegexFlagsDesc : "\u50C5\u652F\u63F4 i / m / u\uFF0C\u4F8B\u5982 im" ,
fieldPriority : "\u512A\u5148\u7D1A" ,
fieldPriorityDesc : "\u6578\u503C\u8D8A\u5C0F\uFF0C\u512A\u5148\u7D1A\u8D8A\u9AD8\uFF0C\u9810\u8A2D 100" ,
fieldDescription : "\u63CF\u8FF0" ,
buttonSave : "\u5132\u5B58" ,
invalidRegex : "\u6B63\u898F\u8868\u9054\u5F0F\u7121\u6548" ,
fieldIsFunction : "\u4F7F\u7528\u51FD\u5F0F\u66FF\u63DB" ,
functionHintInputDelete : "\u53C3\u6578\uFF1AleftMatches (string[])\u3001rightMatches (string[])\u3002\u56DE\u50B3\u5B57\u4E32\u6216 undefined \u8DF3\u904E\u3002" ,
functionHintSelectKey : "\u53C3\u6578\uFF1AselectionText (string)\u3001key (string)\u3002\u56DE\u50B3\u5B57\u4E32\u6216 undefined \u8DF3\u904E\u3002" ,
hintTabstop : "$0\uFF1A\u6E38\u6A19\u4F4D\u7F6E\uFF0C$1/$2\uFF1A\u6309 Tab \u8DF3\u8F49\u7684\u4F4D\u7F6E\uFF0C${1:text}\uFF1A\u8DF3\u8F49\u4E26\u9078\u4E2D text\u3002" ,
functionPlaceholder : "// \u7BC4\u4F8B\uFF1A\nconst d = new Date();\nreturn d.toISOString().slice(0,10) + '$0';" ,
groupMatch : "\u5339\u914D\u689D\u4EF6" ,
groupReplacement : "\u66FF\u63DB" ,
groupOther : "\u5176\u4ED6"
},
ruleType : {
input : "\u8F38\u5165" ,
delete : "\u522A\u9664" ,
selectKey : "\u9078\u4E2D\u66FF\u63DB"
2026-01-05 13:03:55 +08:00
}
},
2026-08-21 15:44:03 +08:00
commands : {
formatArticle : "\u683C\u5F0F\u5316\u5168\u6587" ,
formatSelection : "\u683C\u5F0F\u5316\u9078\u4E2D\u90E8\u5206/\u7576\u524D\u884C" ,
deleteBlankLine : "\u522A\u9664\u9078\u4E2D\u90E8\u5206/\u5168\u6587\u7684\u591A\u9918\u7A7A\u767D\u884C" ,
insertCodeblock : "\u63D2\u5165\u4EE3\u78BC\u584A" ,
switchAutoformat : "\u5207\u63DB\u81EA\u52D5\u683C\u5F0F\u5316\u958B\u95DC" ,
pasteWithoutFormat : "\u7121\u683C\u5F0F\u5316\u7C98\u8CBC" ,
toggleComment : "\u5207\u63DB\u8A3B\u91CB" ,
gotoNewLine : "\u8DF3\u5230\u7576\u524D\u884C\u5F8C\u7684\u65B0\u884C" ,
selectBlock : "\u9078\u64C7\u7576\u524D\u6587\u672C\u584A"
},
2026-01-05 13:03:55 +08:00
headers : {
main : "Obsidian EasyTyping \u63D2\u4EF6" ,
githubDetail : "\u8A73\u60C5\u898B Github\uFF1A" ,
enhancedEditing : "\u589E\u5F37\u7DE8\u8F2F\u8A2D\u7F6E" ,
customizeEditRule : "\u81EA\u5B9A\u7FA9\u7DE8\u8F2F\u8F49\u63DB\u898F\u5247" ,
autoformatSetting : "\u81EA\u52D5\u683C\u5F0F\u5316\u8A2D\u7F6E" ,
2026-08-21 15:44:03 +08:00
detailedSetting : "\u884C\u5167\u5143\u7D20\u9593\u7A7A\u683C" ,
2026-01-05 13:03:55 +08:00
customRegexpBlock : "\u81EA\u5B9A\u7FA9\u6B63\u5247\u5340\u584A" ,
excludeFoldersFiles : "\u6307\u5B9A\u6587\u4EF6\u4E0D\u81EA\u52D5\u683C\u5F0F\u5316" ,
experimentalFeatures : "\u5BE6\u9A57\u529F\u80FD" ,
2026-08-21 15:44:03 +08:00
languagePairSection : "\u8A9E\u8A00\u9593\u7A7A\u683C\u7B56\u7565" ,
addLanguagePair : "\u65B0\u589E\u8A9E\u8A00/\u7B26\u865F\u5C0D\uFF1A" ,
prefixDictSection : "\u524D\u7DB4\u8A5E\u5178" ,
softSpaceSection : "\u81EA\u5B9A\u7FA9\u8EDF\u7A7A\u683C\u7B26\u865F" ,
customScriptSection : "\u81EA\u5B9A\u7FA9\u8A9E\u8A00/\u7B26\u865F\u96C6" ,
spaceStrategyIntro : "\u7A7A\u683C\u7B56\u7565\u8AAA\u660E\uFF1A\n\u7121\u8981\u6C42\uFF1A\u5C0D\u76F8\u95DC\u5340\u584A\u8207\u5DE6\u53F3\u6587\u672C\u6C92\u6709\u7A7A\u683C\u8981\u6C42\u3002\n\u8EDF\u7A7A\u683C\uFF1A\u5C0D\u76F8\u95DC\u5340\u584A\u8207\u5468\u570D\u5340\u584A\u53EA\u8981\u6C42\u6709\u8EDF\u7A7A\u683C\uFF08\u4F8B\u5982\u7576\u524D\u584A\u5DE6\u53F3\u81E8\u8FD1\u6587\u672C\u70BA\u6A19\u9EDE\u7B26\u865F\u6642\uFF0C\u4E0D\u9700\u8981\u518D\u63D2\u5165\u771F\u5BE6\u7A7A\u683C\uFF09\u3002\n\u56B4\u683C\u7A7A\u683C\uFF1A\u7576\u524D\u584A\u8207\u81E8\u8FD1\u6587\u672C\u4E4B\u9593\u56B4\u683C\u6DFB\u52A0\u771F\u5BE6\u7A7A\u683C\u3002" ,
2026-01-05 13:03:55 +08:00
aboutRegexp : {
header : "\u6B63\u5247\u8868\u9054\u5F0F\u76F8\u95DC\u77E5\u8B58\uFF0C\u898B " ,
text : "\u300A\u962E\u4E00\u5CF0\uFF1A\u6B63\u5247\u8868\u9054\u5F0F\u7C21\u660E\u6559\u7A0B\u300B"
},
customizeSelectionRule : "\u81EA\u5B9A\u7FA9\u9078\u4E2D\u6587\u672C\u7DE8\u8F2F\u589E\u5F3A\u898F\u5247" ,
customizeDeleteRule : "\u81EA\u5B9A\u7FA9\u522A\u9664\u7DE8\u8F2F\u589E\u5F3A\u898F\u5247" ,
customizeConvertRule : "\u81EA\u5B9A\u7FA9\u7DE8\u8F2F\u8F49\u63DB\u898F\u5247" ,
2026-08-21 15:44:03 +08:00
editSelectionReplaceRule : "\u7DE8\u8F2F\u9078\u4E2D\u66FF\u63DB\u898F\u5247" ,
builtinRulesSection : "\u5167\u5EFA\u898F\u5247" ,
userRulesSection : "\u4F7F\u7528\u8005\u898F\u5247" ,
deletedRulesSection : "\u5DF2\u522A\u9664\u7684\u5167\u5EFA\u898F\u5247" ,
tabs : {
editEnhance : "\u7DE8\u8F2F\u589E\u5F37" ,
autoFormat : "\u81EA\u52D5\u683C\u5F0F\u5316" ,
builtinRules : "\u5167\u5EFA\u898F\u5247" ,
userRules : "\u81EA\u8A02\u898F\u5247" ,
other : "\u5176\u4ED6\u8A2D\u5B9A"
}
2026-01-05 13:03:55 +08:00
},
dropdownOptions : {
enterTwice : "\u5169\u6B21\u56DE\u8ECA" ,
twoSpace : "\u52A0\u5169\u500B\u7A7A\u683C" ,
mixMode : "\u6DF7\u5408\u6A21\u5F0F" ,
noRequire : "\u7121\u8981\u6C42" ,
softSpace : "\u8EDF\u7A7A\u683C" ,
strictSpace : "\u56B4\u683C\u7A7A\u683C" ,
dummy : "\u5446\u7A7A\u683C" ,
2026-08-21 15:44:03 +08:00
smart : "\u667A\u80FD\u7A7A\u683C" ,
scopeAll : "\u5168\u90E8" ,
scopeText : "\u6587\u672C" ,
scopeFormula : "\u516C\u5F0F" ,
scopeCode : "\u7A0B\u5F0F\u78BC" ,
triggerModeAuto : "\u81EA\u52D5" ,
triggerModeTab : "Tab \u9375" ,
ruleTypeInput : "\u8F38\u5165" ,
ruleTypeDelete : "\u522A\u9664" ,
ruleTypeSelectKey : "\u9078\u4E2D\u66FF\u63DB"
2026-01-05 13:03:55 +08:00
},
toolTip : {
switch : "\u529F\u80FD\u958B\u95DC" ,
editRule : "\u7DE8\u8F2F\u898F\u5247" ,
removeRule : "\u522A\u9664\u898F\u5247" ,
2026-08-21 15:44:03 +08:00
addRule : "\u6DFB\u52A0\u898F\u5247" ,
enableRule : "\u555F\u7528/\u505C\u7528\u898F\u5247" ,
restoreRule : "\u6062\u5FA9\u6B64\u898F\u5247" ,
resetAllRules : "\u91CD\u7F6E\u5167\u5EFA\u898F\u5247" ,
resetSuccess : "\u5167\u5EFA\u898F\u5247\u5DF2\u91CD\u7F6E" ,
exportRules : "\u532F\u51FA\u898F\u5247" ,
importRules : "\u532F\u5165\u898F\u5247" ,
noRulesToExport : "\u6C92\u6709\u53EF\u532F\u51FA\u7684\u4F7F\u7528\u8005\u898F\u5247" ,
importSuccess : "\u532F\u5165\u4E86 %d \u689D\u898F\u5247\uFF0C\u8DF3\u904E %d \u689D\u91CD\u8907\u898F\u5247" ,
importInvalidJson : "\u6A94\u6848\u683C\u5F0F\u932F\u8AA4\uFF1A\u4E0D\u662F\u6709\u6548\u7684 JSON" ,
importNoRules : "\u6A94\u6848\u4E2D\u6C92\u6709\u53EF\u532F\u5165\u7684\u898F\u5247"
2026-01-05 13:03:55 +08:00
},
placeHolder : {
triggerSymbol : "\u89F8\u767C\u7B26" ,
newLeftSideString : "\u5DE6\u908A\u7B26\u865F" ,
newRightSideString : "\u53F3\u908A\u7B26\u865F" ,
addRule : "\u6DFB\u52A0\u898F\u5247" ,
noticeInvaidTrigger : "\u7121\u6548\u7684\u89F8\u767C\u7B26, \u89F8\u767C\u7B26\u5FC5\u9808\u662F\u55AE\u5B57\u7B26\u6216\u8005\u662F \u2014\u2014\u3001\u2026\u2026" ,
noticeWarnTriggerExists : "\u7121\u6548\u898F\u5247! \u89F8\u767C\u7B26 %s \u5DF2\u5B58\u5728" ,
noticeMissingInput : "missing input" ,
beforeDelete : "\u522A\u9664\u524D|" ,
newPattern : "\u89F8\u767C\u898F\u5247\u5F8C\u5B57\u4E32\u6A21\u5F0F" ,
noticeInvaidTriggerPatternContainSymbol : "\u7121\u6548\u898F\u5247, \u8F49\u63DB\u524D\u6A21\u5F0F\u5FC5\u9808\u5305\u542B\u4EE3\u8868\u5149\u6A19\u4F4D\u7F6E\u7684\u7B26\u865F |" ,
beforeConvert : "\u8F49\u63DB\u524D|" ,
noticeInvalidPatternString : "Invalid pattern string!"
},
button : {
update : "\u66F4\u65B0"
2026-08-21 15:44:03 +08:00
},
scriptCategoryLabels : {
chinese : "\u4E2D\u6587" ,
japanese : "\u65E5\u6587" ,
korean : "\u97D3\u6587" ,
cjk : "\u4E2D\u65E5\u97D3" ,
english : "\u82F1\u6587" ,
digit : "\u6578\u5B57" ,
russian : "\u4FC4\u6587" ,
unknown : "\u672A\u77E5"
},
builtinRuleDescriptions : {
"builtin-autopair-input" : "\u8F38\u5165\u5168\u89D2\u62EC\u865F/\u5F15\u865F\u6642\u81EA\u52D5\u88DC\u5168\u914D\u5C0D" ,
"builtin-autopair-jump" : "\u8F38\u5165\u53F3\u5074\u914D\u5C0D\u7B26\u865F\u6642\u81EA\u52D5\u8DF3\u904E\uFF0C\u907F\u514D\u91CD\u8907\u63D2\u5165" ,
"builtin-autopair-delete" : "\u522A\u9664\u5168\u89D2\u62EC\u865F/\u5F15\u865F\u6642\u540C\u6642\u522A\u9664\u914D\u5C0D" ,
"builtin-conv-backtick" : "\u9023\u7E8C\u4E2D\u6587\u9593\u9694\u865F \xB7\xB7 \u8F49\u884C\u5167\u4EE3\u78BC" ,
"builtin-conv-codeblock" : "\u884C\u5167\u4EE3\u78BC\u4E2D\u7E7C\u7E8C\u8F38\u5165 \xB7 \u5347\u7D1A\u70BA\u4EE3\u78BC\u584A" ,
"builtin-conv-formula" : "\uFFE5/$ \u7B26\u865F\u7D44\u5408\u8F49\u884C\u5167\u6216\u584A\u7D1A\u516C\u5F0F" ,
"builtin-conv-linestart" : "\u884C\u9996 \u300B \u8F49\u5F15\u7528\u6A19\u8A18\u3001\u884C\u9996 \u3001 \u8F49\u659C\u7DDA" ,
"builtin-conv-hw2fw" : "CJK\u5B57\u5143\u5F8C\u534A\u89D2\u6A19\u9EDE\u8F49\u5168\u89D2" ,
"builtin-fw2hw-double" : "\u9023\u7E8C\u8F38\u5165\u5169\u500B\u76F8\u540C\u5168\u89D2\u6A19\u9EDE\u8F49\u5C0D\u61C9\u534A\u89D2" ,
"builtin-del-inline-formula" : "\u522A\u9664\u884C\u5167\u516C\u5F0F $...$ \u914D\u5C0D" ,
"builtin-del-highlight" : "\u522A\u9664\u9AD8\u4EAE ==...== \u914D\u5C0D" ,
"builtin-del-block-formula" : "\u522A\u9664\u584A\u7D1A\u516C\u5F0F $$...$$ \u914D\u5C0D" ,
"builtin-del-codeblock" : "\u5FEB\u901F\u522A\u9664\u7A7A\u4EE3\u78BC\u584A" ,
"builtin-del-wikilink" : "\u5FEB\u901F\u522A\u9664\u96D9\u93C8\u53CA\u5D4C\u5165\uFF08![[]]\uFF09" ,
"builtin-sel-wrap-backtick" : "\u9078\u4E2D\u6587\u5B57\u5F8C\u8F38\u5165 \xB7 \u5305\u88F9\u70BA\u884C\u5167\u4EE3\u78BC" ,
"builtin-sel-wrap-symbols" : "\u9078\u4E2D\u6587\u5B57\u5F8C\u8F38\u5165 \u3010/\xA5/\uFFE5 \u5305\u88F9\u70BA []/$$" ,
"builtin-sel-wrap-quotes" : "\u9078\u4E2D\u6587\u5B57\u5F8C\u8F38\u5165\u5168\u89D2\u5F15\u865F\uFF0C\u914D\u5C0D\u5F15\u865F\u5305\u88F9" ,
"builtin-sel-wrap-cjk-brackets" : "\u9078\u4E2D\u6587\u5B57\u5F8C\u8F38\u5165\u300A\uFF08\uFF0C\u914D\u5C0D\u62EC\u865F\u5305\u88F9" ,
"builtin-quote-convert" : "\u8F38\u5165 > \u6216 \u300B \u8F49\u70BA Markdown \u5F15\u7528\u6A19\u8A18" ,
"builtin-quote-space" : "\u5F15\u7528\u6A19\u8A18 > \u5F8C\u81EA\u52D5\u88DC\u7A7A\u683C"
2026-01-05 13:03:55 +08:00
}
};
2026-08-21 15:44:03 +08:00
var zh_TW_default = locale3 ;
2026-01-05 13:03:55 +08:00
2026-08-21 15:44:03 +08:00
// src/lang/locale/ru-RU.ts
var locale4 = {
settings : {
smartPaste : {
name : "\u0423\u043C\u043D\u0430\u044F \u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u0432 \u0441\u043F\u0438\u0441\u043A\u0430\u0445 \u0438 \u0446\u0438\u0442\u0430\u0442\u0430\u0445" ,
desc : "\u041F\u0440\u0438 \u0432\u0441\u0442\u0430\u0432\u043A\u0435 \u0432 \u0441\u043F\u0438\u0441\u043A\u0438 \u0438\u043B\u0438 \u0431\u043B\u043E\u043A\u0438 \u0446\u0438\u0442\u0430\u0442 \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u0434\u043E\u0431\u0430\u0432\u043B\u044F\u044E\u0442\u0441\u044F \u043E\u0442\u0441\u0442\u0443\u043F\u044B \u0438 \u043C\u0430\u0440\u043A\u0435\u0440\u044B \u0441\u043F\u0438\u0441\u043A\u0430/\u0446\u0438\u0442\u0430\u0442\u044B."
},
codeblockEdit : {
name : "\u0423\u043B\u0443\u0447\u0448\u0435\u043D\u0438\u0435 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u043A\u043E\u0434\u043E\u0432\u044B\u0445 \u0431\u043B\u043E\u043A\u043E\u0432" ,
desc : "\u0423\u043B\u0443\u0447\u0448\u0435\u043D\u0438\u0435 \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0432 \u043A\u043E\u0434\u043E\u0432\u044B\u0445 \u0431\u043B\u043E\u043A\u0430\u0445 (Tab, \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435, \u0432\u0441\u0442\u0430\u0432\u043A\u0430, Cmd/Ctrl+A \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435)."
},
backspaceEdit : {
name : "\u0423\u043C\u043D\u044B\u0439 Backspace" ,
desc : "\u0423\u043B\u0443\u0447\u0448\u0435\u043D\u0438\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F \u043F\u0443\u0441\u0442\u044B\u0445 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432 \u0441\u043F\u0438\u0441\u043A\u0430 \u0438\u043B\u0438 \u043F\u0443\u0441\u0442\u044B\u0445 \u0441\u0442\u0440\u043E\u043A \u0441\u0441\u044B\u043B\u043E\u043A."
},
tabOut : {
name : "Tab \u0434\u043B\u044F \u0432\u044B\u0445\u043E\u0434\u0430 \u0438\u0437 \u043F\u0430\u0440\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432" ,
desc : "\u041D\u0430\u0436\u043C\u0438\u0442\u0435 Tab, \u0447\u0442\u043E\u0431\u044B \u043F\u0435\u0440\u0435\u043C\u0435\u0441\u0442\u0438\u0442\u044C \u043A\u0443\u0440\u0441\u043E\u0440 \u0437\u0430 \u043F\u0440\u0435\u0434\u0435\u043B\u044B \u043F\u0430\u0440\u043D\u044B\u0445 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432, \u0442\u0430\u043A\u0438\u0445 \u043A\u0430\u043A \u3010\u3011, \uFF08\uFF09, \u300A\u300B, \u043A\u0430\u0432\u044B\u0447\u043A\u0438 \u0438\u043B\u0438 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u043E\u0433\u043E \u043A\u043E\u0434\u0430."
},
autoFormatting : {
name : "\u0410\u0432\u0442\u043E\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u043F\u0440\u0438 \u043D\u0430\u0431\u043E\u0440\u0435 \u0442\u0435\u043A\u0441\u0442\u0430" ,
desc : "\u0412\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435/\u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u0430\u0432\u0442\u043E\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0442\u0435\u043A\u0441\u0442\u0430 \u0432\u043E \u0432\u0440\u0435\u043C\u044F \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430."
},
autoFormatPaste : {
name : "\u0410\u0432\u0442\u043E\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u043F\u0440\u0438 \u0432\u0441\u0442\u0430\u0432\u043A\u0435" ,
desc : "\u0412\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435/\u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u0430\u0432\u0442\u043E\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u043F\u0440\u0438 \u0432\u0441\u0442\u0430\u0432\u043A\u0435. CMD/CTRL+SHIFT+V (\u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u0431\u0435\u0437 \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F) \u043D\u0435 \u0432\u044B\u0437\u044B\u0432\u0430\u0435\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u043D\u0438\u0435."
},
languagePairSpacing : {
name : "\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u044F\u0437\u044B\u043A\u0430\u043C\u0438" ,
desc : "\u041E\u043F\u0440\u0435\u0434\u0435\u043B\u0438\u0442\u0435, \u043C\u0435\u0436\u0434\u0443 \u043A\u0430\u043A\u0438\u043C\u0438 \u043F\u0430\u0440\u0430\u043C\u0438 \u044F\u0437\u044B\u043A\u043E\u0432/\u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432 \u0434\u043E\u043B\u0436\u043D\u044B \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438 \u0434\u043E\u0431\u0430\u0432\u043B\u044F\u0442\u044C\u0441\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u044B"
},
prefixDictionary : {
name : "\u0421\u043B\u043E\u0432\u0430\u0440\u044C \u043F\u0440\u0435\u0444\u0438\u043A\u0441\u043E\u0432" ,
desc : "\u0420\u0430\u0437\u0434\u0435\u043B\u044F\u0439\u0442\u0435 \u0437\u0430\u043F\u0438\u0441\u0438 \u0437\u0430\u043F\u044F\u0442\u044B\u043C\u0438, \u043F\u0440\u043E\u0431\u0435\u043B\u0430\u043C\u0438 \u0438\u043B\u0438 \u043F\u0435\u0440\u0435\u043D\u043E\u0441\u0430\u043C\u0438 \u0441\u0442\u0440\u043E\u043A. \u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F \u0441\u043B\u043E\u0432\u0430 \u0438 /\u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0435 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u044F/. \u0421\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0449\u0438\u0435 \u0442\u043E\u043A\u0435\u043D\u044B \u043D\u0435 \u043F\u043E\u043B\u0443\u0447\u0430\u0442 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432"
},
softSpaceSymbols : {
leftName : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u043C\u044F\u0433\u043A\u043E\u0433\u043E \u043F\u0440\u043E\u0431\u0435\u043B\u0430 \u0441\u043B\u0435\u0432\u0430" ,
leftDesc : `\u041E\u0431\u0449\u0435\u043F\u0440\u0438\u043D\u044F\u0442\u044B\u0435 \u043F\u043E\u043B\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u044B\u0435 \u0437\u043D\u0430\u043A\u0438 \u043F\u0440\u0435\u043F\u0438\u043D\u0430\u043D\u0438\u044F, \u0430\u043D\u0433\u043B\u0438\u0439\u0441\u043A\u0438\u0435 \u043A\u0430\u0432\u044B\u0447\u043A\u0438 (' "), \u0430 \u0442\u0430\u043A\u0436\u0435 \u043E\u0442\u043A\u0440\u044B\u0432\u0430\u044E\u0449\u0438\u0435 \u0441\u043A\u043E\u0431\u043A\u0438 ([ ( {) \u0443\u0436\u0435 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u044B. \u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0437\u0434\u0435\u0441\u044C \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u0434\u043B\u044F \u043B\u0435\u0432\u043E\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u044B (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, -).` ,
rightName : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u043C\u044F\u0433\u043A\u043E\u0433\u043E \u043F\u0440\u043E\u0431\u0435\u043B\u0430 \u0441\u043F\u0440\u0430\u0432\u0430" ,
rightDesc : `\u041E\u0431\u0449\u0435\u043F\u0440\u0438\u043D\u044F\u0442\u044B\u0435 \u043F\u043E\u043B\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u044B\u0435 \u0437\u043D\u0430\u043A\u0438 \u043F\u0440\u0435\u043F\u0438\u043D\u0430\u043D\u0438\u044F, \u0430\u043D\u0433\u043B\u0438\u0439\u0441\u043A\u0438\u0435 \u043A\u0430\u0432\u044B\u0447\u043A\u0438 (' "), \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u044E\u0449\u0438\u0435 \u0441\u043A\u043E\u0431\u043A\u0438 (] ) }), \u0430 \u0442\u0430\u043A\u0436\u0435 \u0430\u043D\u0433\u043B\u0438\u0439\u0441\u043A\u0430\u044F \u043F\u043E\u043B\u0443\u0448\u0438\u0440\u0438\u043D\u043D\u0430\u044F \u043F\u0443\u043D\u043A\u0442\u0443\u0430\u0446\u0438\u044F (. , ? ! : ;) \u0443\u0436\u0435 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u044B \u043A\u0430\u043A \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u043F\u0440\u0430\u0432\u043E\u0433\u043E \u043C\u044F\u0433\u043A\u043E\u0433\u043E \u043F\u0440\u043E\u0431\u0435\u043B\u0430. \u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u0437\u0434\u0435\u0441\u044C \u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u0434\u043B\u044F \u043F\u0440\u0430\u0432\u043E\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u044B (\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, -).`
},
customScriptCategories : {
name : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0438 \u0441\u043A\u0440\u0438\u043F\u0442\u043E\u0432" ,
desc : "\u0414\u043E\u0431\u0430\u0432\u044C\u0442\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u044F\u0437\u044B\u043A\u0438 \u0438\u043B\u0438 \u043D\u0430\u0431\u043E\u0440\u044B \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432" ,
namePlaceholder : "\u0418\u043C\u044F" ,
patternPlaceholder : "\u0428\u0430\u0431\u043B\u043E\u043D \u043A\u043B\u0430\u0441\u0441\u0430 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432"
},
capitalizeFirstLetter : {
name : "\u0417\u0430\u0433\u043B\u0430\u0432\u043D\u0430\u044F \u0431\u0443\u043A\u0432\u0430 \u0432 \u043D\u0430\u0447\u0430\u043B\u0435 \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u043F\u0440\u0435\u0434\u043B\u043E\u0436\u0435\u043D\u0438\u044F" ,
desc : "\u041F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u043F\u0435\u0440\u0432\u043E\u0439 \u0431\u0443\u043A\u0432\u044B \u043A\u0430\u0436\u0434\u043E\u0433\u043E \u043F\u0440\u0435\u0434\u043B\u043E\u0436\u0435\u043D\u0438\u044F \u0432 \u0430\u043D\u0433\u043B\u0438\u0439\u0441\u043A\u043E\u043C \u0432 \u0437\u0430\u0433\u043B\u0430\u0432\u043D\u0443\u044E."
},
textPunctuationSpace : {
name : "\u0418\u043D\u0442\u0435\u043B\u043B\u0435\u043A\u0442\u0443\u0430\u043B\u044C\u043D\u0430\u044F \u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u043F\u0440\u043E\u0431\u0435\u043B\u0430 \u043C\u0435\u0436\u0434\u0443 \u0442\u0435\u043A\u0441\u0442\u043E\u043C \u0438 \u043F\u0443\u043D\u043A\u0442\u0443\u0430\u0446\u0438\u0435\u0439" ,
desc : "\u0418\u043D\u0442\u0435\u043B\u043B\u0435\u043A\u0442\u0443\u0430\u043B\u044C\u043D\u0430\u044F \u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u043F\u0440\u043E\u0431\u0435\u043B\u0430 \u043C\u0435\u0436\u0434\u0443 \u0442\u0435\u043A\u0441\u0442\u043E\u043C \u0438 \u043F\u0443\u043D\u043A\u0442\u0443\u0430\u0446\u0438\u0435\u0439."
},
spaceStrategyInlineCode : {
name : "\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u043C \u043A\u043E\u0434\u043E\u043C \u0438 \u0442\u0435\u043A\u0441\u0442\u043E\u043C" ,
desc : "\u041E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u043C \u043A\u043E\u0434\u043E\u043C \u0438 \u0442\u0435\u043A\u0441\u0442\u043E\u043C."
},
spaceStrategyInlineFormula : {
name : "\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u043E\u0439 \u0444\u043E\u0440\u043C\u0443\u043B\u043E\u0439 \u0438 \u0442\u0435\u043A\u0441\u0442\u043E\u043C" ,
desc : "\u041E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u043C\u0438 \u0444\u043E\u0440\u043C\u0443\u043B\u0430\u043C\u0438 \u0438 \u0442\u0435\u043A\u0441\u0442\u043E\u043C."
},
spaceStrategyLinkText : {
name : "\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u0441\u0441\u044B\u043B\u043A\u043E\u0439 \u0438 \u0442\u0435\u043A\u0441\u0442\u043E\u043C" ,
desc : "\u041E\u043F\u0440\u0435\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 [[\u0432\u0438\u043A\u0438\u0441\u0441\u044B\u043B\u043A\u0430\u043C\u0438]] [markdown-\u0441\u0441\u044B\u043B\u043A\u0430\u043C\u0438](...) \u0438 \u0442\u0435\u043A\u0441\u0442\u043E\u043C."
},
userDefinedRegexpSwitch : {
name : "\u041F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0445 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0445 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0439" ,
desc : "\u0412\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435/\u0432\u044B\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0445 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0445 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0439, \u043F\u0440\u0435\u0434\u043E\u0442\u0432\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0438 \u0443\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0430 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0449\u0438\u043C \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u044B\u043C \u0438 \u0434\u0440\u0443\u0433\u0438\u043C \u0442\u0435\u043A\u0441\u0442\u043E\u043C."
},
userDefinedRegexp : {
name : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u043E\u0435 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u043E\u0435 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435, \u043E\u0434\u043D\u043E \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0430 \u0441\u0442\u0440\u043E\u043A\u0443" ,
desc : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u043E\u0435 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u043E\u0435 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435, \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0449\u0435\u0435 \u0441 \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u044B\u043C, \u043D\u0435 \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044F, \u043E\u0434\u043D\u043E \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u043D\u0430 \u0441\u0442\u0440\u043E\u043A\u0443, \u043D\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u044F\u0439\u0442\u0435 \u043F\u0440\u043E\u0431\u0435\u043B\u044B \u0432 \u043A\u043E\u043D\u0446\u0435 \u0441\u0442\u0440\u043E\u043A\u0438.\u041A\u043E\u043D\u0435\u0446 \u043A\u0430\u0436\u0434\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u0438 \u0444\u0438\u043A\u0441\u0438\u0440\u043E\u0432\u0430\u043D \u0442\u0440\u0435\u043C\u044F \u0441\u0438\u043C\u0432\u043E\u043B\u0430\u043C\u0438: | \u0438 \u0434\u0432\u0443\u043C\u044F \u0441\u0438\u043C\u0432\u043E\u043B\u0430\u043C\u0438 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432, \u0441\u0438\u043C\u0432\u043E\u043B\u044B \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 - \u044D\u0442\u043E - = +, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043D\u043D\u043E \u043E\u0431\u043E\u0437\u043D\u0430\u0447\u0430\u044E\u0442 \u043E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 (-), \u043C\u044F\u0433\u043A\u0438\u0435 \u043F\u0440\u043E\u0431\u0435\u043B\u044B (=), \u0441\u0442\u0440\u043E\u0433\u0438\u0435 \u043F\u0440\u043E\u0431\u0435\u043B\u044B (+).\u042D\u0442\u0438 \u0434\u0432\u0430 \u0441\u0438\u043C\u0432\u043E\u043B\u0430 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u044F\u0432\u043B\u044F\u044E\u0442\u0441\u044F \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0435\u0439 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u0434\u043B\u044F \u043B\u0435\u0432\u043E\u0439 \u0438 \u043F\u0440\u0430\u0432\u043E\u0439 \u0441\u0442\u043E\u0440\u043E\u043D \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0449\u0435\u0433\u043E \u0431\u043B\u043E\u043A\u0430 \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043D\u043D\u043E. \u0421\u0442\u0440\u043E\u043A\u0438, \u043D\u0430\u0447\u0438\u043D\u0430\u044E\u0449\u0438\u0435\u0441\u044F \u0441 //, \u043E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u044E\u0442\u0441\u044F \u043A\u0430\u043A \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0438"
},
userRulesRespectUserDefinedRegexBlocks : {
name : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0443\u0432\u0430\u0436\u0430\u044E\u0442 \u0431\u043B\u043E\u043A\u0438 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0445 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0445 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0439" ,
desc : "\u041F\u0440\u0438 \u0432\u043A\u043B\u044E\u0447\u0435\u043D\u0438\u0438 \u0442\u0435\u043A\u0441\u0442, \u0441\u043E\u0432\u043F\u0430\u0434\u0430\u044E\u0449\u0438\u0439 \u0441 \u0431\u043B\u043E\u043A\u0430\u043C\u0438 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0445 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0445 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0439, \u043D\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043F\u0443\u0441\u043A\u0430\u0442\u044C \u0430\u0432\u0442\u043E\u043C\u0430\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0435 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430."
},
excludeFoldersFiles : {
name : "\u0418\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043F\u0430\u043F\u043A\u0438/\u0444\u0430\u0439\u043B\u044B" ,
desc : "\u042D\u0442\u043E\u0442 \u043F\u043B\u0430\u0433\u0438\u043D \u0431\u0443\u0434\u0435\u0442 \u043E\u0431\u0440\u0430\u0431\u0430\u0442\u044B\u0432\u0430\u0442\u044C \u043A\u0430\u0436\u0434\u0443\u044E \u0441\u0442\u0440\u043E\u043A\u0443 \u043A\u0430\u043A \u0438\u0441\u043A\u043B\u044E\u0447\u0430\u0435\u043C\u0443\u044E \u043F\u0430\u043F\u043A\u0443 \u0438\u043B\u0438 \u0444\u0430\u0439\u043B. \u041D\u0430\u043F\u0440\u0438\u043C\u0435\u0440: DailyNote/, DailyNote/WeekNotes/, DailyNote/test.md"
},
fixMacOSContextMenu : {
name : "\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u043E\u043B\u043E\u0436\u0435\u043D\u0438\u044F \u043A\u0443\u0440\u0441\u043E\u0440\u0430 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u043D\u043E\u0433\u043E \u043C\u0435\u043D\u044E MacOS (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A Obsidian)" ,
desc : "\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B, \u043A\u043E\u0433\u0434\u0430 \u043A\u0443\u0440\u0441\u043E\u0440 \u043F\u0435\u0440\u0435\u0441\u043A\u0430\u043A\u0438\u0432\u0430\u0435\u0442 \u043D\u0430 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0443\u044E \u0441\u0442\u0440\u043E\u043A\u0443 \u043F\u0440\u0438 \u0432\u044B\u0437\u043E\u0432\u0435 \u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442\u043D\u043E\u0433\u043E \u043C\u0435\u043D\u044E \u043D\u0430 MacOS (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u043F\u0435\u0440\u0435\u0437\u0430\u043F\u0443\u0441\u043A Obsidian)."
},
fixMicrosoftIME : {
name : "\u0418\u0441\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B \u0441 Microsoft Input Method" ,
desc : "\u0410\u0434\u0430\u043F\u0442\u0430\u0446\u0438\u044F \u0434\u043B\u044F \u0441\u0442\u0430\u0440\u044B\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 Microsoft Input Method."
},
strictLineBreaks : {
name : "\u0420\u0435\u0436\u0438\u043C \u0441\u0442\u0440\u043E\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u044B\u0432\u043E\u0432 \u0441\u0442\u0440\u043E\u043A" ,
desc : "\u0412 \u0440\u0435\u0436\u0438\u043C\u0435 \u0441\u0442\u0440\u043E\u0433\u0438\u0445 \u0440\u0430\u0437\u0440\u044B\u0432\u043E\u0432 \u0441\u0442\u0440\u043E\u043A, \u043E\u0434\u043D\u043E\u043A\u0440\u0430\u0442\u043D\u043E\u0435 \u043D\u0430\u0436\u0430\u0442\u0438\u0435 Enter \u0432 \u043E\u0431\u044B\u0447\u043D\u044B\u0445 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u044B\u0445 \u0441\u0442\u0440\u043E\u043A\u0430\u0445 \u0441\u043E\u0437\u0434\u0430\u0441\u0442 \u0434\u0432\u0430 \u0440\u0430\u0437\u0440\u044B\u0432\u0430 \u0441\u0442\u0440\u043E\u043A\u0438 \u0438\u043B\u0438 \u0434\u0432\u0430 \u043F\u0440\u043E\u0431\u0435\u043B\u0430 \u0438 Enter."
},
enhanceModA : {
name : "\u0423\u043B\u0443\u0447\u0448\u0438\u0442\u044C \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435 Mod+A \u0432 \u0442\u0435\u043A\u0441\u0442\u0435" ,
desc : "\u0421\u043D\u0430\u0447\u0430\u043B\u0430 \u0432\u044B\u0434\u0435\u043B\u0438\u0442\u0435 \u0442\u0435\u043A\u0443\u0449\u0443\u044E \u0441\u0442\u0440\u043E\u043A\u0443, \u0437\u0430\u0442\u0435\u043C \u0432\u044B\u0434\u0435\u043B\u0438\u0442\u0435 \u0442\u0435\u043A\u0443\u0449\u0438\u0439 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u044B\u0439 \u0431\u043B\u043E\u043A, \u0437\u0430\u0442\u0435\u043C \u0432\u044B\u0434\u0435\u043B\u0438\u0442\u0435 \u0432\u0435\u0441\u044C \u0442\u0435\u043A\u0441\u0442."
},
collapsePersistentEnter : {
name : "Enter \u0431\u0435\u0437 \u0440\u0430\u0437\u0432\u043E\u0440\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0430" ,
desc : "\u041F\u0440\u0438 \u043D\u0430\u0436\u0430\u0442\u0438\u0438 Enter \u043D\u0430 \u0441\u0432\u0451\u0440\u043D\u0443\u0442\u043E\u043C \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u0442 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0442\u043E\u0433\u043E \u0436\u0435 \u0443\u0440\u043E\u0432\u043D\u044F, \u043D\u0435 \u0440\u0430\u0437\u0432\u043E\u0440\u0430\u0447\u0438\u0432\u0430\u044F \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u043C\u043E\u0435."
},
printDebugInfo : {
name : "\u0412\u044B\u0432\u043E\u0434 \u043E\u0442\u043B\u0430\u0434\u043E\u0447\u043D\u043E\u0439 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0438 \u0432 \u043A\u043E\u043D\u0441\u043E\u043B\u044C" ,
desc : "\u0412\u044B\u0432\u043E\u0434 \u043E\u0442\u043B\u0430\u0434\u043E\u0447\u043D\u043E\u0439 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0438 \u0432 \u043A\u043E\u043D\u0441\u043E\u043B\u044C."
},
rulesStoragePath : {
name : "\u041F\u0443\u0442\u044C \u0445\u0440\u0430\u043D\u0435\u043D\u0438\u044F \u0444\u0430\u0439\u043B\u043E\u0432 \u043F\u0440\u0430\u0432\u0438\u043B" ,
desc : "\u0423\u043A\u0430\u0436\u0438\u0442\u0435 \u043F\u0443\u0442\u044C \u0445\u0440\u0430\u043D\u0435\u043D\u0438\u044F \u0444\u0430\u0439\u043B\u043E\u0432 \u043F\u0440\u0430\u0432\u0438\u043B (\u043E\u0442\u043D\u043E\u0441\u0438\u0442\u0435\u043B\u044C\u043D\u043E \u043A\u043E\u0440\u043D\u044F \u0445\u0440\u0430\u043D\u0438\u043B\u0438\u0449\u0430). \u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E \u0434\u043B\u044F \u0445\u0440\u0430\u043D\u0435\u043D\u0438\u044F \u0432 \u043A\u0430\u0442\u0430\u043B\u043E\u0433\u0435 \u043F\u043B\u0430\u0433\u0438\u043D\u0430" ,
defaultOption : "\u041F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E (\u043A\u0430\u0442\u0430\u043B\u043E\u0433 \u043F\u043B\u0430\u0433\u0438\u043D\u0430)" ,
migrateButton : "\u041F\u0435\u0440\u0435\u043D\u0435\u0441\u0442\u0438" ,
migrateDesc : "\u041F\u0435\u0440\u0435\u043D\u0435\u0441\u0442\u0438 \u0444\u0430\u0439\u043B\u044B \u043F\u0440\u0430\u0432\u0438\u043B \u0438\u0437 \u0440\u0430\u043D\u0435\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043D\u043E\u0433\u043E \u043F\u0443\u0442\u0438 \u0432 \u0442\u0435\u043A\u0443\u0449\u0438\u0439" ,
migrateSuccess : "\u0424\u0430\u0439\u043B\u044B \u043F\u0440\u0430\u0432\u0438\u043B \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u043F\u0435\u0440\u0435\u043D\u0435\u0441\u0435\u043D\u044B"
},
selectionReplaceRule : {
name : "\u041F\u0440\u0430\u0432\u0438\u043B\u043E \u0437\u0430\u043C\u0435\u043D\u044B \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u0442\u0435\u043A\u0441\u0442\u0430" ,
desc : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u043E\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u043E \u0437\u0430\u043C\u0435\u043D\u044B \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u0442\u0435\u043A\u0441\u0442\u0430"
},
deleteRule : {
name : "\u041F\u0440\u0430\u0432\u0438\u043B\u043E \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F" ,
desc : "\u041F\u0440\u0430\u0432\u0438\u043B\u043E: \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 | \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u0438\u044F \u043F\u043E\u0437\u0438\u0446\u0438\u0438 \u043A\u0443\u0440\u0441\u043E\u0440\u0430. \u041F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430: \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435 | \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u0438\u044F \u043F\u043E\u0437\u0438\u0446\u0438\u0438 \u043A\u0443\u0440\u0441\u043E\u0440\u0430."
},
convertRule : {
name : "\u041F\u0440\u0430\u0432\u0438\u043B\u043E \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u044F" ,
desc : "\u041F\u0440\u0430\u0432\u0438\u043B\u043E: \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 | \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u0438\u044F \u043F\u043E\u0437\u0438\u0446\u0438\u0438 \u043A\u0443\u0440\u0441\u043E\u0440\u0430. \u041F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430: \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u043D\u0438\u0435 | \u0434\u043B\u044F \u0443\u043A\u0430\u0437\u0430\u043D\u0438\u044F \u043F\u043E\u0437\u0438\u0446\u0438\u0438 \u043A\u0443\u0440\u0441\u043E\u0440\u0430."
},
trigger : {
name : "\u0422\u0440\u0438\u0433\u0433\u0435\u0440"
},
left : {
name : "\u041B\u0435\u0432\u044B\u0439"
},
right : {
name : "\u041F\u0440\u0430\u0432\u044B\u0439"
},
oldPattern : {
name : "\u0421\u0442\u0430\u0440\u044B\u0439 \u0448\u0430\u0431\u043B\u043E\u043D"
},
newPattern : {
name : "\u041D\u043E\u0432\u044B\u0439 \u0448\u0430\u0431\u043B\u043E\u043D"
},
ruleEditModal : {
addTitle : "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
editTitle : "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
fieldType : "\u0422\u0438\u043F" ,
fieldTrigger : "\u0421\u043E\u0432\u043F\u0430\u0434\u0435\u043D\u0438\u0435 \u043F\u0435\u0440\u0435\u0434 \u043A\u0443\u0440\u0441\u043E\u0440\u043E\u043C" ,
fieldTriggerSelectKey : "\u0421\u0438\u043C\u0432\u043E\u043B \u0437\u0430\u043F\u0443\u0441\u043A\u0430" ,
fieldTriggerRight : "\u0421\u043E\u0432\u043F\u0430\u0434\u0435\u043D\u0438\u0435 \u043F\u043E\u0441\u043B\u0435 \u043A\u0443\u0440\u0441\u043E\u0440\u0430" ,
hintTriggerEscape : "\\\\: \u043E\u0431\u0440\u0430\u0442\u043D\u0430\u044F \u043A\u043E\u0441\u0430\u044F \u0447\u0435\u0440\u0442\u0430, \\n: \u043D\u043E\u0432\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430, \\t: \u0442\u0430\u0431\u0443\u043B\u044F\u0446\u0438\u044F" ,
fieldReplacement : "\u0417\u0430\u043C\u0435\u043D\u0430" ,
fieldReplacementDescSelectKey : "${SEL}: \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0439 \u0442\u0435\u043A\u0441\u0442, ${0:${SEL}}: \u043E\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0442\u0435\u043A\u0441\u0442 \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u043C." ,
fieldReplacementDescInputDelete : "[[0]]: 0-\u044F \u043B\u0435\u0432\u0430\u044F \u0433\u0440\u0443\u043F\u043F\u0430 \u0437\u0430\u0445\u0432\u0430\u0442\u0430, [[R1]]: 1-\u044F \u043F\u0440\u0430\u0432\u0430\u044F \u0433\u0440\u0443\u043F\u043F\u0430 \u0437\u0430\u0445\u0432\u0430\u0442\u0430." ,
fieldIsRegex : "\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0435 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u044F" ,
fieldTriggerMode : "\u0420\u0435\u0436\u0438\u043C \u0437\u0430\u043F\u0443\u0441\u043A\u0430" ,
fieldScope : "\u041E\u0431\u043B\u0430\u0441\u0442\u044C" ,
fieldScopeLanguage : "\u042F\u0437\u044B\u043A (\u043D\u0435\u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E)" ,
fieldRegexFlags : "\u0424\u043B\u0430\u0433\u0438 regex" ,
fieldRegexFlagsDesc : "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044E\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E i / m / u, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 im" ,
fieldPriority : "\u041F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442" ,
fieldPriorityDesc : "\u0427\u0435\u043C \u043C\u0435\u043D\u044C\u0448\u0435 \u0447\u0438\u0441\u043B\u043E, \u0442\u0435\u043C \u0432\u044B\u0448\u0435 \u043F\u0440\u0438\u043E\u0440\u0438\u0442\u0435\u0442, \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 100" ,
fieldDescription : "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435" ,
buttonSave : "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C" ,
invalidRegex : "\u041D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u043E\u0435 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u043E\u0435 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435" ,
fieldIsFunction : "\u0418\u0441\u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u044C \u0444\u0443\u043D\u043A\u0446\u0438\u044E \u0437\u0430\u043C\u0435\u043D\u044B" ,
functionHintInputDelete : "\u0410\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B: leftMatches (string[]), rightMatches (string[]). \u0412\u0435\u0440\u043D\u0438\u0442\u0435 \u0441\u0442\u0440\u043E\u043A\u0443 \u0438\u043B\u0438 undefined \u0434\u043B\u044F \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430." ,
functionHintSelectKey : "\u0410\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u044B: selectionText (string), key (string). \u0412\u0435\u0440\u043D\u0438\u0442\u0435 \u0441\u0442\u0440\u043E\u043A\u0443 \u0438\u043B\u0438 undefined \u0434\u043B\u044F \u043F\u0440\u043E\u043F\u0443\u0441\u043A\u0430." ,
hintTabstop : "$0: \u043F\u043E\u0437\u0438\u0446\u0438\u044F \u043A\u0443\u0440\u0441\u043E\u0440\u0430, $1/$2: \u043F\u043E\u0437\u0438\u0446\u0438\u0438 \u043F\u0435\u0440\u0435\u0445\u043E\u0434\u0430 Tab, ${1:text}: \u043F\u0435\u0440\u0435\u0439\u0442\u0438 \u0438 \u0432\u044B\u0434\u0435\u043B\u0438\u0442\u044C text." ,
functionPlaceholder : "// \u041F\u0440\u0438\u043C\u0435\u0440:\nconst d = new Date();\nreturn d.toISOString().slice(0,10) + '$0';" ,
groupMatch : "\u0423\u0441\u043B\u043E\u0432\u0438\u044F \u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044F" ,
groupReplacement : "\u0417\u0430\u043C\u0435\u043D\u0430" ,
groupOther : "\u041F\u0440\u043E\u0447\u0435\u0435"
},
ruleType : {
input : "\u0412\u0432\u043E\u0434" ,
delete : "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435" ,
selectKey : "\u0417\u0430\u043C\u0435\u043D\u0430 \u0432\u044B\u0431\u043E\u0440\u0430"
}
},
commands : {
formatArticle : "\u0424\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0442\u0435\u043A\u0443\u0449\u0443\u044E \u0441\u0442\u0430\u0442\u044C\u044E" ,
formatSelection : "\u0424\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u044B\u0439 \u0442\u0435\u043A\u0441\u0442 \u0438\u043B\u0438 \u0442\u0435\u043A\u0443\u0449\u0443\u044E \u0441\u0442\u0440\u043E\u043A\u0443" ,
deleteBlankLine : "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043F\u0443\u0441\u0442\u044B\u0435 \u0441\u0442\u0440\u043E\u043A\u0438 \u0432 \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u043E\u043C \u0438\u043B\u0438 \u0432\u0441\u0435\u0439 \u0441\u0442\u0430\u0442\u044C\u0435" ,
insertCodeblock : "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0431\u043B\u043E\u043A \u043A\u043E\u0434\u0430 \u0441/\u0431\u0435\u0437 \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435\u043C" ,
switchAutoformat : "\u041F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u0430\u0432\u0442\u043E\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435" ,
pasteWithoutFormat : "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044C \u0431\u0435\u0437 \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F" ,
toggleComment : "\u041F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439" ,
gotoNewLine : "\u041F\u0435\u0440\u0435\u0439\u0442\u0438 \u043A \u043D\u043E\u0432\u043E\u0439 \u0441\u0442\u0440\u043E\u043A\u0435 \u043F\u043E\u0441\u043B\u0435 \u0442\u0435\u043A\u0443\u0449\u0435\u0439" ,
selectBlock : "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0442\u0435\u043A\u0443\u0449\u0438\u0439 \u0442\u0435\u043A\u0441\u0442\u043E\u0432\u044B\u0439 \u0431\u043B\u043E\u043A"
},
headers : {
main : "\u041F\u043B\u0430\u0433\u0438\u043D Obsidian EasyTyping" ,
githubDetail : "\u041F\u043E\u0434\u0440\u043E\u0431\u043D\u0435\u0435 \u043D\u0430 Github: " ,
enhancedEditing : "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u0443\u043B\u0443\u0447\u0448\u0435\u043D\u043D\u043E\u0433\u043E \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F" ,
customizeEditRule : "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u044F \u0440\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F" ,
autoformatSetting : "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u0430\u0432\u0442\u043E\u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F" ,
detailedSetting : "\u041F\u0440\u043E\u0431\u0435\u043B\u044B \u043C\u0435\u0436\u0434\u0443 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u043C\u0438 \u044D\u043B\u0435\u043C\u0435\u043D\u0442\u0430\u043C\u0438" ,
customRegexpBlock : "\u0411\u043B\u043E\u043A \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0445 \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0445 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0439" ,
excludeFoldersFiles : "\u0418\u0441\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043F\u0430\u043F\u043A\u0438/\u0444\u0430\u0439\u043B\u044B" ,
experimentalFeatures : "\u042D\u043A\u0441\u043F\u0435\u0440\u0438\u043C\u0435\u043D\u0442\u0430\u043B\u044C\u043D\u044B\u0435 \u0444\u0443\u043D\u043A\u0446\u0438\u0438" ,
languagePairSection : "\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u044F\u0437\u044B\u043A\u0430\u043C\u0438" ,
addLanguagePair : "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043D\u043E\u0432\u0443\u044E \u043F\u0430\u0440\u0443 \u044F\u0437\u044B\u043A\u043E\u0432/\u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432:" ,
prefixDictSection : "\u0421\u043B\u043E\u0432\u0430\u0440\u044C \u043F\u0440\u0435\u0444\u0438\u043A\u0441\u043E\u0432" ,
softSpaceSection : "\u0421\u0438\u043C\u0432\u043E\u043B\u044B \u043C\u044F\u0433\u043A\u043E\u0433\u043E \u043F\u0440\u043E\u0431\u0435\u043B\u0430" ,
customScriptSection : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0438 \u0441\u043A\u0440\u0438\u043F\u0442\u043E\u0432" ,
spaceStrategyIntro : "\u0421\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044F \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432:\n\u041D\u0435\u0442 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u0439: \u041D\u0435\u0442 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u0439 \u043A \u043F\u0440\u043E\u0431\u0435\u043B\u0430\u043C \u043C\u0435\u0436\u0434\u0443 \u044D\u0442\u0438\u043C \u0431\u043B\u043E\u043A\u043E\u043C \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0438 \u0438 \u043E\u043A\u0440\u0443\u0436\u0430\u044E\u0449\u0438\u043C \u0442\u0435\u043A\u0441\u0442\u043E\u043C.\n\u041C\u044F\u0433\u043A\u0438\u0439 \u043F\u0440\u043E\u0431\u0435\u043B: \u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044F \u0442\u043E\u043B\u044C\u043A\u043E \u043C\u044F\u0433\u043A\u0438\u0439 \u043F\u0440\u043E\u0431\u0435\u043B \u043C\u0435\u0436\u0434\u0443 \u044D\u0442\u0438\u043C \u0431\u043B\u043E\u043A\u043E\u043C \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0438 \u0438 \u043E\u043A\u0440\u0443\u0436\u0430\u044E\u0449\u0438\u043C\u0438 \u0431\u043B\u043E\u043A\u0430\u043C\u0438.\n\u0421\u0442\u0440\u043E\u0433\u0438\u0439 \u043F\u0440\u043E\u0431\u0435\u043B: \u0421\u0442\u0440\u043E\u0433\u043E\u0435 \u0434\u043E\u0431\u0430\u0432\u043B\u0435\u043D\u0438\u0435 \u043F\u0440\u043E\u0431\u0435\u043B\u043E\u0432 \u043C\u0435\u0436\u0434\u0443 \u0442\u0435\u043A\u0443\u0449\u0438\u043C \u0431\u043B\u043E\u043A\u043E\u043C \u0438 \u043F\u0440\u0438\u043B\u0435\u0433\u0430\u044E\u0449\u0438\u043C \u0442\u0435\u043A\u0441\u0442\u043E\u043C." ,
aboutRegexp : {
header : "\u0414\u043B\u044F \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u0438 \u043E \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u0445 \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u044F\u0445 \u0441\u043C. " ,
text : "Yifeng Nguyen: \u041A\u0440\u0430\u0442\u043A\u043E\u0435 \u0440\u0443\u043A\u043E\u0432\u043E\u0434\u0441\u0442\u0432\u043E \u043F\u043E \u0440\u0435\u0433\u0443\u043B\u044F\u0440\u043D\u044B\u043C \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u044F\u043C"
},
customizeSelectionRule : "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0437\u0430\u043C\u0435\u043D\u044B \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u0442\u0435\u043A\u0441\u0442\u0430" ,
customizeDeleteRule : "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F" ,
customizeConvertRule : "\u041D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0430 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u044F" ,
editSelectionReplaceRule : "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0437\u0430\u043C\u0435\u043D\u044B \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u0442\u0435\u043A\u0441\u0442\u0430" ,
builtinRulesSection : "\u0412\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430" ,
userRulesSection : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430" ,
deletedRulesSection : "\u0423\u0434\u0430\u043B\u0451\u043D\u043D\u044B\u0435 \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430" ,
tabs : {
editEnhance : "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u0435" ,
autoFormat : "\u0410\u0432\u0442\u043E\u0444\u043E\u0440\u043C\u0430\u0442" ,
builtinRules : "\u0412\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0435" ,
userRules : "\u041F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0435" ,
other : "\u041F\u0440\u043E\u0447\u0435\u0435"
}
},
dropdownOptions : {
enterTwice : "\u0414\u0432\u0430\u0436\u0434\u044B \u043D\u0430\u0436\u043C\u0438\u0442\u0435 Enter" ,
twoSpace : "\u0414\u0432\u0430 \u043F\u0440\u043E\u0431\u0435\u043B\u0430" ,
mixMode : "\u0421\u043C\u0435\u0448\u0430\u043D\u043D\u044B\u0439 \u0440\u0435\u0436\u0438\u043C" ,
noRequire : "\u041D\u0435\u0442 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u0439" ,
softSpace : "\u041C\u044F\u0433\u043A\u0438\u0439 \u043F\u0440\u043E\u0431\u0435\u043B" ,
strictSpace : "\u0421\u0442\u0440\u043E\u0433\u0438\u0439 \u043F\u0440\u043E\u0431\u0435\u043B" ,
dummy : "\u0424\u0438\u043A\u0442\u0438\u0432\u043D\u044B\u0439" ,
smart : "\u0423\u043C\u043D\u044B\u0439" ,
scopeAll : "\u0412\u0441\u0435" ,
scopeText : "\u0422\u0435\u043A\u0441\u0442" ,
scopeFormula : "\u0424\u043E\u0440\u043C\u0443\u043B\u0430" ,
scopeCode : "\u041A\u043E\u0434" ,
triggerModeAuto : "\u0410\u0432\u0442\u043E" ,
triggerModeTab : "Tab" ,
ruleTypeInput : "\u0412\u0432\u043E\u0434" ,
ruleTypeDelete : "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435" ,
ruleTypeSelectKey : "\u0417\u0430\u043C\u0435\u043D\u0430 \u0432\u044B\u0431\u043E\u0440\u0430"
},
toolTip : {
switch : "\u041F\u0435\u0440\u0435\u043A\u043B\u044E\u0447\u0438\u0442\u044C" ,
editRule : "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
removeRule : "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
addRule : "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
enableRule : "\u0412\u043A\u043B\u044E\u0447\u0438\u0442\u044C/\u0412\u044B\u043A\u043B\u044E\u0447\u0438\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
restoreRule : "\u0412\u043E\u0441\u0441\u0442\u0430\u043D\u043E\u0432\u0438\u0442\u044C \u044D\u0442\u043E \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
resetAllRules : "\u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430" ,
resetSuccess : "\u0412\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u044B\u0435 \u043F\u0440\u0430\u0432\u0438\u043B\u0430 \u0443\u0441\u043F\u0435\u0448\u043D\u043E \u0441\u0431\u0440\u043E\u0448\u0435\u043D\u044B" ,
exportRules : "\u042D\u043A\u0441\u043F\u043E\u0440\u0442 \u043F\u0440\u0430\u0432\u0438\u043B" ,
importRules : "\u0418\u043C\u043F\u043E\u0440\u0442 \u043F\u0440\u0430\u0432\u0438\u043B" ,
noRulesToExport : "\u041D\u0435\u0442 \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044C\u0441\u043A\u0438\u0445 \u043F\u0440\u0430\u0432\u0438\u043B \u0434\u043B\u044F \u044D\u043A\u0441\u043F\u043E\u0440\u0442\u0430" ,
importSuccess : "\u0418\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u043D\u043E %d \u043F\u0440\u0430\u0432\u0438\u043B, \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D\u043E %d \u0434\u0443\u0431\u043B\u0438\u043A\u0430\u0442\u043E\u0432" ,
importInvalidJson : "\u041E\u0448\u0438\u0431\u043A\u0430 \u0444\u043E\u0440\u043C\u0430\u0442\u0430: \u043D\u0435\u0434\u043E\u043F\u0443\u0441\u0442\u0438\u043C\u044B\u0439 JSON" ,
importNoRules : "\u0412 \u0444\u0430\u0439\u043B\u0435 \u043D\u0435\u0442 \u043F\u0440\u0430\u0432\u0438\u043B \u0434\u043B\u044F \u0438\u043C\u043F\u043E\u0440\u0442\u0430"
},
placeHolder : {
triggerSymbol : "\u0421\u0438\u043C\u0432\u043E\u043B \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430" ,
newLeftSideString : "\u041D\u043E\u0432\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u0441 \u043B\u0435\u0432\u043E\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u044B" ,
newRightSideString : "\u041D\u043E\u0432\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u0441 \u043F\u0440\u0430\u0432\u043E\u0439 \u0441\u0442\u043E\u0440\u043E\u043D\u044B" ,
addRule : "\u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u043F\u0440\u0430\u0432\u0438\u043B\u043E" ,
noticeInvaidTrigger : "\u041D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u0442\u0440\u0438\u0433\u0433\u0435\u0440, \u0442\u0440\u0438\u0433\u0433\u0435\u0440 \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u043C \u0434\u043B\u0438\u043D\u043E\u0439 1 \u0438\u043B\u0438 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u043C \u2014\u2014, \u2026\u2026" ,
noticeWarnTriggerExists : "\u0412\u043D\u0438\u043C\u0430\u043D\u0438\u0435! \u0422\u0440\u0438\u0433\u0433\u0435\u0440 %s \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442!" ,
noticeMissingInput : "\u041E\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u0432\u043E\u0434" ,
beforeDelete : "\u0414\u043E \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u044F" ,
newPattern : "\u041D\u043E\u0432\u044B\u0439 \u0448\u0430\u0431\u043B\u043E\u043D" ,
noticeInvaidTriggerPatternContainSymbol : "\u041D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0439 \u0442\u0440\u0438\u0433\u0433\u0435\u0440, \u0448\u0430\u0431\u043B\u043E\u043D \u0434\u043E\u043B\u0436\u0435\u043D \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C \u0441\u0438\u043C\u0432\u043E\u043B |, \u0443\u043A\u0430\u0437\u044B\u0432\u0430\u044E\u0449\u0438\u0439 \u043D\u0430 \u043F\u043E\u0437\u0438\u0446\u0438\u044E \u043A\u0443\u0440\u0441\u043E\u0440\u0430" ,
beforeConvert : "\u0414\u043E \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u044F" ,
noticeInvalidPatternString : "\u041D\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043B\u044C\u043D\u0430\u044F \u0441\u0442\u0440\u043E\u043A\u0430 \u0448\u0430\u0431\u043B\u043E\u043D\u0430!"
},
button : {
update : "\u041E\u0431\u043D\u043E\u0432\u0438\u0442\u044C"
},
scriptCategoryLabels : {
chinese : "\u041A\u0438\u0442\u0430\u0439\u0441\u043A\u0438\u0439" ,
japanese : "\u042F\u043F\u043E\u043D\u0441\u043A\u0438\u0439" ,
korean : "\u041A\u043E\u0440\u0435\u0439\u0441\u043A\u0438\u0439" ,
cjk : "CJK" ,
english : "\u0410\u043D\u0433\u043B\u0438\u0439\u0441\u043A\u0438\u0439" ,
digit : "\u0426\u0438\u0444\u0440\u044B" ,
russian : "\u0420\u0443\u0441\u0441\u043A\u0438\u0439" ,
unknown : "\u041D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u044B\u0439"
},
builtinRuleDescriptions : {
"builtin-autopair-input" : "\u0410\u0432\u0442\u043E\u0434\u043E\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u0435 \u043F\u0430\u0440\u043D\u044B\u0445 \u043F\u043E\u043B\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u044B\u0445 \u0441\u043A\u043E\u0431\u043E\u043A/\u043A\u0430\u0432\u044B\u0447\u0435\u043A" ,
"builtin-autopair-jump" : "\u041F\u0435\u0440\u0435\u0441\u043A\u043E\u043A \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u044E\u0449\u0438\u0439 \u043F\u0430\u0440\u043D\u044B\u0439 \u0441\u0438\u043C\u0432\u043E\u043B" ,
"builtin-autopair-delete" : "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u043E\u0431\u0435\u0438\u0445 \u0441\u0442\u043E\u0440\u043E\u043D \u043F\u0430\u0440\u043D\u044B\u0445 \u043F\u043E\u043B\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u044B\u0445 \u0441\u043A\u043E\u0431\u043E\u043A/\u043A\u0430\u0432\u044B\u0447\u0435\u043A" ,
"builtin-conv-backtick" : "\u0414\u0432\u043E\u0439\u043D\u0430\u044F \u0441\u0440\u0435\u0434\u043D\u044F\u044F \u0442\u043E\u0447\u043A\u0430 \xB7\xB7 \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044F \u0432 \u0441\u0442\u0440\u043E\u0447\u043D\u044B\u0439 \u043A\u043E\u0434" ,
"builtin-conv-codeblock" : "\u0412\u0432\u043E\u0434 \xB7 \u0432 \u0441\u0442\u0440\u043E\u0447\u043D\u043E\u043C \u043A\u043E\u0434\u0435 \u043F\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0433\u043E \u0432 \u0431\u043B\u043E\u043A \u043A\u043E\u0434\u0430" ,
"builtin-conv-formula" : "\u041A\u043E\u043C\u0431\u0438\u043D\u0430\u0446\u0438\u0438 \uFFE5/$ \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u044E\u0442\u0441\u044F \u0432 \u0441\u0442\u0440\u043E\u0447\u043D\u0443\u044E \u0438\u043B\u0438 \u0431\u043B\u043E\u0447\u043D\u0443\u044E \u0444\u043E\u0440\u043C\u0443\u043B\u0443" ,
"builtin-conv-linestart" : "\u300B \u0432 \u043D\u0430\u0447\u0430\u043B\u0435 \u0441\u0442\u0440\u043E\u043A\u0438 \u2192 \u0446\u0438\u0442\u0430\u0442\u0430, \u3001 \u0432 \u043D\u0430\u0447\u0430\u043B\u0435 \u0441\u0442\u0440\u043E\u043A\u0438 \u2192 \u043A\u043E\u0441\u0430\u044F \u0447\u0435\u0440\u0442\u0430" ,
"builtin-conv-hw2fw" : "\u041F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u0435 \u043F\u043E\u043B\u0443\u0448\u0438\u0440\u0438\u043D\u043D\u043E\u0439 \u043F\u0443\u043D\u043A\u0442\u0443\u0430\u0446\u0438\u0438 \u0432 \u043F\u043E\u043B\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u0443\u044E \u043F\u043E\u0441\u043B\u0435 CJK-\u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432" ,
"builtin-fw2hw-double" : "\u0414\u0432\u043E\u0439\u043D\u0430\u044F \u043E\u0434\u0438\u043D\u0430\u043A\u043E\u0432\u0430\u044F \u043F\u043E\u043B\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u0430\u044F \u043F\u0443\u043D\u043A\u0442\u0443\u0430\u0446\u0438\u044F \u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0435\u0442\u0441\u044F \u0432 \u043F\u043E\u043B\u0443\u0448\u0438\u0440\u0438\u043D\u043D\u0443\u044E" ,
"builtin-del-inline-formula" : "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u043F\u0430\u0440\u044B \u0441\u0442\u0440\u043E\u0447\u043D\u043E\u0439 \u0444\u043E\u0440\u043C\u0443\u043B\u044B $...$" ,
"builtin-del-highlight" : "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u043F\u0430\u0440\u044B \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u044F ==...==" ,
"builtin-del-block-formula" : "\u0423\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u043F\u0430\u0440\u044B \u0431\u043B\u043E\u0447\u043D\u043E\u0439 \u0444\u043E\u0440\u043C\u0443\u043B\u044B $$...$$" ,
"builtin-del-codeblock" : "\u0411\u044B\u0441\u0442\u0440\u043E\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u043F\u0443\u0441\u0442\u043E\u0433\u043E \u0431\u043B\u043E\u043A\u0430 \u043A\u043E\u0434\u0430" ,
"builtin-del-wikilink" : "\u0411\u044B\u0441\u0442\u0440\u043E\u0435 \u0443\u0434\u0430\u043B\u0435\u043D\u0438\u0435 \u0432\u0438\u043A\u0438-\u0441\u0441\u044B\u043B\u043A\u0438 \u0438 \u0432\u0441\u0442\u0430\u0432\u043A\u0438 (![[]])" ,
"builtin-sel-wrap-backtick" : "\u041E\u0431\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u0432 \xB7 \u0432 \u043E\u0431\u0440\u0430\u0442\u043D\u044B\u0435 \u043A\u0430\u0432\u044B\u0447\u043A\u0438" ,
"builtin-sel-wrap-symbols" : "\u041E\u0431\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u0432 []/$ \u0441 \u043F\u043E\u043C\u043E\u0449\u044C\u044E \u3010/\xA5/\uFFE5" ,
"builtin-sel-wrap-quotes" : "\u041E\u0431\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u043F\u0430\u0440\u043D\u044B\u043C\u0438 \u043F\u043E\u043B\u043D\u043E\u0448\u0438\u0440\u0438\u043D\u043D\u044B\u043C\u0438 \u043A\u0430\u0432\u044B\u0447\u043A\u0430\u043C\u0438" ,
"builtin-sel-wrap-cjk-brackets" : "\u041E\u0431\u0435\u0440\u043D\u0443\u0442\u044C \u0432\u044B\u0434\u0435\u043B\u0435\u043D\u0438\u0435 \u0441\u043A\u043E\u0431\u043A\u0430\u043C\u0438 \u300A\u300B \u0438\u043B\u0438 \uFF08\uFF09" ,
"builtin-quote-convert" : "\u041F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u043E\u0432\u0430\u043D\u0438\u0435 > \u0438\u043B\u0438 \u300B \u0432 \u043C\u0430\u0440\u043A\u0435\u0440 \u0446\u0438\u0442\u0430\u0442\u044B Markdown" ,
"builtin-quote-space" : "\u0410\u0432\u0442\u043E\u0432\u0441\u0442\u0430\u0432\u043A\u0430 \u043F\u0440\u043E\u0431\u0435\u043B\u0430 \u043F\u043E\u0441\u043B\u0435 \u043C\u0430\u0440\u043A\u0435\u0440\u0430 \u0446\u0438\u0442\u0430\u0442\u044B >"
}
2026-01-05 13:03:55 +08:00
};
2026-08-21 15:44:03 +08:00
var ru_RU_default = locale4 ;
// src/lang/locale/ja-JP.ts
var locale5 = {
settings : {
smartPaste : {
name : "\u30B9\u30DE\u30FC\u30C8\u8CBC\u308A\u4ED8\u3051" ,
desc : "\u30EA\u30B9\u30C8\u3084\u5F15\u7528\u30D6\u30ED\u30C3\u30AF\u5185\u3067\u8CBC\u308A\u4ED8\u3051\u308B\u969B\u3001\u9069\u5207\u306A\u30A4\u30F3\u30C7\u30F3\u30C8\u3068\u30EA\u30B9\u30C8/\u5F15\u7528\u30DE\u30FC\u30AB\u30FC\u3092\u81EA\u52D5\u7684\u306B\u8FFD\u52A0\u3057\u307E\u3059\u3002"
},
codeblockEdit : {
name : "\u30B3\u30FC\u30C9\u30D6\u30ED\u30C3\u30AF\u7DE8\u96C6\u306E\u5F37\u5316" ,
desc : "\u30B3\u30FC\u30C9\u30D6\u30ED\u30C3\u30AF\u5185\u306E\u7DE8\u96C6\u3092\u6539\u5584\u3057\u307E\u3059\uFF08Tab\u3001\u524A\u9664\u3001\u8CBC\u308A\u4ED8\u3051\u3001Cmd/Ctrl+A \u9078\u629E\uFF09\u3002"
},
backspaceEdit : {
name : "\u30B9\u30DE\u30FC\u30C8\u30D0\u30C3\u30AF\u30B9\u30DA\u30FC\u30B9" ,
desc : "\u7A7A\u306E\u30EA\u30B9\u30C8\u9805\u76EE\u3084\u5F15\u7528\u884C\u3067\u306E\u30D0\u30C3\u30AF\u30B9\u30DA\u30FC\u30B9\u6A5F\u80FD\u3092\u5411\u4E0A\u3055\u305B\u307E\u3059\u3002"
},
tabOut : {
name : "Tab\u3067\u30DA\u30A2\u8A18\u53F7\u306E\u5916\u3078\u79FB\u52D5" ,
desc : "Tab \u30AD\u30FC\u3092\u62BC\u3057\u3066\u3010\u3011\u3001\uFF08\uFF09\u3001\u300A\u300B\u3001\u5F15\u7528\u7B26\u3001\u30A4\u30F3\u30E9\u30A4\u30F3\u30B3\u30FC\u30C9\u306A\u3069\u306E\u30DA\u30A2\u8A18\u53F7\u306E\u5916\u3078\u30AB\u30FC\u30BD\u30EB\u3092\u79FB\u52D5\u3057\u307E\u3059\u3002"
},
autoFormatting : {
name : "\u5165\u529B\u6642\u306E\u81EA\u52D5\u66F8\u5F0F\u8A2D\u5B9A" ,
desc : "\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u7DE8\u96C6\u4E2D\u306E\u30C6\u30AD\u30B9\u30C8\u81EA\u52D5\u66F8\u5F0F\u8A2D\u5B9A\u3092\u5207\u308A\u66FF\u3048\u307E\u3059\u3002"
},
autoFormatPaste : {
name : "\u8CBC\u308A\u4ED8\u3051\u6642\u306E\u81EA\u52D5\u66F8\u5F0F\u8A2D\u5B9A" ,
desc : "\u8CBC\u308A\u4ED8\u3051\u6642\u306E\u81EA\u52D5\u66F8\u5F0F\u8A2D\u5B9A\u3092\u5207\u308A\u66FF\u3048\u307E\u3059\u3002CMD/CTRL+SHIFT+V\uFF08\u66F8\u5F0F\u306A\u3057\u8CBC\u308A\u4ED8\u3051\uFF09\u3067\u306F\u30C8\u30EA\u30AC\u30FC\u3055\u308C\u307E\u305B\u3093\u3002"
},
languagePairSpacing : {
name : "\u8A00\u8A9E\u30DA\u30A2\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0" ,
desc : "\u7570\u306A\u308B\u8A00\u8A9E/\u8A18\u53F7\u30DA\u30A2\u9593\u306E\u81EA\u52D5\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u30EB\u30FC\u30EB\u3092\u5B9A\u7FA9\u3057\u307E\u3059\u3002"
},
prefixDictionary : {
name : "\u63A5\u982D\u8F9E\u8F9E\u66F8" ,
desc : "\u30AB\u30F3\u30DE\u3001\u30B9\u30DA\u30FC\u30B9\u3001\u6539\u884C\u3067\u533A\u5207\u308A\u307E\u3059\u3002\u5358\u8A9E\u307E\u305F\u306F /\u6B63\u898F\u8868\u73FE/ \u306B\u5BFE\u5FDC\u3002\u30DE\u30C3\u30C1\u3057\u305F\u30C8\u30FC\u30AF\u30F3\u306B\u306F\u30B9\u30DA\u30FC\u30B9\u304C\u633F\u5165\u3055\u308C\u305A\u3001\u5165\u529B\u4E2D\u306E\u63A5\u982D\u8F9E\u3082\u30B9\u30DA\u30FC\u30B9\u633F\u5165\u304C\u6291\u5236\u3055\u308C\u307E\u3059\u3002"
},
softSpaceSymbols : {
leftName : "\u30AB\u30B9\u30BF\u30E0\u5DE6\u5074\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9\u8A18\u53F7" ,
leftDesc : `\u4E00\u822C\u7684\u306A\u5168\u89D2\u53E5\u8AAD\u70B9\u3001\u82F1\u8A9E\u306E\u5F15\u7528\u7B26\uFF08' "\uFF09\u3001\u304A\u3088\u3073\u958B\u304D\u62EC\u5F27\uFF08[ ( {\uFF09\u306F\u5185\u8535\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u3053\u3053\u306B\u8FFD\u52A0\u306E\u5DE6\u5074\u8A18\u53F7\u3092\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B\uFF1A-\uFF09\u3002` ,
rightName : "\u30AB\u30B9\u30BF\u30E0\u53F3\u5074\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9\u8A18\u53F7" ,
rightDesc : `\u4E00\u822C\u7684\u306A\u5168\u89D2\u53E5\u8AAD\u70B9\u3001\u82F1\u8A9E\u306E\u5F15\u7528\u7B26\uFF08' "\uFF09\u3001\u9589\u3058\u62EC\u5F27\uFF08] ) }\uFF09\u3001\u304A\u3088\u3073\u82F1\u8A9E\u306E\u534A\u89D2\u53E5\u8AAD\u70B9\uFF08. , ? ! : ;\uFF09\u306F\u53F3\u5074\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9\u8A18\u53F7\u3068\u3057\u3066\u5185\u8535\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u3053\u3053\u306B\u8FFD\u52A0\u306E\u53F3\u5074\u8A18\u53F7\u3092\u8FFD\u52A0\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u4F8B\uFF1A-\uFF09\u3002`
},
customScriptCategories : {
name : "\u30AB\u30B9\u30BF\u30E0\u6587\u5B57\u30AB\u30C6\u30B4\u30EA" ,
desc : "\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u7528\u306E\u30AB\u30B9\u30BF\u30E0\u8A00\u8A9E\u307E\u305F\u306F\u8A18\u53F7\u30BB\u30C3\u30C8\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002" ,
namePlaceholder : "\u540D\u524D" ,
patternPlaceholder : "\u6587\u5B57\u30AF\u30E9\u30B9\u30D1\u30BF\u30FC\u30F3"
},
capitalizeFirstLetter : {
name : "\u6587\u982D\u306E\u5927\u6587\u5B57\u5316" ,
desc : "\u82F1\u8A9E\u306E\u5404\u6587\u306E\u6700\u521D\u306E\u6587\u5B57\u3092\u5927\u6587\u5B57\u306B\u3057\u307E\u3059\u3002"
},
spaceStrategyInlineCode : {
name : "\u30A4\u30F3\u30E9\u30A4\u30F3\u30B3\u30FC\u30C9\u3068\u30C6\u30AD\u30B9\u30C8\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565" ,
desc : "\u30A4\u30F3\u30E9\u30A4\u30F3\u30B3\u30FC\u30C9\u3068\u30C6\u30AD\u30B9\u30C8\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u3092\u5B9A\u7FA9\u3057\u307E\u3059\u3002"
},
spaceStrategyInlineFormula : {
name : "\u30A4\u30F3\u30E9\u30A4\u30F3\u6570\u5F0F\u3068\u30C6\u30AD\u30B9\u30C8\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565" ,
desc : "\u30A4\u30F3\u30E9\u30A4\u30F3\u6570\u5F0F\u3068\u30C6\u30AD\u30B9\u30C8\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u3092\u5B9A\u7FA9\u3057\u307E\u3059\u3002"
},
spaceStrategyLinkText : {
name : "\u30EA\u30F3\u30AF\u3068\u30C6\u30AD\u30B9\u30C8\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565" ,
desc : "[[\u30A6\u30A3\u30AD\u30EA\u30F3\u30AF]] [\u30DE\u30FC\u30AF\u30C0\u30A6\u30F3\u30EA\u30F3\u30AF](...) \u3068\u30C6\u30AD\u30B9\u30C8\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u3092\u5B9A\u7FA9\u3057\u307E\u3059\u3002"
},
userDefinedRegexpSwitch : {
name : "\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u6B63\u898F\u8868\u73FE\u30B9\u30A4\u30C3\u30C1" ,
desc : "\u30AB\u30B9\u30BF\u30E0\u6B63\u898F\u8868\u73FE\u3092\u6709\u52B9\u306B\u3057\u3001\u30DE\u30C3\u30C1\u3057\u305F\u30B3\u30F3\u30C6\u30F3\u30C4\u306E\u66F8\u5F0F\u8A2D\u5B9A\u3092\u9632\u6B62\u3057\u3001\u30DE\u30C3\u30C1\u3057\u305F\u30B3\u30F3\u30C6\u30F3\u30C4\u3068\u4ED6\u306E\u30C6\u30AD\u30B9\u30C8\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002"
},
userDefinedRegexp : {
name : "\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u6B63\u898F\u8868\u73FE\uFF081\u884C\u306B1\u3064\uFF09" ,
desc : "\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u306E\u6B63\u898F\u8868\u73FE\u3067\u3001\u30DE\u30C3\u30C1\u3057\u305F\u30B3\u30F3\u30C6\u30F3\u30C4\u306F\u66F8\u5F0F\u8A2D\u5B9A\u3055\u308C\u307E\u305B\u3093\u30021\u884C\u306B1\u3064\u306E\u5F0F\u3092\u8A18\u8FF0\u3057\u3001\u884C\u672B\u306B\u30B9\u30DA\u30FC\u30B9\u3092\u8FFD\u52A0\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\u5404\u884C\u306E\u672B\u5C3E3\u6587\u5B57\u306F | \u30682\u3064\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u8A18\u53F7\u3067\u56FA\u5B9A\u3055\u308C\u307E\u3059\u3002\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u8A18\u53F7\u306F - = + \u3067\u3001\u305D\u308C\u305E\u308C\u30B9\u30DA\u30FC\u30B9\u4E0D\u8981(-)\u3001\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9(=)\u3001\u53B3\u5BC6\u30B9\u30DA\u30FC\u30B9(+)\u3092\u610F\u5473\u3057\u307E\u3059\u3002\u3053\u308C\u30892\u3064\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u8A18\u53F7\u306F\u3001\u30DE\u30C3\u30C1\u30D6\u30ED\u30C3\u30AF\u306E\u5DE6\u53F3\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u3067\u3059\u3002// \u3067\u59CB\u307E\u308B\u884C\u306F\u30B3\u30E1\u30F3\u30C8\u3068\u3057\u3066\u6271\u308F\u308C\u307E\u3059\u3002"
},
userRulesRespectUserDefinedRegexBlocks : {
name : "\u30E6\u30FC\u30B6\u30FC\u30EB\u30FC\u30EB\u306F\u30AB\u30B9\u30BF\u30E0\u6B63\u898F\u8868\u73FE\u30D6\u30ED\u30C3\u30AF\u3092\u5C0A\u91CD" ,
desc : "\u6709\u52B9\u6642\u3001\u30AB\u30B9\u30BF\u30E0\u6B63\u898F\u8868\u73FE\u30D6\u30ED\u30C3\u30AF\u306B\u30DE\u30C3\u30C1\u3057\u305F\u30C6\u30AD\u30B9\u30C8\u306F\u81EA\u52D5\u30E6\u30FC\u30B6\u30FC\u30EB\u30FC\u30EB\u3092\u30C8\u30EA\u30AC\u30FC\u3057\u307E\u305B\u3093\u3002"
},
excludeFoldersFiles : {
name : "\u9664\u5916\u30D5\u30A9\u30EB\u30C0/\u30D5\u30A1\u30A4\u30EB" ,
desc : "\u3053\u306E\u30D7\u30E9\u30B0\u30A4\u30F3\u306F\u5404\u884C\u3092\u9664\u5916\u30D5\u30A9\u30EB\u30C0\u307E\u305F\u306F\u30D5\u30A1\u30A4\u30EB\u3068\u3057\u3066\u89E3\u6790\u3057\u307E\u3059\u3002\u4F8B\uFF1ADailyNote/\u3001DailyNote/WeekNotes/\u3001DailyNote/test.md"
},
fixMacOSContextMenu : {
name : "macOS \u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u30E1\u30CB\u30E5\u30FC\u306E\u30AB\u30FC\u30BD\u30EB\u4F4D\u7F6E\u3092\u4FEE\u6B63\uFF08Obsidian\u306E\u518D\u8D77\u52D5\u304C\u5FC5\u8981\uFF09" ,
desc : "macOS \u3067\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u30E1\u30CB\u30E5\u30FC\u3092\u547C\u3073\u51FA\u3057\u305F\u969B\u306B\u30AB\u30FC\u30BD\u30EB\u304C\u6B21\u306E\u884C\u306B\u30B8\u30E3\u30F3\u30D7\u3059\u308B\u554F\u984C\u3092\u4FEE\u6B63\u3057\u307E\u3059\uFF08Obsidian\u306E\u518D\u8D77\u52D5\u304C\u5FC5\u8981\uFF09\u3002"
},
fixMicrosoftIME : {
name : "Microsoft IME \u306E\u554F\u984C\u3092\u4FEE\u6B63" ,
desc : "\u65E7\u30D0\u30FC\u30B8\u30E7\u30F3\u306E Microsoft IME \u306B\u5BFE\u5FDC\u3057\u307E\u3059\u3002"
},
strictLineBreaks : {
name : "\u53B3\u5BC6\u6539\u884C\u30E2\u30FC\u30C9" ,
desc : "\u53B3\u5BC6\u6539\u884C\u30E2\u30FC\u30C9\u3067\u306F\u3001\u901A\u5E38\u306E\u30C6\u30AD\u30B9\u30C8\u884C\u3067 Enter \u30921\u56DE\u62BC\u3059\u3068\u30012\u3064\u306E\u6539\u884C\u307E\u305F\u306F2\u3064\u306E\u30B9\u30DA\u30FC\u30B9\u3068 Enter \u304C\u751F\u6210\u3055\u308C\u307E\u3059\u3002"
},
enhanceModA : {
name : "Ctrl/Cmd+A \u9078\u629E\u306E\u5F37\u5316" ,
desc : "1\u56DE\u76EE\uFF1A\u73FE\u5728\u306E\u884C\u3092\u9078\u629E\u30012\u56DE\u76EE\uFF1A\u73FE\u5728\u306E\u30C6\u30AD\u30B9\u30C8\u30D6\u30ED\u30C3\u30AF\u3092\u9078\u629E\u30013\u56DE\u76EE\uFF1A\u5168\u30C6\u30AD\u30B9\u30C8\u3092\u9078\u629E\u3002"
},
collapsePersistentEnter : {
name : "\u6298\u308A\u305F\u305F\u307F\u6642\u306EEnter\u52D5\u4F5C\u7DAD\u6301" ,
desc : "\u6298\u308A\u305F\u305F\u307E\u308C\u305F\u898B\u51FA\u3057\u3067 Enter \u3092\u62BC\u3059\u3068\u3001\u6298\u308A\u305F\u305F\u307F\u3092\u5C55\u958B\u305B\u305A\u306B\u4E0B\u306B\u540C\u30EC\u30D9\u30EB\u306E\u898B\u51FA\u3057\u3092\u633F\u5165\u3057\u307E\u3059\u3002"
},
printDebugInfo : {
name : "\u30B3\u30F3\u30BD\u30FC\u30EB\u306B\u30C7\u30D0\u30C3\u30B0\u60C5\u5831\u3092\u51FA\u529B" ,
desc : "\u30B3\u30F3\u30BD\u30FC\u30EB\u306B\u30C7\u30D0\u30C3\u30B0\u60C5\u5831\u3092\u51FA\u529B\u3057\u307E\u3059\u3002"
},
rulesStoragePath : {
name : "\u30EB\u30FC\u30EB\u30D5\u30A1\u30A4\u30EB\u306E\u4FDD\u5B58\u30D1\u30B9" ,
desc : "\u30EB\u30FC\u30EB\u30D5\u30A1\u30A4\u30EB\u306E\u4FDD\u5B58\u30D1\u30B9\u3092\u8A2D\u5B9A\u3057\u307E\u3059\uFF08\u30DC\u30EB\u30C8\u30EB\u30FC\u30C8\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9\uFF09\u3002\u30C7\u30D5\u30A9\u30EB\u30C8\u3092\u9078\u629E\u3059\u308B\u3068\u30D7\u30E9\u30B0\u30A4\u30F3\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u4FDD\u5B58\u3055\u308C\u307E\u3059" ,
defaultOption : "\u30C7\u30D5\u30A9\u30EB\u30C8\uFF08\u30D7\u30E9\u30B0\u30A4\u30F3\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\uFF09" ,
migrateButton : "\u79FB\u884C" ,
migrateDesc : "\u524D\u56DE\u8AAD\u307F\u8FBC\u3093\u3060\u30D1\u30B9\u304B\u3089\u73FE\u5728\u306E\u30D1\u30B9\u306B\u30EB\u30FC\u30EB\u30D5\u30A1\u30A4\u30EB\u3092\u79FB\u884C\u3057\u307E\u3059" ,
migrateSuccess : "\u30EB\u30FC\u30EB\u30D5\u30A1\u30A4\u30EB\u306E\u79FB\u884C\u304C\u5B8C\u4E86\u3057\u307E\u3057\u305F"
},
selectionReplaceRule : {
name : "\u9078\u629E\u7F6E\u63DB\u30EB\u30FC\u30EB" ,
desc : "\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u306E\u9078\u629E\u7F6E\u63DB\u30EB\u30FC\u30EB"
},
deleteRule : {
name : "\u524A\u9664\u30EB\u30FC\u30EB" ,
desc : "\u30EB\u30FC\u30EB\uFF1A| \u3067\u30AB\u30FC\u30BD\u30EB\u4F4D\u7F6E\u3092\u793A\u3057\u307E\u3059\u3002\u30D2\u30F3\u30C8\uFF1A| \u3092\u4F7F\u7528\u3057\u3066\u30AB\u30FC\u30BD\u30EB\u4F4D\u7F6E\u3092\u8868\u3057\u307E\u3059\u3002"
},
convertRule : {
name : "\u5909\u63DB\u30EB\u30FC\u30EB" ,
desc : "\u30EB\u30FC\u30EB\uFF1A| \u3067\u30AB\u30FC\u30BD\u30EB\u4F4D\u7F6E\u3092\u793A\u3057\u307E\u3059\u3002\u30D2\u30F3\u30C8\uFF1A| \u3092\u4F7F\u7528\u3057\u3066\u30AB\u30FC\u30BD\u30EB\u4F4D\u7F6E\u3092\u8868\u3057\u307E\u3059\u3002"
},
trigger : {
name : "\u30C8\u30EA\u30AC\u30FC"
},
left : {
name : "\u5DE6"
},
right : {
name : "\u53F3"
},
oldPattern : {
name : "\u65E7\u30D1\u30BF\u30FC\u30F3"
},
newPattern : {
name : "\u65B0\u30D1\u30BF\u30FC\u30F3"
},
ruleEditModal : {
addTitle : "\u30EB\u30FC\u30EB\u3092\u8FFD\u52A0" ,
editTitle : "\u30EB\u30FC\u30EB\u3092\u7DE8\u96C6" ,
fieldType : "\u30BF\u30A4\u30D7" ,
fieldTrigger : "\u30AB\u30FC\u30BD\u30EB\u524D\u30DE\u30C3\u30C1" ,
fieldTriggerSelectKey : "\u30C8\u30EA\u30AC\u30FC\u30AD\u30FC" ,
fieldTriggerRight : "\u30AB\u30FC\u30BD\u30EB\u5F8C\u30DE\u30C3\u30C1" ,
hintTriggerEscape : "\\\\: \u30D0\u30C3\u30AF\u30B9\u30E9\u30C3\u30B7\u30E5\u3001\\n: \u6539\u884C\u3001\\t: \u30BF\u30D6" ,
fieldReplacement : "\u7F6E\u63DB\u5185\u5BB9" ,
fieldReplacementDescSelectKey : "${SEL}: \u9078\u629E\u3055\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3001${0:${SEL}}: \u30C6\u30AD\u30B9\u30C8\u3092\u9078\u629E\u3057\u307E\u3059\u3002" ,
fieldReplacementDescInputDelete : "[[0]]: \u5DE6\u5074\u7B2C0\u30AD\u30E3\u30D7\u30C1\u30E3\u30B0\u30EB\u30FC\u30D7\u3001[[R1]]: \u53F3\u5074\u7B2C1\u30AD\u30E3\u30D7\u30C1\u30E3\u30B0\u30EB\u30FC\u30D7\u3002" ,
fieldIsRegex : "\u6B63\u898F\u8868\u73FE\u3067\u30DE\u30C3\u30C1" ,
fieldTriggerMode : "\u30C8\u30EA\u30AC\u30FC\u65B9\u5F0F" ,
fieldScope : "\u30B9\u30B3\u30FC\u30D7" ,
fieldScopeLanguage : "\u8A00\u8A9E\uFF08\u4EFB\u610F\uFF09" ,
fieldRegexFlags : "\u6B63\u898F\u8868\u73FE\u30D5\u30E9\u30B0" ,
fieldRegexFlagsDesc : "i / m / u \u306E\u307F\u5BFE\u5FDC\u3002\u4F8B: im" ,
fieldPriority : "\u512A\u5148\u5EA6" ,
fieldPriorityDesc : "\u6570\u5024\u304C\u5C0F\u3055\u3044\u307B\u3069\u512A\u5148\u5EA6\u304C\u9AD8\u3044\u3001\u30C7\u30D5\u30A9\u30EB\u30C8100" ,
fieldDescription : "\u8AAC\u660E" ,
buttonSave : "\u4FDD\u5B58" ,
invalidRegex : "\u7121\u52B9\u306A\u6B63\u898F\u8868\u73FE" ,
fieldIsFunction : "\u95A2\u6570\u3067\u7F6E\u63DB" ,
functionHintInputDelete : "\u5F15\u6570: leftMatches (string[])\u3001rightMatches (string[])\u3002\u6587\u5B57\u5217\u307E\u305F\u306F undefined \u3092\u8FD4\u3057\u3066\u30B9\u30AD\u30C3\u30D7\u3002" ,
functionHintSelectKey : "\u5F15\u6570: selectionText (string)\u3001key (string)\u3002\u6587\u5B57\u5217\u307E\u305F\u306F undefined \u3092\u8FD4\u3057\u3066\u30B9\u30AD\u30C3\u30D7\u3002" ,
hintTabstop : "$0: \u30AB\u30FC\u30BD\u30EB\u4F4D\u7F6E\u3001$1/$2: Tab \u30B8\u30E3\u30F3\u30D7\u4F4D\u7F6E\u3001${1:text}: \u30B8\u30E3\u30F3\u30D7\u3057\u3066 text \u3092\u9078\u629E\u3002" ,
functionPlaceholder : "// \u4F8B:\nconst d = new Date();\nreturn d.toISOString().slice(0,10) + '$0';" ,
groupMatch : "\u30DE\u30C3\u30C1\u6761\u4EF6" ,
groupReplacement : "\u7F6E\u63DB" ,
groupOther : "\u305D\u306E\u4ED6"
},
ruleType : {
input : "\u5165\u529B" ,
delete : "\u524A\u9664" ,
selectKey : "\u9078\u629E\u7F6E\u63DB"
}
},
commands : {
formatArticle : "\u73FE\u5728\u306E\u8A18\u4E8B\u3092\u66F8\u5F0F\u8A2D\u5B9A" ,
formatSelection : "\u9078\u629E\u3057\u305F\u30C6\u30AD\u30B9\u30C8\u307E\u305F\u306F\u73FE\u5728\u306E\u884C\u3092\u66F8\u5F0F\u8A2D\u5B9A" ,
deleteBlankLine : "\u9078\u629E\u7BC4\u56F2\u307E\u305F\u306F\u8A18\u4E8B\u5168\u4F53\u306E\u7A7A\u767D\u884C\u3092\u524A\u9664" ,
insertCodeblock : "\u30B3\u30FC\u30C9\u30D6\u30ED\u30C3\u30AF\u3092\u633F\u5165" ,
switchAutoformat : "\u81EA\u52D5\u66F8\u5F0F\u3092\u5207\u308A\u66FF\u3048" ,
pasteWithoutFormat : "\u66F8\u5F0F\u306A\u3057\u3067\u8CBC\u308A\u4ED8\u3051" ,
toggleComment : "\u30B3\u30E1\u30F3\u30C8\u3092\u5207\u308A\u66FF\u3048" ,
gotoNewLine : "\u73FE\u5728\u306E\u884C\u306E\u5F8C\u306B\u65B0\u3057\u3044\u884C\u3078\u79FB\u52D5" ,
selectBlock : "\u73FE\u5728\u306E\u30C6\u30AD\u30B9\u30C8\u30D6\u30ED\u30C3\u30AF\u3092\u9078\u629E"
},
headers : {
main : "Obsidian EasyTyping \u30D7\u30E9\u30B0\u30A4\u30F3" ,
githubDetail : "\u8A73\u7D30\u306F Github \u3092\u3054\u89A7\u304F\u3060\u3055\u3044\uFF1A" ,
enhancedEditing : "\u7DE8\u96C6\u5F37\u5316\u8A2D\u5B9A" ,
customizeEditRule : "\u7DE8\u96C6\u5909\u63DB\u30EB\u30FC\u30EB\u306E\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA" ,
autoformatSetting : "\u81EA\u52D5\u66F8\u5F0F\u8A2D\u5B9A" ,
detailedSetting : "\u30A4\u30F3\u30E9\u30A4\u30F3\u8981\u7D20\u9593\u306E\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0" ,
customRegexpBlock : "\u30AB\u30B9\u30BF\u30E0\u6B63\u898F\u8868\u73FE\u30D6\u30ED\u30C3\u30AF" ,
excludeFoldersFiles : "\u9664\u5916\u30D5\u30A9\u30EB\u30C0/\u30D5\u30A1\u30A4\u30EB" ,
experimentalFeatures : "\u5B9F\u9A13\u7684\u6A5F\u80FD" ,
languagePairSection : "\u8A00\u8A9E\u30DA\u30A2\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0" ,
addLanguagePair : "\u65B0\u3057\u3044\u8A00\u8A9E/\u8A18\u53F7\u30DA\u30A2\u3092\u8FFD\u52A0\uFF1A" ,
prefixDictSection : "\u63A5\u982D\u8F9E\u8F9E\u66F8" ,
softSpaceSection : "\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9\u8A18\u53F7" ,
customScriptSection : "\u30AB\u30B9\u30BF\u30E0\u6587\u5B57\u30AB\u30C6\u30B4\u30EA" ,
spaceStrategyIntro : "\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u6226\u7565\u306E\u8AAC\u660E\uFF1A\n\u4E0D\u8981\uFF1A\u3053\u306E\u30AB\u30C6\u30B4\u30EA\u30D6\u30ED\u30C3\u30AF\u3068\u5468\u56F2\u306E\u30C6\u30AD\u30B9\u30C8\u9593\u306B\u30B9\u30DA\u30FC\u30B7\u30F3\u30B0\u306F\u4E0D\u8981\u3067\u3059\u3002\n\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9\uFF1A\u3053\u306E\u30AB\u30C6\u30B4\u30EA\u30D6\u30ED\u30C3\u30AF\u3068\u5468\u56F2\u306E\u30D6\u30ED\u30C3\u30AF\u9593\u306B\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9\u306E\u307F\u5FC5\u8981\u3067\u3059\uFF08\u4F8B\uFF1A\u96A3\u63A5\u30C6\u30AD\u30B9\u30C8\u304C\u53E5\u8AAD\u70B9\u306E\u5834\u5408\u3001\u5B9F\u969B\u306E\u30B9\u30DA\u30FC\u30B9\u306F\u8FFD\u52A0\u3055\u308C\u307E\u305B\u3093\uFF09\u3002\n\u53B3\u5BC6\u30B9\u30DA\u30FC\u30B9\uFF1A\u73FE\u5728\u306E\u30D6\u30ED\u30C3\u30AF\u3068\u96A3\u63A5\u30C6\u30AD\u30B9\u30C8\u9593\u306B\u53B3\u5BC6\u306B\u5B9F\u969B\u306E\u30B9\u30DA\u30FC\u30B9\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002" ,
aboutRegexp : {
header : "\u6B63\u898F\u8868\u73FE\u306B\u3064\u3044\u3066\u306E\u8A73\u7D30\u306F\u4EE5\u4E0B\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\uFF1A" ,
text : "\u6B63\u898F\u8868\u73FE\u306E\u7C21\u6F54\u306A\u30C1\u30E5\u30FC\u30C8\u30EA\u30A2\u30EB"
},
customizeSelectionRule : "\u9078\u629E\u7F6E\u63DB\u30EB\u30FC\u30EB\u306E\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA" ,
customizeDeleteRule : "\u524A\u9664\u30EB\u30FC\u30EB\u306E\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA" ,
customizeConvertRule : "\u5909\u63DB\u30EB\u30FC\u30EB\u306E\u30AB\u30B9\u30BF\u30DE\u30A4\u30BA" ,
editSelectionReplaceRule : "\u9078\u629E\u7F6E\u63DB\u30EB\u30FC\u30EB\u306E\u7DE8\u96C6" ,
builtinRulesSection : "\u7D44\u307F\u8FBC\u307F\u30EB\u30FC\u30EB" ,
userRulesSection : "\u30E6\u30FC\u30B6\u30FC\u30EB\u30FC\u30EB" ,
deletedRulesSection : "\u524A\u9664\u3055\u308C\u305F\u7D44\u307F\u8FBC\u307F\u30EB\u30FC\u30EB" ,
tabs : {
editEnhance : "\u7DE8\u96C6\u5F37\u5316" ,
autoFormat : "\u81EA\u52D5\u66F8\u5F0F" ,
builtinRules : "\u7D44\u307F\u8FBC\u307F\u30EB\u30FC\u30EB" ,
userRules : "\u30E6\u30FC\u30B6\u30FC\u30EB\u30FC\u30EB" ,
other : "\u305D\u306E\u4ED6"
}
},
dropdownOptions : {
enterTwice : "Enter 2\u56DE" ,
twoSpace : "\u30B9\u30DA\u30FC\u30B92\u3064" ,
mixMode : "\u30DF\u30C3\u30AF\u30B9\u30E2\u30FC\u30C9" ,
noRequire : "\u4E0D\u8981" ,
softSpace : "\u30BD\u30D5\u30C8\u30B9\u30DA\u30FC\u30B9" ,
strictSpace : "\u53B3\u5BC6\u30B9\u30DA\u30FC\u30B9" ,
dummy : "\u30C0\u30DF\u30FC" ,
smart : "\u30B9\u30DE\u30FC\u30C8" ,
scopeAll : "\u3059\u3079\u3066" ,
scopeText : "\u30C6\u30AD\u30B9\u30C8" ,
scopeFormula : "\u6570\u5F0F" ,
scopeCode : "\u30B3\u30FC\u30C9" ,
triggerModeAuto : "\u81EA\u52D5" ,
triggerModeTab : "Tab" ,
ruleTypeInput : "\u5165\u529B" ,
ruleTypeDelete : "\u524A\u9664" ,
ruleTypeSelectKey : "\u9078\u629E\u7F6E\u63DB"
},
toolTip : {
switch : "\u30B9\u30A4\u30C3\u30C1" ,
editRule : "\u30EB\u30FC\u30EB\u3092\u7DE8\u96C6" ,
removeRule : "\u30EB\u30FC\u30EB\u3092\u524A\u9664" ,
addRule : "\u30EB\u30FC\u30EB\u3092\u8FFD\u52A0" ,
enableRule : "\u30EB\u30FC\u30EB\u306E\u6709\u52B9\u5316/\u7121\u52B9\u5316" ,
restoreRule : "\u3053\u306E\u30EB\u30FC\u30EB\u3092\u5FA9\u5143" ,
resetAllRules : "\u3059\u3079\u3066\u306E\u7D44\u307F\u8FBC\u307F\u30EB\u30FC\u30EB\u3092\u30EA\u30BB\u30C3\u30C8" ,
resetSuccess : "\u7D44\u307F\u8FBC\u307F\u30EB\u30FC\u30EB\u304C\u6B63\u5E38\u306B\u30EA\u30BB\u30C3\u30C8\u3055\u308C\u307E\u3057\u305F" ,
exportRules : "\u30EB\u30FC\u30EB\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8" ,
importRules : "\u30EB\u30FC\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8" ,
noRulesToExport : "\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3059\u308B\u30E6\u30FC\u30B6\u30FC\u30EB\u30FC\u30EB\u304C\u3042\u308A\u307E\u305B\u3093" ,
importSuccess : "%d\u4EF6\u306E\u30EB\u30FC\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3057\u3001%d\u4EF6\u306E\u91CD\u8907\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u307E\u3057\u305F" ,
importInvalidJson : "\u7121\u52B9\u306A\u30D5\u30A1\u30A4\u30EB\uFF1A\u6709\u52B9\u306AJSON\u3067\u306F\u3042\u308A\u307E\u305B\u3093" ,
importNoRules : "\u30D5\u30A1\u30A4\u30EB\u306B\u30A4\u30F3\u30DD\u30FC\u30C8\u53EF\u80FD\u306A\u30EB\u30FC\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093"
},
placeHolder : {
triggerSymbol : "\u30C8\u30EA\u30AC\u30FC\u8A18\u53F7" ,
newLeftSideString : "\u65B0\u3057\u3044\u5DE6\u5074\u6587\u5B57\u5217" ,
newRightSideString : "\u65B0\u3057\u3044\u53F3\u5074\u6587\u5B57\u5217" ,
addRule : "\u30EB\u30FC\u30EB\u3092\u8FFD\u52A0" ,
noticeInvaidTrigger : "\u7121\u52B9\u306A\u30C8\u30EA\u30AC\u30FC\u3067\u3059\u3002\u30C8\u30EA\u30AC\u30FC\u306F\u9577\u30551\u306E\u8A18\u53F7\u307E\u305F\u306F \u2014\u2014\u3001\u2026\u2026 \u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059" ,
noticeWarnTriggerExists : "\u8B66\u544A\uFF01\u30C8\u30EA\u30AC\u30FC %s \u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\uFF01" ,
noticeMissingInput : "\u5165\u529B\u304C\u4E0D\u8DB3\u3057\u3066\u3044\u307E\u3059" ,
beforeDelete : "\u524A\u9664\u524D" ,
newPattern : "\u65B0\u3057\u3044\u30D1\u30BF\u30FC\u30F3" ,
noticeInvaidTriggerPatternContainSymbol : "\u7121\u52B9\u306A\u30C8\u30EA\u30AC\u30FC\u3067\u3059\u3002\u30D1\u30BF\u30FC\u30F3\u306B\u306F\u30AB\u30FC\u30BD\u30EB\u4F4D\u7F6E\u3092\u793A\u3059\u8A18\u53F7 | \u304C\u542B\u307E\u308C\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059" ,
beforeConvert : "\u5909\u63DB\u524D" ,
noticeInvalidPatternString : "\u7121\u52B9\u306A\u30D1\u30BF\u30FC\u30F3\u6587\u5B57\u5217\u3067\u3059\uFF01"
},
button : {
update : "\u66F4\u65B0"
},
scriptCategoryLabels : {
chinese : "\u4E2D\u56FD\u8A9E" ,
japanese : "\u65E5\u672C\u8A9E" ,
korean : "\u97D3\u56FD\u8A9E" ,
cjk : "CJK" ,
english : "\u82F1\u8A9E" ,
digit : "\u6570\u5B57" ,
russian : "\u30ED\u30B7\u30A2\u8A9E" ,
unknown : "\u4E0D\u660E"
},
builtinRuleDescriptions : {
"builtin-autopair-input" : "\u5168\u89D2\u62EC\u5F27/\u5F15\u7528\u7B26\u306E\u5165\u529B\u6642\u306B\u81EA\u52D5\u88DC\u5B8C" ,
"builtin-autopair-jump" : "\u9589\u3058\u30DA\u30A2\u8A18\u53F7\u306E\u5165\u529B\u6642\u306B\u81EA\u52D5\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u91CD\u8907\u3092\u9632\u6B62" ,
"builtin-autopair-delete" : "\u5168\u89D2\u62EC\u5F27/\u5F15\u7528\u7B26\u306E\u524A\u9664\u6642\u306B\u30DA\u30A2\u3054\u3068\u524A\u9664" ,
"builtin-conv-backtick" : "\u4E2D\u70B9 \xB7\xB7 \u306E\u9023\u7D9A\u5165\u529B\u3067\u30A4\u30F3\u30E9\u30A4\u30F3\u30B3\u30FC\u30C9\u306B\u5909\u63DB" ,
"builtin-conv-codeblock" : "\u30A4\u30F3\u30E9\u30A4\u30F3\u30B3\u30FC\u30C9\u5185\u3067 \xB7 \u3092\u5165\u529B\u3059\u308B\u3068\u30B3\u30FC\u30C9\u30D6\u30ED\u30C3\u30AF\u306B\u30A2\u30C3\u30D7\u30B0\u30EC\u30FC\u30C9" ,
"builtin-conv-formula" : "\uFFE5/$ \u306E\u7D44\u307F\u5408\u308F\u305B\u3067\u30A4\u30F3\u30E9\u30A4\u30F3\u307E\u305F\u306F\u30D6\u30ED\u30C3\u30AF\u6570\u5F0F\u306B\u5909\u63DB" ,
"builtin-conv-linestart" : "\u884C\u982D\u306E \u300B \u2192 \u5F15\u7528\u30DE\u30FC\u30AB\u30FC\u3001\u3001 \u2192 \u30B9\u30E9\u30C3\u30B7\u30E5" ,
"builtin-conv-hw2fw" : "CJK\u6587\u5B57\u306E\u5F8C\u306E\u534A\u89D2\u53E5\u8AAD\u70B9\u3092\u5168\u89D2\u306B\u5909\u63DB" ,
"builtin-fw2hw-double" : "\u540C\u3058\u5168\u89D2\u53E5\u8AAD\u70B9\u30922\u56DE\u5165\u529B\u3059\u308B\u3068\u534A\u89D2\u306B\u5909\u63DB" ,
"builtin-del-inline-formula" : "\u30A4\u30F3\u30E9\u30A4\u30F3\u6570\u5F0F $...$ \u306E\u30DA\u30A2\u3092\u524A\u9664" ,
"builtin-del-highlight" : "\u30CF\u30A4\u30E9\u30A4\u30C8 ==...== \u306E\u30DA\u30A2\u3092\u524A\u9664" ,
"builtin-del-block-formula" : "\u30D6\u30ED\u30C3\u30AF\u6570\u5F0F $$...$$ \u306E\u30DA\u30A2\u3092\u524A\u9664" ,
"builtin-del-codeblock" : "\u7A7A\u306E\u30B3\u30FC\u30C9\u30D6\u30ED\u30C3\u30AF\u3092\u3059\u3070\u3084\u304F\u524A\u9664" ,
"builtin-del-wikilink" : "\u30A6\u30A3\u30AD\u30EA\u30F3\u30AF\u3068\u57CB\u3081\u8FBC\u307F(![[]])\u3092\u3059\u3070\u3084\u304F\u524A\u9664" ,
"builtin-sel-wrap-backtick" : "\xB7 \u3067\u9078\u629E\u30C6\u30AD\u30B9\u30C8\u3092\u30D0\u30C3\u30AF\u30AF\u30A9\u30FC\u30C8\u3067\u56F2\u3080" ,
"builtin-sel-wrap-symbols" : "\u9078\u629E\u30C6\u30AD\u30B9\u30C8\u3092\u3010/\xA5/\uFFE5\u3067 []/$$\u3067\u56F2\u3080" ,
"builtin-sel-wrap-quotes" : "\u9078\u629E\u30C6\u30AD\u30B9\u30C8\u3092\u5168\u89D2\u5F15\u7528\u7B26\u3067\u56F2\u3080" ,
"builtin-sel-wrap-cjk-brackets" : "\u9078\u629E\u30C6\u30AD\u30B9\u30C8\u3092\u300A\u300B\u307E\u305F\u306F\uFF08\uFF09\u62EC\u5F27\u3067\u56F2\u3080" ,
"builtin-quote-convert" : "> \u307E\u305F\u306F \u300B\u3092 Markdown \u5F15\u7528\u30DE\u30FC\u30AB\u30FC\u306B\u5909\u63DB" ,
"builtin-quote-space" : "\u5F15\u7528\u30DE\u30FC\u30AB\u30FC > \u306E\u5F8C\u306B\u30B9\u30DA\u30FC\u30B9\u3092\u81EA\u52D5\u633F\u5165"
}
};
var ja_JP_default = locale5 ;
// src/lang/locale/ko-KR.ts
var locale6 = {
settings : {
smartPaste : {
name : "\uC2A4\uB9C8\uD2B8 \uBD99\uC5EC\uB123\uAE30" ,
desc : "\uBAA9\uB85D\uC774\uB098 \uC778\uC6A9 \uBE14\uB85D\uC5D0\uC11C \uBD99\uC5EC\uB123\uC744 \uB54C \uC801\uC808\uD55C \uB4E4\uC5EC\uC4F0\uAE30\uC640 \uBAA9\uB85D/\uC778\uC6A9 \uAE30\uD638\uB97C \uC790\uB3D9\uC73C\uB85C \uCD94\uAC00\uD569\uB2C8\uB2E4."
},
codeblockEdit : {
name : "\uCF54\uB4DC \uBE14\uB85D \uD3B8\uC9D1 \uAC15\uD654" ,
desc : "\uCF54\uB4DC \uBE14\uB85D \uB0B4 \uD3B8\uC9D1 \uAE30\uB2A5 \uAC15\uD654 (Tab, \uC0AD\uC81C, \uBD99\uC5EC\uB123\uAE30, Cmd/Ctrl+A \uC120\uD0DD)"
},
backspaceEdit : {
name : "\uC2A4\uB9C8\uD2B8 \uBC31\uC2A4\uD398\uC774\uC2A4" ,
desc : "\uBE48 \uBAA9\uB85D \uD56D\uBAA9\uC774\uB098 \uBE48 \uC778\uC6A9 \uC904\uC5D0\uC11C \uBC31\uC2A4\uD398\uC774\uC2A4 \uAE30\uB2A5\uC744 \uD5A5\uC0C1\uC2DC\uD0B5\uB2C8\uB2E4."
},
tabOut : {
name : "Tab\uC73C\uB85C \uC30D \uAE30\uD638 \uBC16\uC73C\uB85C \uC774\uB3D9" ,
desc : "Tab \uD0A4\uB97C \uB20C\uB7EC \u3010\u3011, \uFF08\uFF09, \u300A\u300B, \uB530\uC634\uD45C, \uC778\uB77C\uC778 \uCF54\uB4DC \uB4F1\uC758 \uC30D \uAE30\uD638 \uBC16\uC73C\uB85C \uCEE4\uC11C\uB97C \uC774\uB3D9\uD569\uB2C8\uB2E4."
},
autoFormatting : {
name : "\uC785\uB825 \uC2DC \uC790\uB3D9 \uC11C\uC2DD" ,
desc : "\uBB38\uC11C \uD3B8\uC9D1 \uC911 \uD14D\uC2A4\uD2B8 \uC790\uB3D9 \uC11C\uC2DD \uC9C0\uC815\uC744 \uCF1C\uAC70\uB098 \uB055\uB2C8\uB2E4."
},
autoFormatPaste : {
name : "\uBD99\uC5EC\uB123\uAE30 \uC2DC \uC790\uB3D9 \uC11C\uC2DD" ,
desc : "\uBD99\uC5EC\uB123\uAE30 \uC2DC \uC790\uB3D9 \uC11C\uC2DD\uC744 \uCF1C\uAC70\uB098 \uB055\uB2C8\uB2E4. CMD/CTRL+SHIFT+V(\uC11C\uC2DD \uC5C6\uC774 \uBD99\uC5EC\uB123\uAE30)\uC5D0\uC11C\uB294 \uC791\uB3D9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
},
languagePairSpacing : {
name : "\uC5B8\uC5B4 \uC30D \uAC04\uACA9" ,
desc : "\uC11C\uB85C \uB2E4\uB978 \uC5B8\uC5B4/\uAE30\uD638 \uC30D \uC0AC\uC774\uC758 \uC790\uB3D9 \uAC04\uACA9 \uADDC\uCE59\uC744 \uC815\uC758\uD569\uB2C8\uB2E4."
},
prefixDictionary : {
name : "\uC811\uB450\uC0AC \uC0AC\uC804" ,
desc : "\uC27C\uD45C, \uACF5\uBC31 \uB610\uB294 \uC904\uBC14\uAFC8\uC73C\uB85C \uAD6C\uBD84\uD569\uB2C8\uB2E4. \uB2E8\uC5B4 \uB610\uB294 /\uC815\uADDC\uC2DD/\uC744 \uC9C0\uC6D0\uD569\uB2C8\uB2E4. \uB9E4\uCE6D\uB41C \uD1A0\uD070\uC5D0\uB294 \uACF5\uBC31\uC774 \uC0BD\uC785\uB418\uC9C0 \uC54A\uC73C\uBA70, \uC785\uB825 \uC911\uC778 \uC811\uB450\uC0AC\uB3C4 \uACF5\uBC31 \uC0BD\uC785\uC774 \uC5B5\uC81C\uB429\uB2C8\uB2E4."
},
softSpaceSymbols : {
leftName : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC67C\uCABD \uC18C\uD504\uD2B8 \uC2A4\uD398\uC774\uC2A4 \uAE30\uD638" ,
leftDesc : `\uC77C\uBC18\uC801\uC778 \uC804\uAC01 \uBB38\uC7A5\uBD80\uD638, \uC601\uBB38 \uC778\uC6A9\uBD80\uD638(' "), \uC5EC\uB294 \uAD04\uD638([ ( {)\uAC00 \uB0B4\uC7A5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uC5EC\uAE30\uC5D0 \uCD94\uAC00 \uC67C\uCABD \uAE30\uD638\uB97C \uCD94\uAC00\uD558\uC138\uC694 (\uC608: -).` ,
rightName : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC624\uB978\uCABD \uC18C\uD504\uD2B8 \uC2A4\uD398\uC774\uC2A4 \uAE30\uD638" ,
rightDesc : `\uC77C\uBC18\uC801\uC778 \uC804\uAC01 \uBB38\uC7A5\uBD80\uD638, \uC601\uBB38 \uC778\uC6A9\uBD80\uD638(' "), \uB2EB\uB294 \uAD04\uD638(] ) }), \uADF8\uB9AC\uACE0 \uC601\uBB38 \uBC18\uAC01 \uBB38\uC7A5\uBD80\uD638(. , ? ! : ;)\uAC00 \uC624\uB978\uCABD \uC18C\uD504\uD2B8 \uC2A4\uD398\uC774\uC2A4 \uAE30\uD638\uB85C \uB0B4\uC7A5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uC5EC\uAE30\uC5D0 \uCD94\uAC00 \uC624\uB978\uCABD \uAE30\uD638\uB97C \uCD94\uAC00\uD558\uC138\uC694 (\uC608: -).`
},
customScriptCategories : {
name : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uBB38\uC790 \uBC94\uC8FC" ,
desc : "\uAC04\uACA9 \uC804\uB7B5\uC744 \uC704\uD55C \uC0AC\uC6A9\uC790 \uC815\uC758 \uC5B8\uC5B4 \uB610\uB294 \uAE30\uD638 \uC9D1\uD569\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4." ,
namePlaceholder : "\uC774\uB984" ,
patternPlaceholder : "\uBB38\uC790 \uD074\uB798\uC2A4 \uD328\uD134"
},
capitalizeFirstLetter : {
name : "\uBB38\uC7A5 \uCCAB \uAE00\uC790 \uB300\uBB38\uC790\uD654" ,
desc : "\uC601\uC5B4 \uBB38\uC7A5\uC758 \uCCAB \uAE00\uC790\uB97C \uB300\uBB38\uC790\uB85C \uBCC0\uD658\uD569\uB2C8\uB2E4."
},
spaceStrategyInlineCode : {
name : "\uC778\uB77C\uC778 \uCF54\uB4DC\uC640 \uD14D\uC2A4\uD2B8 \uC0AC\uC774 \uAC04\uACA9 \uC804\uB7B5" ,
desc : "\uC778\uB77C\uC778 \uCF54\uB4DC\uC640 \uD14D\uC2A4\uD2B8 \uC0AC\uC774\uC758 \uAC04\uACA9 \uC804\uB7B5\uC744 \uC815\uC758\uD569\uB2C8\uB2E4."
},
spaceStrategyInlineFormula : {
name : "\uC778\uB77C\uC778 \uC218\uC2DD\uACFC \uD14D\uC2A4\uD2B8 \uC0AC\uC774 \uAC04\uACA9 \uC804\uB7B5" ,
desc : "\uC778\uB77C\uC778 \uC218\uC2DD\uACFC \uD14D\uC2A4\uD2B8 \uC0AC\uC774\uC758 \uAC04\uACA9 \uC804\uB7B5\uC744 \uC815\uC758\uD569\uB2C8\uB2E4."
},
spaceStrategyLinkText : {
name : "\uB9C1\uD06C\uC640 \uD14D\uC2A4\uD2B8 \uC0AC\uC774 \uAC04\uACA9 \uC804\uB7B5" ,
desc : "[[\uC704\uD0A4\uB9C1\uD06C]] [\uB9C8\uD06C\uB2E4\uC6B4 \uB9C1\uD06C](...) \uC640 \uD14D\uC2A4\uD2B8 \uC0AC\uC774\uC758 \uAC04\uACA9 \uC804\uB7B5\uC744 \uC815\uC758\uD569\uB2C8\uB2E4."
},
userDefinedRegexpSwitch : {
name : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC815\uADDC\uC2DD \uC2A4\uC704\uCE58" ,
desc : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC815\uADDC\uC2DD\uC744 \uD65C\uC131\uD654\uD558\uC5EC \uB9E4\uCE6D\uB41C \uCF58\uD150\uCE20\uC758 \uC11C\uC2DD\uC744 \uBC29\uC9C0\uD558\uACE0, \uB9E4\uCE6D\uB41C \uCF58\uD150\uCE20\uC640 \uB2E4\uB978 \uD14D\uC2A4\uD2B8 \uC0AC\uC774\uC758 \uAC04\uACA9 \uC804\uB7B5\uC744 \uC124\uC815\uD569\uB2C8\uB2E4."
},
userDefinedRegexp : {
name : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC815\uADDC\uC2DD, \uD55C \uC904\uC5D0 \uD558\uB098\uC529" ,
desc : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC815\uADDC\uC2DD\uC73C\uB85C \uB9E4\uCE6D\uB41C \uCF58\uD150\uCE20\uB294 \uC11C\uC2DD\uC774 \uC801\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uD55C \uC904\uC5D0 \uD558\uB098\uC529 \uC791\uC131\uD558\uBA70, \uC904 \uB05D\uC5D0 \uACF5\uBC31\uC744 \uCD94\uAC00\uD558\uC9C0 \uB9C8\uC138\uC694.\uAC01 \uC904\uC758 \uB9C8\uC9C0\uB9C9 3\uC790\uB294 |\uC640 \uB450 \uAC1C\uC758 \uAC04\uACA9 \uC804\uB7B5 \uAE30\uD638\uB85C \uACE0\uC815\uB429\uB2C8\uB2E4. \uAC04\uACA9 \uC804\uB7B5 \uAE30\uD638\uB294 - = +\uC774\uBA70, \uAC01\uAC01 \uAC04\uACA9 \uBD88\uD544\uC694(-), \uC18C\uD504\uD2B8\uC6E8\uC5B4 \uC2A4\uD398\uC774\uC2A4(=), \uC5C4\uACA9\uD55C \uC2A4\uD398\uC774\uC2A4(+)\uB97C \uC758\uBBF8\uD569\uB2C8\uB2E4.\uC774 \uB450 \uAC04\uACA9 \uC804\uB7B5 \uAE30\uD638\uB294 \uB9E4\uCE6D \uBE14\uB85D\uC758 \uC67C\uCABD\uACFC \uC624\uB978\uCABD\uC758 \uAC04\uACA9 \uC804\uB7B5\uC785\uB2C8\uB2E4. // \uB85C \uC2DC\uC791\uD558\uB294 \uC904\uC740 \uC8FC\uC11D\uC73C\uB85C \uCC98\uB9AC\uB429\uB2C8\uB2E4."
},
userRulesRespectUserDefinedRegexBlocks : {
name : "\uC0AC\uC6A9\uC790 \uADDC\uCE59\uC774 \uCEE4\uC2A4\uD140 \uC815\uADDC\uC2DD \uBE14\uB85D\uC744 \uC900\uC218" ,
desc : "\uD65C\uC131\uD654 \uC2DC \uCEE4\uC2A4\uD140 \uC815\uADDC\uC2DD \uBE14\uB85D\uC5D0 \uB9E4\uCE6D\uB41C \uD14D\uC2A4\uD2B8\uB294 \uC790\uB3D9 \uC0AC\uC6A9\uC790 \uADDC\uCE59\uC744 \uD2B8\uB9AC\uAC70\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
},
excludeFoldersFiles : {
name : "\uC81C\uC678 \uD3F4\uB354/\uD30C\uC77C" ,
desc : "\uC774 \uD50C\uB7EC\uADF8\uC778\uC740 \uAC01 \uC904\uC744 \uC81C\uC678 \uD3F4\uB354 \uB610\uB294 \uD30C\uC77C\uB85C \uD30C\uC2F1\uD569\uB2C8\uB2E4. \uC608: DailyNote/, DailyNote/WeekNotes/, DailyNote/test.md"
},
fixMacOSContextMenu : {
name : "macOS \uCEE8\uD14D\uC2A4\uD2B8 \uBA54\uB274 \uCEE4\uC11C \uC704\uCE58 \uC218\uC815 (Obsidian \uC7AC\uC2DC\uC791 \uD544\uC694)" ,
desc : "macOS\uC5D0\uC11C \uCEE8\uD14D\uC2A4\uD2B8 \uBA54\uB274 \uD638\uCD9C \uC2DC \uCEE4\uC11C\uAC00 \uB2E4\uC74C \uC904\uB85C \uC774\uB3D9\uD558\uB294 \uBB38\uC81C\uB97C \uC218\uC815\uD569\uB2C8\uB2E4 (Obsidian \uC7AC\uC2DC\uC791 \uD544\uC694)."
},
fixMicrosoftIME : {
name : "Microsoft \uC785\uB825\uAE30 \uBB38\uC81C \uC218\uC815" ,
desc : "\uC774\uC804 \uBC84\uC804\uC758 Microsoft \uC785\uB825\uAE30\uC5D0 \uB300\uD55C \uD638\uD658\uC131 \uCC98\uB9AC."
},
strictLineBreaks : {
name : "\uC5C4\uACA9\uD55C \uC904\uBC14\uAFC8 \uBAA8\uB4DC" ,
desc : "\uC5C4\uACA9\uD55C \uC904\uBC14\uAFC8 \uBAA8\uB4DC\uC5D0\uC11C \uC77C\uBC18 \uD14D\uC2A4\uD2B8 \uC904\uC5D0\uC11C Enter\uB97C \uD55C \uBC88 \uB204\uB974\uBA74 \uB450 \uBC88\uC758 \uC904\uBC14\uAFC8 \uB610\uB294 \uB450 \uAC1C\uC758 \uACF5\uBC31\uACFC Enter\uAC00 \uC0DD\uC131\uB429\uB2C8\uB2E4."
},
enhanceModA : {
name : "Ctrl/Cmd+A \uC120\uD0DD \uAC15\uD654" ,
desc : "\uCCAB \uBC88\uC9F8: \uD604\uC7AC \uC904 \uC120\uD0DD, \uB450 \uBC88\uC9F8: \uD604\uC7AC \uD14D\uC2A4\uD2B8 \uBE14\uB85D \uC120\uD0DD, \uC138 \uBC88\uC9F8: \uC804\uCCB4 \uD14D\uC2A4\uD2B8 \uC120\uD0DD."
},
collapsePersistentEnter : {
name : "\uC811\uD78C \uC0C1\uD0DC\uC5D0\uC11C Enter \uC720\uC9C0" ,
desc : "\uC811\uD78C \uC81C\uBAA9\uC5D0\uC11C Enter\uB97C \uB204\uB974\uBA74 \uC811\uD798\uC744 \uD3BC\uCE58\uC9C0 \uC54A\uACE0 \uC544\uB798\uC5D0 \uAC19\uC740 \uC218\uC900\uC758 \uC81C\uBAA9\uC744 \uC0BD\uC785\uD569\uB2C8\uB2E4."
},
printDebugInfo : {
name : "\uCF58\uC194\uC5D0 \uB514\uBC84\uADF8 \uC815\uBCF4 \uCD9C\uB825" ,
desc : "\uCF58\uC194\uC5D0 \uB514\uBC84\uADF8 \uC815\uBCF4\uB97C \uCD9C\uB825\uD569\uB2C8\uB2E4."
},
rulesStoragePath : {
name : "\uADDC\uCE59 \uD30C\uC77C \uC800\uC7A5 \uACBD\uB85C" ,
desc : "\uADDC\uCE59 \uD30C\uC77C\uC758 \uC800\uC7A5 \uACBD\uB85C\uB97C \uC124\uC815\uD569\uB2C8\uB2E4 (\uBCFC\uD2B8 \uB8E8\uD2B8 \uAE30\uC900 \uC0C1\uB300 \uACBD\uB85C). \uAE30\uBCF8\uAC12\uC744 \uC120\uD0DD\uD558\uBA74 \uD50C\uB7EC\uADF8\uC778 \uB514\uB809\uD130\uB9AC\uC5D0 \uC800\uC7A5\uB429\uB2C8\uB2E4" ,
defaultOption : "\uAE30\uBCF8\uAC12 (\uD50C\uB7EC\uADF8\uC778 \uB514\uB809\uD130\uB9AC)" ,
migrateButton : "\uB9C8\uC774\uADF8\uB808\uC774\uC158" ,
migrateDesc : "\uC774\uC804\uC5D0 \uB85C\uB4DC\uD55C \uACBD\uB85C\uC5D0\uC11C \uD604\uC7AC \uACBD\uB85C\uB85C \uADDC\uCE59 \uD30C\uC77C\uC744 \uB9C8\uC774\uADF8\uB808\uC774\uC158\uD569\uB2C8\uB2E4" ,
migrateSuccess : "\uADDC\uCE59 \uD30C\uC77C\uC774 \uC131\uACF5\uC801\uC73C\uB85C \uB9C8\uC774\uADF8\uB808\uC774\uC158\uB418\uC5C8\uC2B5\uB2C8\uB2E4"
},
selectionReplaceRule : {
name : "\uC120\uD0DD \uB300\uCCB4 \uADDC\uCE59" ,
desc : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC120\uD0DD \uB300\uCCB4 \uADDC\uCE59"
},
deleteRule : {
name : "\uC0AD\uC81C \uADDC\uCE59" ,
desc : "\uADDC\uCE59: |\uB85C \uCEE4\uC11C \uC704\uCE58\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4. \uD301: |\uB97C \uC0AC\uC6A9\uD558\uC5EC \uCEE4\uC11C \uC704\uCE58\uB97C \uB098\uD0C0\uB0C5\uB2C8\uB2E4."
},
convertRule : {
name : "\uBCC0\uD658 \uADDC\uCE59" ,
desc : "\uADDC\uCE59: |\uB85C \uCEE4\uC11C \uC704\uCE58\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4. \uD301: |\uB97C \uC0AC\uC6A9\uD558\uC5EC \uCEE4\uC11C \uC704\uCE58\uB97C \uB098\uD0C0\uB0C5\uB2C8\uB2E4."
},
trigger : {
name : "\uD2B8\uB9AC\uAC70"
},
left : {
name : "\uC67C\uCABD"
},
right : {
name : "\uC624\uB978\uCABD"
},
oldPattern : {
name : "\uC774\uC804 \uD328\uD134"
},
newPattern : {
name : "\uC0C8 \uD328\uD134"
},
ruleEditModal : {
addTitle : "\uADDC\uCE59 \uCD94\uAC00" ,
editTitle : "\uADDC\uCE59 \uD3B8\uC9D1" ,
fieldType : "\uC720\uD615" ,
fieldTrigger : "\uCEE4\uC11C \uC55E \uB9E4\uCE6D" ,
fieldTriggerSelectKey : "\uD2B8\uB9AC\uAC70 \uD0A4" ,
fieldTriggerRight : "\uCEE4\uC11C \uB4A4 \uB9E4\uCE6D" ,
hintTriggerEscape : "\\\\: \uBC31\uC2AC\uB798\uC2DC, \\n: \uC904\uBC14\uAFC8, \\t: \uD0ED" ,
fieldReplacement : "\uB300\uCCB4 \uB0B4\uC6A9" ,
fieldReplacementDescSelectKey : "${SEL}: \uC120\uD0DD\uB41C \uD14D\uC2A4\uD2B8, ${0:${SEL}}: \uD14D\uC2A4\uD2B8\uB97C \uC120\uD0DD\uD569\uB2C8\uB2E4." ,
fieldReplacementDescInputDelete : "[[0]]: \uC67C\uCABD 0\uBC88\uC9F8 \uCEA1\uCC98 \uADF8\uB8F9, [[R1]]: \uC624\uB978\uCABD 1\uBC88\uC9F8 \uCEA1\uCC98 \uADF8\uB8F9." ,
fieldIsRegex : "\uC815\uADDC\uC2DD\uC73C\uB85C \uB9E4\uCE6D" ,
fieldTriggerMode : "\uD2B8\uB9AC\uAC70 \uBC29\uC2DD" ,
fieldScope : "\uBC94\uC704" ,
fieldScopeLanguage : "\uC5B8\uC5B4 (\uC120\uD0DD\uC0AC\uD56D)" ,
fieldRegexFlags : "\uC815\uADDC\uC2DD \uD50C\uB798\uADF8" ,
fieldRegexFlagsDesc : "i / m / u \uB9CC \uC9C0\uC6D0, \uC608: im" ,
fieldPriority : "\uC6B0\uC120\uC21C\uC704" ,
fieldPriorityDesc : "\uC22B\uC790\uAC00 \uC791\uC744\uC218\uB85D \uC6B0\uC120\uC21C\uC704\uAC00 \uB192\uC74C, \uAE30\uBCF8\uAC12 100" ,
fieldDescription : "\uC124\uBA85" ,
buttonSave : "\uC800\uC7A5" ,
invalidRegex : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uC815\uADDC\uC2DD" ,
fieldIsFunction : "\uD568\uC218\uB85C \uB300\uCCB4" ,
functionHintInputDelete : "\uC778\uC218: leftMatches (string[]), rightMatches (string[]). \uBB38\uC790\uC5F4 \uB610\uB294 undefined\uB97C \uBC18\uD658\uD558\uC5EC \uAC74\uB108\uB701\uB2C8\uB2E4." ,
functionHintSelectKey : "\uC778\uC218: selectionText (string), key (string). \uBB38\uC790\uC5F4 \uB610\uB294 undefined\uB97C \uBC18\uD658\uD558\uC5EC \uAC74\uB108\uB701\uB2C8\uB2E4." ,
hintTabstop : "$0: \uCEE4\uC11C \uC704\uCE58, $1/$2: Tab \uC810\uD504 \uC704\uCE58, ${1:text}: \uC810\uD504 \uD6C4 text \uC120\uD0DD." ,
functionPlaceholder : "// \uC608\uC2DC:\nconst d = new Date();\nreturn d.toISOString().slice(0,10) + '$0';" ,
groupMatch : "\uB9E4\uCE6D \uC870\uAC74" ,
groupReplacement : "\uB300\uCCB4" ,
groupOther : "\uAE30\uD0C0"
},
ruleType : {
input : "\uC785\uB825" ,
delete : "\uC0AD\uC81C" ,
selectKey : "\uC120\uD0DD \uB300\uCCB4"
}
},
commands : {
formatArticle : "\uD604\uC7AC \uBB38\uC11C \uC11C\uC2DD \uC9C0\uC815" ,
formatSelection : "\uC120\uD0DD\uD55C \uD14D\uC2A4\uD2B8 \uB610\uB294 \uD604\uC7AC \uC904 \uC11C\uC2DD \uC9C0\uC815" ,
deleteBlankLine : "\uC120\uD0DD \uC601\uC5ED \uB610\uB294 \uC804\uCCB4 \uBB38\uC11C\uC758 \uBE48 \uC904 \uC0AD\uC81C" ,
insertCodeblock : "\uCF54\uB4DC \uBE14\uB85D \uC0BD\uC785" ,
switchAutoformat : "\uC790\uB3D9 \uC11C\uC2DD \uC804\uD658" ,
pasteWithoutFormat : "\uC11C\uC2DD \uC5C6\uC774 \uBD99\uC5EC\uB123\uAE30" ,
toggleComment : "\uC8FC\uC11D \uC804\uD658" ,
gotoNewLine : "\uD604\uC7AC \uC904 \uB2E4\uC74C\uC5D0 \uC0C8 \uC904\uB85C \uC774\uB3D9" ,
selectBlock : "\uD604\uC7AC \uD14D\uC2A4\uD2B8 \uBE14\uB85D \uC120\uD0DD"
},
headers : {
main : "Obsidian EasyTyping \uD50C\uB7EC\uADF8\uC778" ,
githubDetail : "\uC790\uC138\uD55C \uB0B4\uC6A9\uC740 Github\uB97C \uCC38\uC870\uD558\uC138\uC694: " ,
enhancedEditing : "\uD3B8\uC9D1 \uAC15\uD654 \uC124\uC815" ,
customizeEditRule : "\uD3B8\uC9D1 \uBCC0\uD658 \uADDC\uCE59 \uC0AC\uC6A9\uC790 \uC815\uC758" ,
autoformatSetting : "\uC790\uB3D9 \uC11C\uC2DD \uC124\uC815" ,
detailedSetting : "\uC778\uB77C\uC778 \uC694\uC18C \uAC04 \uAC04\uACA9" ,
customRegexpBlock : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uC815\uADDC\uC2DD \uBE14\uB85D" ,
excludeFoldersFiles : "\uC81C\uC678 \uD3F4\uB354/\uD30C\uC77C" ,
experimentalFeatures : "\uC2E4\uD5D8\uC801 \uAE30\uB2A5" ,
languagePairSection : "\uC5B8\uC5B4 \uC30D \uAC04\uACA9" ,
addLanguagePair : "\uC0C8 \uC5B8\uC5B4/\uAE30\uD638 \uC30D \uCD94\uAC00:" ,
prefixDictSection : "\uC811\uB450\uC0AC \uC0AC\uC804" ,
softSpaceSection : "\uC18C\uD504\uD2B8 \uC2A4\uD398\uC774\uC2A4 \uAE30\uD638" ,
customScriptSection : "\uC0AC\uC6A9\uC790 \uC815\uC758 \uBB38\uC790 \uBC94\uC8FC" ,
spaceStrategyIntro : "\uAC04\uACA9 \uC804\uB7B5 \uC124\uBA85:\n\uBD88\uD544\uC694: \uC774 \uBC94\uC8FC \uBE14\uB85D\uACFC \uC8FC\uBCC0 \uD14D\uC2A4\uD2B8 \uC0AC\uC774\uC5D0 \uAC04\uACA9\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4.\n\uC18C\uD504\uD2B8 \uC2A4\uD398\uC774\uC2A4: \uC774 \uBC94\uC8FC \uBE14\uB85D\uACFC \uC8FC\uBCC0 \uBE14\uB85D \uC0AC\uC774\uC5D0 \uC18C\uD504\uD2B8 \uC2A4\uD398\uC774\uC2A4\uB9CC \uD544\uC694\uD569\uB2C8\uB2E4 (\uC608: \uC778\uC811 \uD14D\uC2A4\uD2B8\uAC00 \uBB38\uC7A5\uBD80\uD638\uC778 \uACBD\uC6B0 \uC2E4\uC81C \uACF5\uBC31\uC774 \uCD94\uAC00\uB418\uC9C0 \uC54A\uC74C).\n\uC5C4\uACA9\uD55C \uC2A4\uD398\uC774\uC2A4: \uD604\uC7AC \uBE14\uB85D\uACFC \uC778\uC811 \uD14D\uC2A4\uD2B8 \uC0AC\uC774\uC5D0 \uC5C4\uACA9\uD558\uAC8C \uC2E4\uC81C \uACF5\uBC31\uC744 \uCD94\uAC00\uD569\uB2C8\uB2E4." ,
aboutRegexp : {
header : "\uC815\uADDC\uC2DD\uC5D0 \uB300\uD55C \uC790\uC138\uD55C \uB0B4\uC6A9\uC740 \uB2E4\uC74C\uC744 \uCC38\uC870\uD558\uC138\uC694: " ,
text : "\uC815\uADDC\uC2DD \uAC04\uACB0 \uD29C\uD1A0\uB9AC\uC5BC"
},
customizeSelectionRule : "\uC120\uD0DD \uB300\uCCB4 \uADDC\uCE59 \uC0AC\uC6A9\uC790 \uC815\uC758" ,
customizeDeleteRule : "\uC0AD\uC81C \uADDC\uCE59 \uC0AC\uC6A9\uC790 \uC815\uC758" ,
customizeConvertRule : "\uBCC0\uD658 \uADDC\uCE59 \uC0AC\uC6A9\uC790 \uC815\uC758" ,
editSelectionReplaceRule : "\uC120\uD0DD \uB300\uCCB4 \uADDC\uCE59 \uD3B8\uC9D1" ,
builtinRulesSection : "\uB0B4\uC7A5 \uADDC\uCE59" ,
userRulesSection : "\uC0AC\uC6A9\uC790 \uADDC\uCE59" ,
deletedRulesSection : "\uC0AD\uC81C\uB41C \uB0B4\uC7A5 \uADDC\uCE59" ,
tabs : {
editEnhance : "\uD3B8\uC9D1 \uAC15\uD654" ,
autoFormat : "\uC790\uB3D9 \uC11C\uC2DD" ,
builtinRules : "\uB0B4\uC7A5 \uADDC\uCE59" ,
userRules : "\uC0AC\uC6A9\uC790 \uADDC\uCE59" ,
other : "\uAE30\uD0C0"
}
},
dropdownOptions : {
enterTwice : "Enter \uB450 \uBC88" ,
twoSpace : "\uACF5\uBC31 \uB450 \uAC1C" ,
mixMode : "\uD63C\uD569 \uBAA8\uB4DC" ,
noRequire : "\uBD88\uD544\uC694" ,
softSpace : "\uC18C\uD504\uD2B8 \uC2A4\uD398\uC774\uC2A4" ,
strictSpace : "\uC5C4\uACA9\uD55C \uC2A4\uD398\uC774\uC2A4" ,
dummy : "\uB354\uBBF8" ,
smart : "\uC2A4\uB9C8\uD2B8" ,
scopeAll : "\uC804\uCCB4" ,
scopeText : "\uD14D\uC2A4\uD2B8" ,
scopeFormula : "\uC218\uC2DD" ,
scopeCode : "\uCF54\uB4DC" ,
triggerModeAuto : "\uC790\uB3D9" ,
triggerModeTab : "Tab" ,
ruleTypeInput : "\uC785\uB825" ,
ruleTypeDelete : "\uC0AD\uC81C" ,
ruleTypeSelectKey : "\uC120\uD0DD \uB300\uCCB4"
},
toolTip : {
switch : "\uC2A4\uC704\uCE58" ,
editRule : "\uADDC\uCE59 \uD3B8\uC9D1" ,
removeRule : "\uADDC\uCE59 \uC0AD\uC81C" ,
addRule : "\uADDC\uCE59 \uCD94\uAC00" ,
enableRule : "\uADDC\uCE59 \uD65C\uC131\uD654/\uBE44\uD65C\uC131\uD654" ,
restoreRule : "\uC774 \uADDC\uCE59 \uBCF5\uC6D0" ,
resetAllRules : "\uBAA8\uB4E0 \uB0B4\uC7A5 \uADDC\uCE59 \uCD08\uAE30\uD654" ,
resetSuccess : "\uB0B4\uC7A5 \uADDC\uCE59\uC774 \uC131\uACF5\uC801\uC73C\uB85C \uCD08\uAE30\uD654\uB418\uC5C8\uC2B5\uB2C8\uB2E4" ,
exportRules : "\uADDC\uCE59 \uB0B4\uBCF4\uB0B4\uAE30" ,
importRules : "\uADDC\uCE59 \uAC00\uC838\uC624\uAE30" ,
noRulesToExport : "\uB0B4\uBCF4\uB0BC \uC0AC\uC6A9\uC790 \uADDC\uCE59\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" ,
importSuccess : "%d\uAC1C \uADDC\uCE59\uC744 \uAC00\uC838\uC654\uC73C\uBA70, %d\uAC1C \uC911\uBCF5 \uADDC\uCE59\uC744 \uAC74\uB108\uB6F0\uC5C8\uC2B5\uB2C8\uB2E4" ,
importInvalidJson : "\uC798\uBABB\uB41C \uD30C\uC77C: \uC720\uD6A8\uD55C JSON\uC774 \uC544\uB2D9\uB2C8\uB2E4" ,
importNoRules : "\uD30C\uC77C\uC5D0\uC11C \uAC00\uC838\uC62C \uC218 \uC788\uB294 \uADDC\uCE59\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
},
placeHolder : {
triggerSymbol : "\uD2B8\uB9AC\uAC70 \uAE30\uD638" ,
newLeftSideString : "\uC0C8 \uC67C\uCABD \uBB38\uC790\uC5F4" ,
newRightSideString : "\uC0C8 \uC624\uB978\uCABD \uBB38\uC790\uC5F4" ,
addRule : "\uADDC\uCE59 \uCD94\uAC00" ,
noticeInvaidTrigger : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD2B8\uB9AC\uAC70, \uD2B8\uB9AC\uAC70\uB294 \uAE38\uC774 1\uC758 \uAE30\uD638 \uB610\uB294 \u2014\u2014, \u2026\u2026 \uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4" ,
noticeWarnTriggerExists : "\uACBD\uACE0! \uD2B8\uB9AC\uAC70 %s \uC774(\uAC00) \uC774\uBBF8 \uC874\uC7AC\uD569\uB2C8\uB2E4!" ,
noticeMissingInput : "\uC785\uB825\uC774 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4" ,
beforeDelete : "\uC0AD\uC81C \uC804" ,
newPattern : "\uC0C8 \uD328\uD134" ,
noticeInvaidTriggerPatternContainSymbol : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD2B8\uB9AC\uAC70, \uD328\uD134\uC5D0 \uCEE4\uC11C \uC704\uCE58\uB97C \uB098\uD0C0\uB0B4\uB294 \uAE30\uD638 |\uAC00 \uD3EC\uD568\uB418\uC5B4\uC57C \uD569\uB2C8\uB2E4" ,
beforeConvert : "\uBCC0\uD658 \uC804" ,
noticeInvalidPatternString : "\uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uD328\uD134 \uBB38\uC790\uC5F4\uC785\uB2C8\uB2E4!"
},
button : {
update : "\uC5C5\uB370\uC774\uD2B8"
},
scriptCategoryLabels : {
chinese : "\uC911\uAD6D\uC5B4" ,
japanese : "\uC77C\uBCF8\uC5B4" ,
korean : "\uD55C\uAD6D\uC5B4" ,
cjk : "CJK" ,
english : "\uC601\uC5B4" ,
digit : "\uC22B\uC790" ,
russian : "\uB7EC\uC2DC\uC544\uC5B4" ,
unknown : "\uC54C \uC218 \uC5C6\uC74C"
},
builtinRuleDescriptions : {
"builtin-autopair-input" : "\uC804\uAC01 \uAD04\uD638/\uB530\uC634\uD45C \uC785\uB825 \uC2DC \uC790\uB3D9 \uC644\uC131" ,
"builtin-autopair-jump" : "\uB2EB\uB294 \uC30D \uAE30\uD638\uB97C \uC785\uB825\uD560 \uB54C \uC790\uB3D9\uC73C\uB85C \uAC74\uB108\uB6F0\uC5B4 \uC911\uBCF5 \uBC29\uC9C0" ,
"builtin-autopair-delete" : "\uC804\uAC01 \uAD04\uD638/\uB530\uC634\uD45C \uC0AD\uC81C \uC2DC \uC30D\uC73C\uB85C \uC0AD\uC81C" ,
"builtin-conv-backtick" : "\uC911\uAC04\uC810 \xB7\xB7 \uC5F0\uC18D \uC785\uB825 \uC2DC \uC778\uB77C\uC778 \uCF54\uB4DC\uB85C \uBCC0\uD658" ,
"builtin-conv-codeblock" : "\uC778\uB77C\uC778 \uCF54\uB4DC \uB0B4\uC5D0\uC11C \xB7 \uC785\uB825 \uC2DC \uCF54\uB4DC \uBE14\uB85D\uC73C\uB85C \uC5C5\uADF8\uB808\uC774\uB4DC" ,
"builtin-conv-formula" : "\uFFE5/$ \uC870\uD569\uC73C\uB85C \uC778\uB77C\uC778 \uB610\uB294 \uBE14\uB85D \uC218\uC2DD\uC73C\uB85C \uBCC0\uD658" ,
"builtin-conv-linestart" : "\uC904 \uC2DC\uC791\uC5D0\uC11C \u300B \u2192 \uC778\uC6A9 \uD45C\uC2DC, \u3001 \u2192 \uC2AC\uB798\uC2DC" ,
"builtin-conv-hw2fw" : "CJK \uBB38\uC790 \uB4A4 \uBC18\uAC01 \uBB38\uC7A5\uBD80\uD638\uB97C \uC804\uAC01\uC73C\uB85C \uBCC0\uD658" ,
"builtin-fw2hw-double" : "\uB3D9\uC77C\uD55C \uC804\uAC01 \uBB38\uC7A5\uBD80\uD638 \uB450 \uBC88 \uC785\uB825 \uC2DC \uBC18\uAC01\uC73C\uB85C \uBCC0\uD658" ,
"builtin-del-inline-formula" : "\uC778\uB77C\uC778 \uC218\uC2DD $...$ \uC30D \uC0AD\uC81C" ,
"builtin-del-highlight" : "\uD558\uC774\uB77C\uC774\uD2B8 ==...== \uC30D \uC0AD\uC81C" ,
"builtin-del-block-formula" : "\uBE14\uB85D \uC218\uC2DD $$...$$ \uC30D \uC0AD\uC81C" ,
"builtin-del-codeblock" : "\uBE48 \uCF54\uB4DC \uBE14\uB85D \uBE60\uB978 \uC0AD\uC81C" ,
"builtin-del-wikilink" : "\uC704\uD0A4\uB9C1\uD06C \uBC0F \uC784\uBCA0\uB4DC(![[]]) \uBE60\uB978 \uC0AD\uC81C" ,
"builtin-sel-wrap-backtick" : "\xB7 \uB85C \uC120\uD0DD \uD14D\uC2A4\uD2B8\uB97C \uBC31\uD2F1\uC73C\uB85C \uAC10\uC2F8\uAE30" ,
"builtin-sel-wrap-symbols" : "\uC120\uD0DD\uD55C \uD14D\uC2A4\uD2B8\uB97C \u3010/\xA5/\uFFE5\uB85C []/$$\uB85C \uAC10\uC2F8\uAE30" ,
"builtin-sel-wrap-quotes" : "\uC120\uD0DD\uD55C \uD14D\uC2A4\uD2B8\uB97C \uC804\uAC01 \uB530\uC634\uD45C\uB85C \uAC10\uC2F8\uAE30" ,
"builtin-sel-wrap-cjk-brackets" : "\uC120\uD0DD\uD55C \uD14D\uC2A4\uD2B8\uB97C \u300A\u300B \uB610\uB294 \uFF08\uFF09 \uAD04\uD638\uB85C \uAC10\uC2F8\uAE30" ,
"builtin-quote-convert" : "> \uB610\uB294 \u300B\uB97C Markdown \uC778\uC6A9 \uD45C\uC2DC\uB85C \uBCC0\uD658" ,
"builtin-quote-space" : "\uC778\uC6A9 \uD45C\uC2DC > \uB4A4\uC5D0 \uC790\uB3D9\uC73C\uB85C \uACF5\uBC31 \uC0BD\uC785"
}
};
var ko_KR_default = locale6 ;
// src/lang/locale/index.ts
var localeMap = {
"en" : en_US_default ,
"zh" : zh_CN_default ,
"zh-cn" : zh_CN_default ,
"zh-tw" : zh_TW_default ,
"ru" : ru_RU_default ,
"ja" : ja_JP_default ,
"ko" : ko_KR_default
};
var cached = null ;
function getLocale () {
var _a ;
if ( cached )
return cached ;
const lang = import_obsidian2 . moment . locale (). toLowerCase ();
cached = ( _a = localeMap [ lang ]) != null ? _a : en_US_default ;
return cached ;
}
// src/rule_engine.ts
var import_obsidian3 = require ( "obsidian" );
function escapeRegex ( s ) {
return s . replace ( /[.*+?^${}()|[\]\\]/g , "\\$&" );
}
var RuleEngine = class {
constructor () {
this . rulesById = /* @__PURE__ */ new Map ();
this . sortedRules = [];
this . ruleIdCounter = 0 ;
this . fnErrorLastNotify = /* @__PURE__ */ new Map ();
this . regexCache = /* @__PURE__ */ new Map ();
}
static parseOptions ( options = "" ) {
const type = options . includes ( "d" ) ? "delete" /* Delete */ : options . includes ( "s" ) ? "selectKey" /* SelectKey */ : "input" /* Input */ ;
const triggerMode = options . includes ( "T" ) ? "tab" /* Tab */ : "auto" /* Auto */ ;
const isRegex = options . includes ( "r" );
const isFunctionReplacement = options . includes ( "F" );
const scope = [];
if ( options . includes ( "a" ) || ! options . includes ( "t" ) && ! options . includes ( "f" ) && ! options . includes ( "c" )) {
scope . push ( "all" /* All */ );
} else {
if ( options . includes ( "t" ))
scope . push ( "text" /* Text */ );
if ( options . includes ( "f" ))
scope . push ( "formula" /* Formula */ );
if ( options . includes ( "c" ))
scope . push ( "code" /* Code */ );
}
return { type , triggerMode , isRegex , isFunctionReplacement , scope };
}
static normalizeRegexFlags ( flags = "" ) {
const normalized = flags . toLowerCase (). replace ( /[^imu]/g , "" );
return Array . from ( new Set ( normalized . split ( "" ))). sort (( a , b ) => "imu" . indexOf ( a ) - "imu" . indexOf ( b )). join ( "" );
}
static validateRegex ( rule ) {
var _a ;
const opts = RuleEngine . parseOptions ( rule . options );
if ( ! opts . isRegex )
return null ;
const regexFlags = RuleEngine . normalizeRegexFlags ( rule . regex_flags );
const leftPattern = rule . trigger ;
const rightPattern = ( _a = rule . trigger_right ) != null ? _a : "" ;
if ( leftPattern ) {
try {
new RegExp ( "(?:" + leftPattern + ")" , regexFlags );
} catch ( e ) {
return `trigger: ${ e . message } ` ;
}
}
if ( rightPattern ) {
try {
new RegExp ( "(?:" + rightPattern + ")" , regexFlags );
} catch ( e ) {
return `trigger_right: ${ e . message } ` ;
}
}
return null ;
}
static escapeText ( text , preserveBackslashes = false ) {
let result = text ;
if ( ! preserveBackslashes ) {
result = result . replace ( /\\/g , "\\\\" );
}
return result . replace ( /\n/g , "\\n" ). replace ( /\t/g , "\\t" ). replace ( /\r/g , "\\r" );
}
static unescapeText ( text ) {
let result = "" ;
for ( let i = 0 ; i < text . length ; i ++ ) {
if ( text [ i ] === "\\" && i + 1 < text . length ) {
switch ( text [ i + 1 ]) {
case "n" :
result += "\n" ;
i ++ ;
break ;
case "t" :
result += " " ;
i ++ ;
break ;
case "r" :
result += "\r" ;
i ++ ;
break ;
case "\\" :
result += "\\" ;
i ++ ;
break ;
default :
result += text [ i ];
break ;
}
} else {
result += text [ i ];
}
}
return result ;
}
static parseSelectKeyRuleTriggerKeys ( pattern ) {
const keys = [];
for ( let i = 0 ; i < pattern . length ; i ++ ) {
if ( pattern [ i ] === "\\" && i + 1 < pattern . length ) {
keys . push ( pattern [ i + 1 ]);
i ++ ;
} else {
keys . push ( pattern [ i ]);
}
}
return keys ;
}
static normalizeRule ( simple ) {
var _a , _b , _c , _d , _e , _f , _g , _h , _i ;
const opts = RuleEngine . parseOptions ( simple . options );
let replacement = simple . replacement ;
if ( opts . isFunctionReplacement && typeof simple . replacement === "string" ) {
try {
if ( opts . type === "selectKey" /* SelectKey */ ) {
replacement = new Function ( "selectionText" , "key" , simple . replacement );
} else {
replacement = new Function ( "leftMatches" , "rightMatches" , simple . replacement );
}
} catch ( e ) {
console . error ( `[RuleEngine] Failed to compile function for rule " ${ ( _a = simple . id ) != null ? _a : "?" } ":` , e );
replacement = () => void 0 ;
new import_obsidian3 . Notice ( `[EasyTyping] Rule " ${ ( _b = simple . id ) != null ? _b : "?" } " has invalid function body: ${ e . message } ` );
}
}
if ( opts . type === "selectKey" /* SelectKey */ ) {
return {
description : ( _c = simple . description ) != null ? _c : "" ,
enabled : ( _d = simple . enabled ) != null ? _d : true ,
type : "selectKey" /* SelectKey */ ,
triggerMode : "auto" /* Auto */ ,
triggerKeys : RuleEngine . parseSelectKeyRuleTriggerKeys ( simple . trigger ),
scope : opts . scope ,
scopeLanguage : simple . scope_language ,
regexFlags : void 0 ,
priority : ( _e = simple . priority ) != null ? _e : 100 ,
match : { left : "" , right : "" , isRegex : false },
replacement
};
}
const triggerMode = opts . type === "input" /* Input */ ? opts . triggerMode : "auto" /* Auto */ ;
return {
description : ( _f = simple . description ) != null ? _f : "" ,
enabled : ( _g = simple . enabled ) != null ? _g : true ,
type : opts . type ,
triggerMode ,
triggerKeys : void 0 ,
scope : opts . scope ,
scopeLanguage : simple . scope_language ,
regexFlags : opts . isRegex ? RuleEngine . normalizeRegexFlags ( simple . regex_flags ) : void 0 ,
priority : ( _h = simple . priority ) != null ? _h : 100 ,
match : {
left : simple . trigger ,
right : ( _i = simple . trigger_right ) != null ? _i : "" ,
isRegex : opts . isRegex
},
replacement
};
}
generateId () {
return `rule- ${ ++ this . ruleIdCounter } ` ;
}
insertSorted ( rule ) {
let lo = 0 , hi = this . sortedRules . length ;
while ( lo < hi ) {
const mid = lo + hi >>> 1 ;
if ( this . sortedRules [ mid ]. priority <= rule . priority )
lo = mid + 1 ;
else
hi = mid ;
}
this . sortedRules . splice ( lo , 0 , rule );
}
addRule ( rule ) {
var _a ;
const id = ( _a = rule . id ) != null ? _a : this . generateId ();
const fullRule = { ... rule , id };
this . rulesById . set ( id , fullRule );
this . insertSorted ( fullRule );
return id ;
}
addSimpleRule ( simple ) {
const normalized = RuleEngine . normalizeRule ( simple );
return this . addRule ({ ... normalized , id : simple . id });
}
addSimpleRules ( rules ) {
return rules . map (( r ) => this . addSimpleRule ( r ));
}
removeRule ( id ) {
if ( ! this . rulesById . has ( id ))
return false ;
this . rulesById . delete ( id );
this . regexCache . delete ( id );
const idx = this . sortedRules . findIndex (( r ) => r . id === id );
if ( idx !== - 1 )
this . sortedRules . splice ( idx , 1 );
return true ;
}
updateRule ( id , patch ) {
const existing = this . rulesById . get ( id );
if ( ! existing )
return false ;
if ( patch . match !== void 0 || patch . type !== void 0 || patch . regexFlags !== void 0 ) {
this . regexCache . delete ( id );
}
const priorityChanged = patch . priority !== void 0 && patch . priority !== existing . priority ;
Object . assign ( existing , patch );
if ( priorityChanged ) {
const idx = this . sortedRules . findIndex (( r ) => r . id === id );
if ( idx !== - 1 )
this . sortedRules . splice ( idx , 1 );
this . insertSorted ( existing );
}
return true ;
}
setEnabled ( id , enabled ) {
const rule = this . rulesById . get ( id );
if ( rule )
rule . enabled = enabled ;
}
getRules () {
return this . sortedRules ;
}
getRulesByType ( type ) {
return this . sortedRules . filter (( r ) => r . type === type );
}
getRule ( id ) {
return this . rulesById . get ( id );
}
clear () {
this . rulesById . clear ();
this . sortedRules = [];
this . regexCache . clear ();
}
loadFromFiles ( builtinRules , userRules ) {
this . clear ();
this . addSimpleRules ( builtinRules );
this . addSimpleRules ( userRules );
}
getCachedRegex ( rule ) {
const existing = this . regexCache . get ( rule . id );
if ( existing !== void 0 )
return existing ;
const leftPattern = rule . match . isRegex ? rule . match . left : escapeRegex ( rule . match . left );
const rightPattern = rule . match . isRegex ? rule . match . right : escapeRegex ( rule . match . right );
const regexFlags = rule . match . isRegex ? RuleEngine . normalizeRegexFlags ( rule . regexFlags ) : "" ;
try {
const cached2 = {
left : leftPattern ? new RegExp ( "(?:" + leftPattern + ")(?![\\s\\S])" , regexFlags ) : null ,
right : rightPattern ? new RegExp ( "(?:" + rightPattern + ")" , regexFlags ) : null
};
this . regexCache . set ( rule . id , cached2 );
return cached2 ;
} catch ( e ) {
console . error ( `[RuleEngine] Invalid regex in rule " ${ rule . id } ":` , e );
new import_obsidian3 . Notice ( `[EasyTyping] Rule " ${ rule . id } " has invalid regex: ${ e . message } ` );
this . regexCache . set ( rule . id , null );
return null ;
}
}
expandVariables ( text , match ) {
text = text . replace ( /\[\[R(\d+)\]\]/g , ( _ , n ) => {
var _a ;
const idx = parseInt ( n );
return ( _a = match . rightMatches [ idx ]) != null ? _a : "" ;
});
text = text . replace ( /\[\[(\d+)\]\]/g , ( _ , n ) => {
var _a , _b ;
const idx = parseInt ( n );
return ( _b = ( _a = match . leftMatches [ idx ]) != null ? _a : match . rightMatches [ idx ]) != null ? _b : "" ;
});
if ( match . selectionText !== void 0 ) {
text = text . replace ( /\$\{SEL\}/g , match . selectionText );
}
if ( match . key !== void 0 ) {
text = text . replace ( /\$\{KEY\}/g , match . key );
}
return text ;
}
findMatchingBrace ( text , openIdx ) {
let depth = 1 ;
for ( let i = openIdx + 1 ; i < text . length ; i ++ ) {
if ( text [ i ] === "{" )
depth ++ ;
else if ( text [ i ] === "}" ) {
depth -- ;
if ( depth === 0 )
return i ;
}
}
return - 1 ;
}
parseTabstops ( text , baseOffset , match ) {
const tabstops = [];
let result = "" ;
let i = 0 ;
while ( i < text . length ) {
if ( text [ i ] === "$" ) {
if ( i + 1 < text . length && text [ i + 1 ] === "{" ) {
const closeIdx = this . findMatchingBrace ( text , i + 1 );
if ( closeIdx === - 1 ) {
result += text [ i ];
i ++ ;
continue ;
}
const inner = text . substring ( i + 2 , closeIdx );
const colonIdx = inner . indexOf ( ":" );
let num ;
let defaultVal ;
if ( colonIdx > - 1 ) {
num = parseInt ( inner . substring ( 0 , colonIdx ));
defaultVal = inner . substring ( colonIdx + 1 );
if (( match == null ? void 0 : match . selectionText ) !== void 0 )
defaultVal = defaultVal . replace ( /\$\{SEL\}/g , match . selectionText );
if (( match == null ? void 0 : match . key ) !== void 0 )
defaultVal = defaultVal . replace ( /\$\{KEY\}/g , match . key );
} else {
num = parseInt ( inner );
defaultVal = "" ;
}
const from = baseOffset + result . length ;
result += defaultVal ;
const to = baseOffset + result . length ;
tabstops . push ({ number : num , from , to });
i = closeIdx + 1 ;
} else if ( i + 1 < text . length && /\d/ . test ( text [ i + 1 ])) {
let numStr = "" ;
let j = i + 1 ;
while ( j < text . length && /\d/ . test ( text [ j ])) {
numStr += text [ j ];
j ++ ;
}
const num = parseInt ( numStr );
const pos = baseOffset + result . length ;
tabstops . push ({ number : num , from : pos , to : pos });
i = j ;
} else {
result += text [ i ];
i ++ ;
}
} else {
result += text [ i ];
i ++ ;
}
}
tabstops . sort (( a , b ) => a . number - b . number );
return [ result , tabstops ];
}
notifyFunctionError ( ruleId , error ) {
var _a ;
const now = Date . now ();
const last = ( _a = this . fnErrorLastNotify . get ( ruleId )) != null ? _a : 0 ;
if ( now - last > 5e3 ) {
this . fnErrorLastNotify . set ( ruleId , now );
const msg = error instanceof Error ? error . message : String ( error );
new import_obsidian3 . Notice ( `[EasyTyping] Rule " ${ ruleId } " runtime error: ${ msg } ` );
}
console . error ( `[RuleEngine] Runtime error in rule " ${ ruleId } ":` , error );
}
process ( ctx ) {
var _a ;
for ( const rule of this . sortedRules ) {
if ( ! rule . enabled )
continue ;
if ( rule . type !== ctx . kind )
continue ;
if ( rule . triggerMode === "tab" /* Tab */ && ctx . changeType !== "tab" )
continue ;
if ( rule . triggerMode === "auto" /* Auto */ && ctx . changeType === "tab" )
continue ;
if ( ctx . scopeHint !== "all" /* All */ && ! rule . scope . includes ( "all" /* All */ ) && ! rule . scope . includes ( ctx . scopeHint ))
continue ;
if ( rule . scopeLanguage && ctx . scopeHint === "code" /* Code */ && rule . scope . includes ( "code" /* Code */ ) && ctx . scopeLanguage !== rule . scopeLanguage )
continue ;
switch ( ctx . kind ) {
case "selectKey" /* SelectKey */ : {
if ( ! (( _a = rule . triggerKeys ) == null ? void 0 : _a . includes ( ctx . key )))
continue ;
const result = this . applySelectKeyRule ( rule , ctx );
if ( result ) {
if ( ctx . debug )
console . log ( "[RuleEngine] hit:" , rule . id , rule . description );
return result ;
}
break ;
}
default : {
const result = this . matchAndApplyTextRule ( rule , ctx );
if ( result ) {
if ( ctx . debug )
console . log ( "[RuleEngine] hit:" , rule . id , rule . description );
return result ;
}
break ;
}
}
}
return null ;
}
matchAndApplyTextRule ( rule , ctx ) {
const { from , to } = ctx . selection ;
const leftDoc = ctx . docText . slice ( 0 , from );
const rightDoc = ctx . docText . slice ( to );
const cached2 = this . getCachedRegex ( rule );
if ( ! cached2 )
return null ;
const leftRegex = cached2 . left ;
const rightRegex = cached2 . right ;
const leftMatch = leftRegex ? leftRegex . exec ( leftDoc ) : [ "" ];
const rightMatch = rightRegex ? this . matchAtStart ( rightDoc , rightRegex ) : [ "" ];
if ( ! leftMatch || ! rightMatch )
return null ;
const matchFrom = from - leftMatch [ 0 ]. length ;
const matchTo = to + rightMatch [ 0 ]. length ;
return this . applyReplacement ( rule , {
leftMatches : [... leftMatch ],
rightMatches : [... rightMatch ],
matchRange : { from : matchFrom , to : matchTo }
}, ctx );
}
matchAtStart ( doc , regex ) {
regex . lastIndex = 0 ;
const match = regex . exec ( doc );
if ( ! match || match . index !== 0 )
return null ;
return match ;
}
applySelectKeyRule ( rule , ctx ) {
const selectionText = ctx . docText . slice ( ctx . selection . from , ctx . selection . to );
return this . applyReplacement ( rule , {
leftMatches : [],
rightMatches : [],
matchRange : ctx . selection ,
selectionText ,
key : ctx . key
}, ctx );
}
applyReplacement ( rule , match , ctx ) {
let text ;
if ( typeof rule . replacement === "function" ) {
try {
if ( rule . type === "selectKey" /* SelectKey */ ) {
const fn = rule . replacement ;
const result = fn ( match . selectionText , match . key );
if ( result === void 0 )
return null ;
text = result ;
} else {
const fn = rule . replacement ;
const result = fn ( match . leftMatches , match . rightMatches );
if ( result === void 0 )
return null ;
text = result ;
}
} catch ( e ) {
this . notifyFunctionError ( rule . id , e );
return null ;
}
} else {
text = rule . replacement ;
}
text = RuleEngine . unescapeText ( text );
text = this . expandVariables ( text , match );
const [ finalText , tabstops ] = this . parseTabstops ( text , match . matchRange . from , match );
const cursor = tabstops . length > 0 ? tabstops [ 0 ]. from : match . matchRange . from + finalText . length ;
return {
newText : finalText ,
cursor ,
tabstops ,
matchRange : match . matchRange
};
}
};
// src/default_rules.ts
var DEFAULT_BUILTIN_RULES = [
{
id : "builtin-autopair-input" ,
trigger : "[\uFF08\u300A\u300C\u300E\u201C\u201D\u2018\u2019\u300A]" ,
replacement : "const p={'\u3010':'\u3010$0\u3011','\uFF08':'\uFF08$0\uFF09','\u300A':'\u300A$0\u300B','\u300C':'\u300C$0\u300D','\u300E':'\u300E$0\u300F','\u201C':'\u201C$0\u201D','\u201D':'\u201C$0\u201D','\u2018':'\u2018$0\u2019','\u2019':'\u2018$0\u2019','\u300A':'\u300A$0\u300B'}; return p[leftMatches[0]];" ,
options : "rF" ,
priority : 10 ,
description : "\u8F93\u5165\u5168\u89D2\u62EC\u53F7/\u5F15\u53F7\u65F6\u81EA\u52A8\u8865\u5168\u914D\u5BF9"
},
{
id : "builtin-autopair-jump" ,
trigger : "\u300A\u300B|\u201C\u201D|\u201C\u201C|\u2018\u2019|\u2018\u2018|\uFF08\uFF09" ,
trigger_right : "\u300B|\u201D|\u2019|\uFF09" ,
replacement : 'const map = {\n "\u300A\u300B": ["\u300B", "\u300A\u300B"],\n "\uFF08\uFF09": ["\uFF09", "\uFF08\uFF09"],\n "\u201C\u201D": ["\u201D", "\u201C\u201D"],\n "\u201C\u201C": ["\u201D", "\u201C\u201D"],\n "\u2018\u2019": ["\u2019", "\u2018\u2019"],\n "\u2018\u2018": ["\u2019", "\u2018\u2019"]\n}\nif(map[leftMatches[0]][0]==rightMatches[0]){\n return map[leftMatches[0]][1];\n}\nreturn undefined;' ,
options : "rF" ,
priority : 5 ,
description : "\u8F93\u5165\u53F3\u4FA7\u914D\u5BF9\u7B26\u53F7\u65F6\u81EA\u52A8\u8DF3\u8FC7\uFF0C\u907F\u514D\u91CD\u590D\u63D2\u5165"
},
{
id : "builtin-autopair-delete" ,
trigger : "[\u3010\uFF08\u300A\u300C\u300E\u201C\u2018]" ,
trigger_right : "[\u3011\uFF09\u300B\u300D\u300F\u201D\u2019]" ,
replacement : "const p={'\u3010':'\u3011','\uFF08':'\uFF09','\u300A':'\u300B','\u300C':'\u300D','\u300E':'\u300F','\u201C':'\u201D','\u2018':'\u2019'}; return p[leftMatches[0]]===rightMatches[0] ? '' : undefined;" ,
options : "drF" ,
priority : 10 ,
description : "\u5220\u9664\u5168\u89D2\u62EC\u53F7/\u5F15\u53F7\u65F6\u540C\u65F6\u5220\u9664\u914D\u5BF9"
},
{ id : "builtin-conv-backtick" , trigger : "\xB7\xB7" , replacement : "`$0`" , priority : 10 , description : "\u8FDE\u7EED\u4E2D\u6587\u95F4\u9694\u53F7 \xB7\xB7 \u8F6C\u884C\u5185\u4EE3\u7801" },
{
id : "builtin-conv-codeblock" ,
trigger : "(?<=^|\\n)([ \\t]*)`\xB7" ,
trigger_right : "`" ,
replacement : "[[1]]```$0\n[[1]]```" ,
options : "r" ,
priority : 10 ,
description : "\u884C\u5185\u4EE3\u7801\u4E2D\u7EE7\u7EED\u8F93\u5165 \xB7 \u5347\u7EA7\u4E3A\u4EE3\u7801\u5757"
},
{
id : "builtin-conv-formula" ,
trigger : "(\uFFE5\uFFE5|\xA5\xA5|\\$\uFFE5|\\$\xA5|\\$\\$)" ,
trigger_right : "\\$?" ,
replacement : "return rightMatches[0] === '$' ? '$$\\n$0\\n$$' : '$$0$';" ,
options : "rF" ,
priority : 10 ,
description : "\uFFE5/$ \u7B26\u53F7\u7EC4\u5408\u8F6C\u884C\u5185\u6216\u5757\u7EA7\u516C\u5F0F"
},
{
id : "builtin-conv-linestart" ,
trigger : "(^|\\n)([\u300B\u3001])" ,
replacement : "const m = {'\u300B': '[[1]]> $0', '\u3001': '[[1]]/$0'}; return m[leftMatches[2]];" ,
options : "rF" ,
priority : 10 ,
description : "\u884C\u9996 \u300B \u8F6C\u5F15\u7528\u6807\u8BB0\u3001\u884C\u9996 \u3001 \u8F6C\u659C\u6760"
},
{
id : "builtin-conv-hw2fw" ,
trigger : "([\u4E00-\u9FA5\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF])([,.:?!;(])" ,
trigger_right : "\\)?" ,
replacement : "const m={',':'\uFF0C','.':'\u3002','?':'\uFF1F','!':'\uFF01',':':'\uFF1A',';':'\uFF1B','(':'\uFF08$0\uFF09'}; return leftMatches[1] + m[leftMatches[2]];" ,
options : "rF" ,
priority : 15 ,
enabled : false ,
description : "CJK\u5B57\u7B26\u540E\u534A\u89D2\u6807\u70B9\u8F6C\u5168\u89D2"
},
{
id : "builtin-fw2hw-double" ,
trigger : "([\u3002\uFF01\uFF1B\uFF0C\uFF1A\uFF1F\u300B\uFF5C\uFF08\u300A])\\1" ,
trigger_right : "[\uFF09\u300B]?" ,
replacement : "const p={'\uFF08':['\uFF09','($0)'],'\u300A':['\u300B','<$0']};\nconst m={'\u3002':'.$0','\uFF01':'!$0','\uFF1B':';$0','\uFF0C':',$0','\uFF1A':':$0','\uFF1F':'?$0','\u300B':'>$0','\uFF5C':'|$0','\uFF08':'($0)','\u300A':'<$0'};\nconst c=leftMatches[1],r=rightMatches[0]||'',e=p[c]; \nreturn e&&e[0]===r?e[1]:m[c];" ,
options : "rF" ,
priority : 3 ,
description : "\u8FDE\u7EED\u8F93\u5165\u4E24\u4E2A\u76F8\u540C\u5168\u89D2\u6807\u70B9\u8F6C\u5BF9\u5E94\u534A\u89D2"
},
{ id : "builtin-del-inline-formula" , trigger : "$" , trigger_right : "$" , replacement : "" , options : "d" , priority : 30 , description : "\u5220\u9664\u884C\u5185\u516C\u5F0F $...$ \u914D\u5BF9" },
{ id : "builtin-del-highlight" , trigger : "==" , trigger_right : "==" , replacement : "" , options : "d" , priority : 30 , description : "\u5220\u9664\u9AD8\u4EAE ==...== \u914D\u5BF9" },
{ id : "builtin-del-block-formula" , trigger : "$$\n" , trigger_right : "\n$$" , replacement : "" , options : "d" , priority : 30 , description : "\u5220\u9664\u5757\u7EA7\u516C\u5F0F $$...$$ \u914D\u5BF9" },
{
id : "builtin-del-codeblock" ,
trigger : "(?<=^|\\n)([ \\t]*)```" ,
trigger_right : "[ \\t]*\\n([ \\t]*)```" ,
replacement : "[[1]]" ,
options : "dr" ,
priority : 30 ,
description : "\u5FEB\u901F\u5220\u9664\u7A7A\u4EE3\u7801\u5757"
},
{
id : "builtin-del-wikilink" ,
trigger : " ?!?\\[\\[[^\\n\\[\\]]*\\]\\]" ,
replacement : "" ,
options : "dr" ,
priority : 30 ,
description : "\u5FEB\u901F\u5220\u9664\u53CC\u94FE\u53CA\u5D4C\u5165\uFF08![[]]\uFF09"
},
{
id : "builtin-sel-wrap-backtick" ,
trigger : "\xB7" ,
replacement : "`${0:${SEL}}`" ,
options : "s" ,
priority : 40 ,
description : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165 \xB7 \u5305\u88F9\u4E3A\u884C\u5185\u4EE3\u7801"
},
{
id : "builtin-sel-wrap-symbols" ,
trigger : `\u3010\xA5\uFFE5` ,
replacement : "const m={'\xA5': ['$', '$'], '\uFFE5': ['$', '$'], '\u3010': ['[', ']']}; \nreturn m[key][0] + '${0:${SEL}}' + m[key][1];" ,
options : "sF" ,
priority : 40 ,
description : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165 \u3010/\xA5/\uFFE5 \u5305\u88F9\u4E3A []/$$"
},
{
id : "builtin-sel-wrap-quotes" ,
trigger : `\u201C\u201D\u2018\u2019` ,
replacement : "const m={'\u201C': ['\u201C','\u201D'], '\u201D': ['\u201C','\u201D'], '\u2018': ['\u2018','\u2019'], '\u2019': ['\u2018','\u2019']}; return m[key][0] + '${0:${SEL}}' + m[key][1];" ,
options : "sF" ,
priority : 40 ,
description : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165\u5168\u89D2\u5F15\u53F7\uFF0C\u914D\u5BF9\u5F15\u53F7\u5305\u88F9"
},
{
id : "builtin-sel-wrap-cjk-brackets" ,
trigger : `\u300A\uFF08` ,
replacement : "const m={'\u300A': ['\u300A','\u300B'], '\uFF08': ['\uFF08','\uFF09']}; return m[key][0] + '${0:${SEL}}' + m[key][1];" ,
options : "sF" ,
priority : 40 ,
description : "\u9009\u4E2D\u6587\u5B57\u540E\u8F93\u5165\u300A\uFF08\uFF0C\u914D\u5BF9\u62EC\u53F7\u5305\u88F9"
},
{ id : "builtin-quote-convert" , trigger : "((?:^|\\n)\\s*>*) ?[>\u300B]" , replacement : "[[1]]> $0" , options : "r" , priority : 50 , description : "\u8F93\u5165 > \u6216 \u300B \u8F6C\u4E3A Markdown \u5F15\u7528\u6807\u8BB0" },
{ id : "builtin-quote-space" , trigger : "((?:^|\\n)\\s*>+)([^ >\u300B]+)" , replacement : "[[1]] [[2]]$0" , options : "r" , priority : 50 , description : "\u5F15\u7528\u6807\u8BB0 > \u540E\u81EA\u52A8\u8865\u7A7A\u683C" }
];
// src/settings/rule_edit_modal.ts
var import_obsidian4 = require ( "obsidian" );
var import_view = require ( "@codemirror/view" );
var import_state2 = require ( "@codemirror/state" );
var import_commands = require ( "@codemirror/commands" );
var JS_KEYWORDS = /* @__PURE__ */ new Set ([
"const" ,
"let" ,
"var" ,
"function" ,
"return" ,
"if" ,
"else" ,
"for" ,
"while" ,
"do" ,
"switch" ,
"case" ,
"break" ,
"continue" ,
"new" ,
"this" ,
"true" ,
"false" ,
"null" ,
"undefined" ,
"typeof" ,
"instanceof" ,
"in" ,
"of" ,
"try" ,
"catch" ,
"finally" ,
"throw" ,
"async" ,
"await"
]);
function tokenizeJS ( text ) {
const tokens = [];
let i = 0 ;
while ( i < text . length ) {
if ( text [ i ] === "/" && text [ i + 1 ] === "/" ) {
const start = i ;
while ( i < text . length && text [ i ] !== "\n" )
i ++ ;
tokens . push ({ from : start , to : i , cls : "et-hl-comment" });
continue ;
}
if ( text [ i ] === "/" && text [ i + 1 ] === "*" ) {
const start = i ;
i += 2 ;
while ( i < text . length - 1 && ! ( text [ i ] === "*" && text [ i + 1 ] === "/" ))
i ++ ;
if ( i < text . length - 1 )
i += 2 ;
else
i = text . length ;
tokens . push ({ from : start , to : i , cls : "et-hl-comment" });
continue ;
}
if ( text [ i ] === '"' || text [ i ] === "'" || text [ i ] === "`" ) {
const quote = text [ i ];
const start = i ;
i ++ ;
while ( i < text . length && text [ i ] !== quote ) {
if ( text [ i ] === "\\" )
i ++ ;
i ++ ;
}
if ( i < text . length )
i ++ ;
tokens . push ({ from : start , to : i , cls : "et-hl-string" });
continue ;
}
if ( /\d/ . test ( text [ i ]) && ( i === 0 || /[^a-zA-Z_$]/ . test ( text [ i - 1 ]))) {
const start = i ;
if ( text [ i ] === "0" && ( text [ i + 1 ] === "x" || text [ i + 1 ] === "X" )) {
i += 2 ;
while ( i < text . length && /[0-9a-fA-F]/ . test ( text [ i ]))
i ++ ;
} else {
while ( i < text . length && /\d/ . test ( text [ i ]))
i ++ ;
if ( i < text . length && text [ i ] === "." ) {
i ++ ;
while ( i < text . length && /\d/ . test ( text [ i ]))
i ++ ;
}
}
tokens . push ({ from : start , to : i , cls : "et-hl-number" });
continue ;
}
if ( /[a-zA-Z_$]/ . test ( text [ i ])) {
const start = i ;
while ( i < text . length && /[a-zA-Z0-9_$]/ . test ( text [ i ]))
i ++ ;
if ( JS_KEYWORDS . has ( text . slice ( start , i ))) {
tokens . push ({ from : start , to : i , cls : "et-hl-keyword" });
}
continue ;
}
i ++ ;
}
return tokens ;
}
var jsHighlightPlugin = import_view . ViewPlugin . fromClass ( class {
constructor ( view ) {
this . decorations = this . buildDecorations ( view );
}
update ( update ) {
if ( update . docChanged || update . viewportChanged ) {
this . decorations = this . buildDecorations ( update . view );
}
}
buildDecorations ( view ) {
const text = view . state . doc . toString ();
const tokens = tokenizeJS ( text );
const ranges = tokens . map (( t ) => import_view . Decoration . mark ({ class : t . cls }). range ( t . from , t . to ));
return import_view . Decoration . set ( ranges , true );
}
}, {
decorations : ( v ) => v . decorations
});
var fnEditorTheme = import_view . EditorView . theme ({
"&" : {
fontSize : "13px" ,
backgroundColor : "var(--background-primary)"
},
".cm-content" : {
fontFamily : "var(--font-monospace)" ,
padding : "8px" ,
minHeight : "120px"
},
"&.cm-focused" : {
outline : "none"
},
".cm-gutters" : { display : "none" },
".cm-activeLine" : { backgroundColor : "transparent" }
});
function createJSEditorView ( container , initialValue , onChange ) {
const state = import_state2 . EditorState . create ({
doc : initialValue ,
extensions : [
jsHighlightPlugin ,
fnEditorTheme ,
import_view . keymap . of ([ import_commands . indentWithTab ]),
import_state2 . EditorState . tabSize . of ( 4 ),
import_view . EditorView . updateListener . of (( update ) => {
if ( update . docChanged ) {
onChange ( update . state . doc . toString ());
}
})
]
});
return new import_view . EditorView ({ state , parent : container });
}
var RuleEditModal = class extends import_obsidian4 . Modal {
constructor ( app , mode , initial , onSubmit ) {
super ( app );
this . ruleType = "input" /* Input */ ;
this . triggerMode = "auto" /* Auto */ ;
this . trigger = "" ;
this . triggerRight = "" ;
this . replacement = "" ;
this . isRegex = false ;
this . regexFlags = "" ;
this . scopeLanguage = "" ;
this . priority = 100 ;
this . description = "" ;
this . enabled = true ;
this . isFunction = false ;
this . ruleScopes = [ "all" /* All */ ];
this . cmEditor = null ;
this . mode = mode ;
this . initial = initial ;
this . onSubmit = onSubmit ;
if ( initial . options !== void 0 || initial . trigger !== void 0 ) {
const opts = RuleEngine . parseOptions ( initial . options );
this . ruleType = opts . type ;
this . triggerMode = opts . triggerMode ;
this . isRegex = opts . isRegex ;
this . isFunction = opts . isFunctionReplacement ;
this . ruleScopes = opts . scope . length > 0 ? [... opts . scope ] : [ "all" /* All */ ];
}
if ( initial . trigger !== void 0 )
this . trigger = RuleEngine . escapeText ( initial . trigger , this . isRegex );
if ( initial . trigger_right !== void 0 )
this . triggerRight = RuleEngine . escapeText ( initial . trigger_right , this . isRegex );
if ( typeof initial . replacement === "string" )
this . replacement = initial . replacement ;
if ( initial . regex_flags !== void 0 )
this . regexFlags = RuleEngine . normalizeRegexFlags ( initial . regex_flags );
if ( initial . priority !== void 0 )
this . priority = initial . priority ;
if ( initial . description !== void 0 )
this . description = initial . description ;
if ( initial . enabled !== void 0 )
this . enabled = initial . enabled ;
if ( initial . scope_language !== void 0 )
this . scopeLanguage = initial . scope_language ;
}
onOpen () {
const { contentEl } = this ;
this . modalEl . addClass ( "et-rule-edit-modal" );
contentEl . addClass ( "et-rule-edit-modal-content" );
const locale7 = getLocale ();
const title = this . mode === "create" ? locale7 . settings . ruleEditModal . addTitle : locale7 . settings . ruleEditModal . editTitle ;
const headerEl = contentEl . createDiv ({ cls : "et-rule-edit-header" });
const titleEl = headerEl . createEl ( "h2" , { text : title , cls : "et-rule-edit-title" });
const pillBar = contentEl . createDiv ({ cls : "et-pill-bar" });
const typeSection = pillBar . createDiv ({ cls : "et-pill-section" });
typeSection . createEl ( "span" , {
cls : "et-pill-group-label" ,
text : locale7 . settings . ruleEditModal . fieldType
});
const typeOptions = typeSection . createDiv ({ cls : "et-pill-options" });
const typePills = [
{ value : "input" /* Input */ , label : locale7 . dropdownOptions . ruleTypeInput },
{ value : "delete" /* Delete */ , label : locale7 . dropdownOptions . ruleTypeDelete },
{ value : "selectKey" /* SelectKey */ , label : locale7 . dropdownOptions . ruleTypeSelectKey }
];
for ( const { value , label } of typePills ) {
const pill = typeOptions . createEl ( "button" , {
cls : `et-pill ${ this . ruleType === value ? " et-pill-active" : "" } ` ,
text : label
});
pill . dataset . pillGroup = "ruleType" ;
pill . dataset . pillValue = value ;
pill . addEventListener ( "click" , () => {
this . ruleType = value ;
this . refreshVisibility ( contentEl );
});
}
const triggerModeSection = pillBar . createDiv ({ cls : "et-pill-section" });
triggerModeSection . dataset . field = "triggerModeSection" ;
const triggerModeLabel = triggerModeSection . createEl ( "span" , {
cls : "et-pill-group-label" ,
text : locale7 . settings . ruleEditModal . fieldTriggerMode
});
triggerModeLabel . dataset . field = "triggerModeLabel" ;
const triggerModeOptions = triggerModeSection . createDiv ({ cls : "et-pill-options" });
const triggerModePills = [
{ value : "auto" /* Auto */ , label : locale7 . dropdownOptions . triggerModeAuto },
{ value : "tab" /* Tab */ , label : locale7 . dropdownOptions . triggerModeTab }
];
for ( const { value , label } of triggerModePills ) {
const pill = triggerModeOptions . createEl ( "button" , {
cls : `et-pill ${ this . triggerMode === value ? " et-pill-active" : "" } ` ,
text : label
});
pill . dataset . pillGroup = "triggerMode" ;
pill . dataset . pillValue = value ;
pill . addEventListener ( "click" , () => {
this . triggerMode = value ;
this . refreshVisibility ( contentEl );
});
}
const matchGroup = contentEl . createDiv ({ cls : "et-modal-group" });
const matchHeader = matchGroup . createDiv ({ cls : "et-modal-group-header" });
matchHeader . createEl ( "span" , { cls : "et-modal-group-title" , text : locale7 . settings . ruleEditModal . groupMatch });
const regexChip = matchHeader . createEl ( "button" , {
cls : `et-pill-chip ${ this . isRegex ? " et-pill-chip-active" : "" } ` ,
text : locale7 . settings . ruleEditModal . fieldIsRegex
});
regexChip . dataset . field = "isRegexChip" ;
regexChip . addEventListener ( "click" , () => {
this . isRegex = ! this . isRegex ;
this . refreshVisibility ( contentEl );
});
const triggerSetting = new import_obsidian4 . Setting ( matchGroup ). setName ( locale7 . settings . ruleEditModal . fieldTrigger ). setDesc ( "" ). addText (( text ) => {
text . setValue ( this . trigger );
text . onChange (( v ) => this . trigger = v );
});
triggerSetting . settingEl . dataset . field = "trigger" ;
const triggerRightSetting = new import_obsidian4 . Setting ( matchGroup ). setName ( locale7 . settings . ruleEditModal . fieldTriggerRight ). addText (( text ) => {
text . setValue ( this . triggerRight );
text . onChange (( v ) => this . triggerRight = v );
});
triggerRightSetting . settingEl . dataset . field = "triggerRight" ;
const regexFlagsSetting = new import_obsidian4 . Setting ( matchGroup ). setName ( locale7 . settings . ruleEditModal . fieldRegexFlags ). setDesc ( locale7 . settings . ruleEditModal . fieldRegexFlagsDesc ). addText (( text ) => {
text . setPlaceholder ( "imu" );
text . setValue ( this . regexFlags );
text . onChange (( v ) => this . regexFlags = RuleEngine . normalizeRegexFlags ( v ));
});
regexFlagsSetting . settingEl . dataset . field = "regexFlags" ;
const replacementGroup = contentEl . createDiv ({ cls : "et-modal-group" });
const replHeader = replacementGroup . createDiv ({ cls : "et-modal-group-header" });
replHeader . createEl ( "span" , { cls : "et-modal-group-title" , text : locale7 . settings . ruleEditModal . groupReplacement });
const fnChip = replHeader . createEl ( "button" , {
cls : `et-pill-chip ${ this . isFunction ? " et-pill-chip-active" : "" } ` ,
text : locale7 . settings . ruleEditModal . fieldIsFunction
});
fnChip . dataset . field = "isFunctionChip" ;
fnChip . addEventListener ( "click" , () => {
this . isFunction = ! this . isFunction ;
this . refreshVisibility ( contentEl );
});
const replacementSetting = new import_obsidian4 . Setting ( replacementGroup );
replacementSetting . settingEl . addClass ( "et-replacement-setting" );
replacementSetting . settingEl . dataset . field = "replacementTextarea" ;
const replacementArea = new import_obsidian4 . TextAreaComponent ( replacementSetting . controlEl );
replacementArea . inputEl . addClass ( "et-replacement-textarea" );
replacementArea . inputEl . setAttribute ( "aria-label" , locale7 . settings . ruleEditModal . fieldReplacement );
replacementArea . setValue ( this . replacement );
replacementArea . onChange (( v ) => this . replacement = v );
const replacementHint = replacementGroup . createEl ( "div" , {
cls : "setting-item-description et-replacement-hint" ,
text : ""
});
replacementHint . dataset . field = "replacementHint" ;
const editorWrapper = replacementGroup . createDiv ();
editorWrapper . dataset . field = "fnEditor" ;
const editorContainer = editorWrapper . createDiv ({ cls : "et-fn-editor-container" });
editorContainer . setAttribute ( "aria-label" , locale7 . settings . ruleEditModal . fieldReplacement );
this . cmEditor = createJSEditorView ( editorContainer , this . replacement , ( value ) => {
this . replacement = value ;
});
const fnHint = replacementGroup . createEl ( "div" , {
cls : "setting-item-description et-fn-hint" ,
text : ""
});
fnHint . dataset . field = "fnHint" ;
const otherGroup = contentEl . createDiv ({ cls : "et-modal-group" });
const otherHeader = otherGroup . createDiv ({ cls : "et-modal-group-header" });
otherHeader . createEl ( "span" , { cls : "et-modal-group-title" , text : locale7 . settings . ruleEditModal . groupOther });
const scopeSetting = new import_obsidian4 . Setting ( otherGroup ). setName ( locale7 . settings . ruleEditModal . fieldScope );
scopeSetting . settingEl . dataset . field = "scopeSetting" ;
scopeSetting . settingEl . addClass ( "et-scope-setting" );
const scopeControls = scopeSetting . controlEl . createDiv ({ cls : "et-scope-options" });
const scopeOptions = [
{ value : "all" /* All */ , label : locale7 . dropdownOptions . scopeAll },
{ value : "text" /* Text */ , label : locale7 . dropdownOptions . scopeText },
{ value : "formula" /* Formula */ , label : locale7 . dropdownOptions . scopeFormula },
{ value : "code" /* Code */ , label : locale7 . dropdownOptions . scopeCode }
];
for ( const { value , label } of scopeOptions ) {
const chip = scopeControls . createEl ( "button" , {
cls : `et-pill-chip ${ this . ruleScopes . includes ( value ) ? " et-pill-chip-active" : "" } ` ,
text : label ,
attr : { type : "button" }
});
chip . dataset . scopeValue = value ;
chip . addEventListener ( "click" , () => {
this . toggleRuleScope ( value );
this . refreshVisibility ( contentEl );
});
}
const scopeLangSetting = new import_obsidian4 . Setting ( otherGroup ). setName ( locale7 . settings . ruleEditModal . fieldScopeLanguage ). addText (( text ) => {
text . setPlaceholder ( "e.g. python, javascript" );
text . setValue ( this . scopeLanguage );
text . onChange (( v ) => this . scopeLanguage = v . trim (). toLowerCase ());
});
scopeLangSetting . settingEl . dataset . field = "scopeLanguage" ;
new import_obsidian4 . Setting ( otherGroup ). setName ( locale7 . settings . ruleEditModal . fieldPriority ). setDesc ( locale7 . settings . ruleEditModal . fieldPriorityDesc ). addText (( text ) => {
text . setValue ( String ( this . priority ));
text . inputEl . type = "number" ;
text . onChange (( v ) => {
const n = parseInt ( v );
if ( ! isNaN ( n ))
this . priority = n ;
});
});
new import_obsidian4 . Setting ( otherGroup ). setName ( locale7 . settings . ruleEditModal . fieldDescription ). addText (( text ) => {
text . setValue ( this . description );
text . onChange (( v ) => this . description = v );
});
const footerEl = contentEl . createDiv ({ cls : "et-rule-edit-footer" });
const saveButton = footerEl . createEl ( "button" , {
cls : "mod-cta et-rule-edit-save" ,
text : locale7 . settings . ruleEditModal . buttonSave
});
saveButton . addEventListener ( "click" , () => {
const rule = this . buildSimpleRule ();
const regexError = RuleEngine . validateRegex ( rule );
if ( regexError ) {
new import_obsidian4 . Notice ( `[EasyTyping] ${ locale7 . settings . ruleEditModal . invalidRegex } : ${ regexError } ` );
return ;
}
this . close ();
this . onSubmit ( rule );
});
this . refreshVisibility ( contentEl );
this . setInitialFocus ( contentEl , titleEl );
}
setInitialFocus ( contentEl , titleEl ) {
window . requestAnimationFrame (() => {
if ( this . mode === "create" ) {
const triggerInput = contentEl . querySelector ( '[data-field="trigger"] input' );
if ( ! triggerInput )
return ;
triggerInput . focus ();
triggerInput . setSelectionRange ( triggerInput . value . length , triggerInput . value . length );
return ;
}
titleEl . tabIndex = - 1 ;
titleEl . focus ();
});
}
refreshVisibility ( contentEl ) {
const locale7 = getLocale ();
const triggerRightEl = contentEl . querySelector ( '[data-field="triggerRight"]' );
if ( triggerRightEl ) {
triggerRightEl . classList . toggle ( "et-hidden" , this . ruleType === "selectKey" /* SelectKey */ );
}
const regexFlagsEl = contentEl . querySelector ( '[data-field="regexFlags"]' );
if ( regexFlagsEl ) {
regexFlagsEl . classList . toggle ( "et-hidden" , this . ruleType === "selectKey" /* SelectKey */ || ! this . isRegex );
}
const triggerEl = contentEl . querySelector ( '[data-field="trigger"]' );
if ( triggerEl ) {
const nameEl = triggerEl . querySelector ( ".setting-item-name" );
if ( nameEl ) {
nameEl . textContent = this . ruleType === "selectKey" /* SelectKey */ ? locale7 . settings . ruleEditModal . fieldTriggerSelectKey : locale7 . settings . ruleEditModal . fieldTrigger ;
}
const descEl = triggerEl . querySelector ( ".setting-item-description" );
if ( descEl ) {
descEl . textContent = this . isRegex ? "" : locale7 . settings . ruleEditModal . hintTriggerEscape ;
}
}
contentEl . querySelectorAll ( '[data-pill-group="ruleType"]' ). forEach (( el ) => {
el . classList . toggle ( "et-pill-active" , el . dataset . pillValue === this . ruleType );
});
const triggerModeSection = contentEl . querySelector ( '[data-field="triggerModeSection"]' );
if ( triggerModeSection )
triggerModeSection . classList . toggle ( "et-hidden" , this . ruleType !== "input" /* Input */ );
contentEl . querySelectorAll ( '[data-pill-group="triggerMode"]' ). forEach (( el ) => {
const htmlEl = el ;
htmlEl . classList . toggle ( "et-hidden" , this . ruleType !== "input" /* Input */ );
htmlEl . classList . toggle ( "et-pill-active" , htmlEl . dataset . pillValue === this . triggerMode );
});
const regexChip = contentEl . querySelector ( '[data-field="isRegexChip"]' );
if ( regexChip ) {
regexChip . classList . toggle ( "et-pill-chip-active" , this . isRegex );
regexChip . classList . toggle ( "et-hidden" , this . ruleType === "selectKey" /* SelectKey */ );
}
const fnChip = contentEl . querySelector ( '[data-field="isFunctionChip"]' );
if ( fnChip )
fnChip . classList . toggle ( "et-pill-chip-active" , this . isFunction );
const replacementHintEl = contentEl . querySelector ( '[data-field="replacementHint"]' );
if ( replacementHintEl ) {
const parts = [];
if ( this . ruleType === "selectKey" /* SelectKey */ ) {
parts . push ( locale7 . settings . ruleEditModal . fieldReplacementDescSelectKey );
} else if ( this . isRegex ) {
parts . push ( locale7 . settings . ruleEditModal . fieldReplacementDescInputDelete );
}
parts . push ( locale7 . settings . ruleEditModal . hintTabstop );
replacementHintEl . textContent = parts . join ( "\n" );
replacementHintEl . classList . toggle ( "et-hidden" , this . isFunction );
}
const fnHint = contentEl . querySelector ( '[data-field="fnHint"]' );
if ( fnHint ) {
fnHint . classList . toggle ( "et-hidden" , ! this . isFunction );
const parts = [];
if ( this . ruleType === "selectKey" /* SelectKey */ ) {
parts . push ( locale7 . settings . ruleEditModal . functionHintSelectKey );
} else {
parts . push ( locale7 . settings . ruleEditModal . functionHintInputDelete );
if ( this . isRegex ) {
parts . push ( locale7 . settings . ruleEditModal . fieldReplacementDescInputDelete );
}
}
parts . push ( locale7 . settings . ruleEditModal . hintTabstop );
fnHint . textContent = parts . join ( "\n" );
}
const textareaSetting = contentEl . querySelector ( '[data-field="replacementTextarea"]' );
const editorSetting = contentEl . querySelector ( '[data-field="fnEditor"]' );
if ( textareaSetting && editorSetting ) {
textareaSetting . classList . toggle ( "et-hidden" , this . isFunction );
editorSetting . classList . toggle ( "et-hidden" , ! this . isFunction );
if ( this . isFunction ) {
if ( this . cmEditor ) {
const current = this . cmEditor . state . doc . toString ();
if ( current !== this . replacement ) {
this . cmEditor . dispatch ({
changes : { from : 0 , to : current . length , insert : this . replacement }
});
}
}
} else {
const textarea = textareaSetting . querySelector ( "textarea" );
if ( textarea && textarea . value !== this . replacement ) {
textarea . value = this . replacement ;
}
}
}
const scopeLangEl = contentEl . querySelector ( '[data-field="scopeLanguage"]' );
if ( scopeLangEl ) {
scopeLangEl . classList . toggle ( "et-hidden" , ! this . ruleScopes . includes ( "code" /* Code */ ));
}
contentEl . querySelectorAll ( "[data-scope-value]" ). forEach (( el ) => {
const htmlEl = el ;
htmlEl . classList . toggle ( "et-pill-chip-active" , this . ruleScopes . includes ( htmlEl . dataset . scopeValue ));
});
}
buildSimpleRule () {
let options = "" ;
if ( this . ruleType === "delete" /* Delete */ )
options += "d" ;
else if ( this . ruleType === "selectKey" /* SelectKey */ )
options += "s" ;
if ( this . ruleType === "input" /* Input */ && this . triggerMode === "tab" /* Tab */ )
options += "T" ;
if ( this . isRegex )
options += "r" ;
if ( this . isFunction )
options += "F" ;
const normalizedScopes = this . getNormalizedRuleScopes ();
if ( ! normalizedScopes . includes ( "all" /* All */ )) {
if ( normalizedScopes . includes ( "text" /* Text */ ))
options += "t" ;
if ( normalizedScopes . includes ( "formula" /* Formula */ ))
options += "f" ;
if ( normalizedScopes . includes ( "code" /* Code */ ))
options += "c" ;
}
return {
trigger : this . isRegex ? this . trigger : RuleEngine . unescapeText ( this . trigger ),
trigger_right : ( this . isRegex ? this . triggerRight : RuleEngine . unescapeText ( this . triggerRight )) || void 0 ,
replacement : this . replacement ,
options : options || void 0 ,
priority : this . priority ,
description : this . description || void 0 ,
enabled : this . enabled ,
scope_language : normalizedScopes . includes ( "code" /* Code */ ) && this . scopeLanguage ? this . scopeLanguage : void 0 ,
regex_flags : this . isRegex ? RuleEngine . normalizeRegexFlags ( this . regexFlags ) || void 0 : void 0
};
}
toggleRuleScope ( scope ) {
if ( scope === "all" /* All */ ) {
this . ruleScopes = [ "all" /* All */ ];
return ;
}
const nextScopes = this . ruleScopes . filter (( item ) => item !== "all" /* All */ );
const hasScope = nextScopes . includes ( scope );
this . ruleScopes = hasScope ? nextScopes . filter (( item ) => item !== scope ) : [... nextScopes , scope ];
if ( this . ruleScopes . length === 0 ) {
this . ruleScopes = [ "all" /* All */ ];
}
}
getNormalizedRuleScopes () {
return this . ruleScopes . length > 0 ? this . ruleScopes : [ "all" /* All */ ];
}
onClose () {
if ( this . cmEditor ) {
this . cmEditor . destroy ();
this . cmEditor = null ;
}
this . contentEl . empty ();
}
};
// src/settings/easy_typing_settings_tab.ts
var import_sprintf_js = __toESM ( require_sprintf ());
var DEFAULT_PATH_VALUE = "" ;
var FolderSuggest = class extends import_obsidian5 . AbstractInputSuggest {
constructor ( app , inputEl , defaultLabel , onSelect ) {
super ( app , inputEl );
this . defaultLabel = defaultLabel ;
this . onSelectCb = onSelect ;
}
getSuggestions ( query ) {
const lowerQuery = query . toLowerCase ();
const folders = this . app . vault . getAllFolders (). map (( f ) => f . path ). filter (( p ) => p . toLowerCase (). includes ( lowerQuery ));
return [ DEFAULT_PATH_VALUE , ... folders ];
}
renderSuggestion ( path , el ) {
el . setText ( path || this . defaultLabel );
}
selectSuggestion ( path , _evt ) {
this . setValue ( path );
this . close ();
this . onSelectCb ( path );
}
};
var EasyTypingSettingTab = class extends import_obsidian5 . PluginSettingTab {
2026-01-05 13:03:55 +08:00
constructor ( app , plugin ) {
super ( app , plugin );
2026-08-21 15:44:03 +08:00
this . activeTab = "edit-enhance" ;
this . dragSourceIndex = null ;
2026-01-05 13:03:55 +08:00
this . plugin = plugin ;
}
display () {
const { containerEl } = this ;
2026-08-21 15:44:03 +08:00
const locale7 = getLocale ();
2026-01-05 13:03:55 +08:00
containerEl . empty ();
2026-08-21 15:44:03 +08:00
const shellEl = containerEl . createDiv ({ cls : "et-settings-shell" });
const heroEl = shellEl . createDiv ({ cls : "et-settings-hero" });
const heroMainEl = heroEl . createDiv ({ cls : "et-settings-hero-main" });
heroMainEl . createEl ( "h1" , { text : locale7 . headers . main });
const heroMetaEl = heroMainEl . createDiv ({ cls : "et-settings-hero-meta" });
heroMetaEl . createSpan ({ text : locale7 . headers . githubDetail , cls : "et-settings-hero-label" });
heroMetaEl . createEl ( "a" , {
2026-01-05 13:03:55 +08:00
text : "easy-typing-obsidian" ,
2026-08-21 15:44:03 +08:00
href : "https://github.com/Yaozhuwa/easy-typing-obsidian" ,
cls : "et-settings-hero-link"
2026-01-05 13:03:55 +08:00
});
2026-08-21 15:44:03 +08:00
const navEl = shellEl . createEl ( "nav" , {
cls : "et-settings-nav" ,
attr : { role : "tablist" , "aria-orientation" : "horizontal" }
});
const contentEl = shellEl . createEl ( "div" , { cls : "et-settings-content" });
const tabs = [
{ id : "edit-enhance" , label : locale7 . headers . tabs . editEnhance },
{ id : "auto-format" , label : locale7 . headers . tabs . autoFormat },
{ id : "builtin-rules" , label : locale7 . headers . tabs . builtinRules },
{ id : "user-rules" , label : locale7 . headers . tabs . userRules },
{ id : "other" , label : locale7 . headers . tabs . other }
];
const tabPanels = {};
const tabButtons = [];
const activateTab = ( tabId , focusButton = false ) => {
this . activeTab = tabId ;
tabs . forEach (( tab , index ) => {
const button = tabButtons [ index ];
const panel = tabPanels [ tab . id ];
const isActive = tab . id === tabId ;
button . toggleClass ( "et-settings-tab-active" , isActive );
button . setAttribute ( "aria-selected" , isActive ? "true" : "false" );
button . tabIndex = isActive ? 0 : - 1 ;
panel . toggleClass ( "et-settings-tab-hidden" , ! isActive );
panel . setAttribute ( "aria-hidden" , isActive ? "false" : "true" );
if ( focusButton && isActive ) {
button . focus ();
}
});
};
tabs . forEach (( tab ) => {
const isActive = tab . id === this . activeTab ;
const buttonId = `easy-typing-settings-tab- ${ tab . id } ` ;
const panelId = `easy-typing-settings-panel- ${ tab . id } ` ;
const btn = navEl . createEl ( "button" , {
cls : `et-settings-tab-btn ${ isActive ? "et-settings-tab-active" : "" } ` ,
attr : {
id : buttonId ,
role : "tab" ,
type : "button" ,
"aria-selected" : isActive ? "true" : "false" ,
"aria-controls" : panelId
}
});
btn . tabIndex = isActive ? 0 : - 1 ;
btn . setText ( tab . label );
tabButtons . push ( btn );
const panel = contentEl . createEl ( "section" , {
cls : `et-settings-tab-panel ${ isActive ? "" : "et-settings-tab-hidden" } ` ,
attr : {
id : panelId ,
role : "tabpanel" ,
"data-tab-id" : tab . id ,
"aria-labelledby" : buttonId ,
"aria-hidden" : isActive ? "false" : "true"
}
});
tabPanels [ tab . id ] = panel ;
btn . addEventListener ( "click" , () => {
activateTab ( tab . id );
});
btn . addEventListener ( "keydown" , ( evt ) => {
const currentIndex = tabs . findIndex (( item ) => item . id === tab . id );
if ( currentIndex === - 1 )
return ;
let targetIndex = null ;
switch ( evt . key ) {
case "ArrowRight" :
case "ArrowDown" :
targetIndex = ( currentIndex + 1 ) % tabs . length ;
break ;
case "ArrowLeft" :
case "ArrowUp" :
targetIndex = ( currentIndex - 1 + tabs . length ) % tabs . length ;
break ;
case "Home" :
targetIndex = 0 ;
break ;
case "End" :
targetIndex = tabs . length - 1 ;
break ;
}
if ( targetIndex !== null ) {
evt . preventDefault ();
activateTab ( tabs [ targetIndex ]. id , true );
}
2026-01-05 13:03:55 +08:00
});
});
2026-08-21 15:44:03 +08:00
this . buildEditEnhanceTab ( tabPanels [ "edit-enhance" ]);
this . buildAutoFormatTab ( tabPanels [ "auto-format" ]);
this . buildBuiltinRulesSection ( tabPanels [ "builtin-rules" ]);
this . buildUserRulesSection ( tabPanels [ "user-rules" ]);
this . buildOtherTab ( tabPanels [ "other" ]);
}
createSection ( container , title , description , actionsBuilder , extraCls = "" ) {
const sectionEl = container . createDiv ({ cls : `et-settings-section ${ extraCls } ` . trim () });
if ( title || description || actionsBuilder ) {
const headerEl = sectionEl . createDiv ({ cls : "et-settings-section-header" });
const headingEl = headerEl . createDiv ({ cls : "et-settings-section-heading" });
if ( title ) {
headingEl . createEl ( "h3" , { text : title });
}
if ( description ) {
headingEl . createDiv ({ text : description , cls : "et-settings-section-desc setting-item-description" });
}
if ( actionsBuilder ) {
const actionsEl = headerEl . createDiv ({ cls : "et-settings-section-actions" });
actionsBuilder ( actionsEl );
}
}
const bodyEl = sectionEl . createDiv ({ cls : "et-settings-section-body" });
return { sectionEl , bodyEl };
}
setInteractiveDisabled ( element , disabled ) {
element . toggleClass ( "et-settings-disabled" , disabled );
element . setAttribute ( "aria-disabled" , disabled ? "true" : "false" );
element . querySelectorAll ( "button, input, textarea, select" ). forEach (( node ) => {
node . disabled = disabled ;
2026-01-05 13:03:55 +08:00
});
2026-08-21 15:44:03 +08:00
}
buildEditEnhanceTab ( el ) {
const locale7 = getLocale ();
const section = this . createSection ( el , locale7 . headers . enhancedEditing );
new import_obsidian5 . Setting ( section . bodyEl ). setName ( locale7 . settings . codeblockEdit . name ). setDesc ( locale7 . settings . codeblockEdit . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . BetterCodeEdit ). onChange ( async ( value ) => {
this . plugin . settings . BetterCodeEdit = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( section . bodyEl ). setName ( locale7 . settings . backspaceEdit . name ). setDesc ( locale7 . settings . backspaceEdit . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . BetterBackspace ). onChange ( async ( value ) => {
this . plugin . settings . BetterBackspace = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( section . bodyEl ). setName ( locale7 . settings . tabOut . name ). setDesc ( locale7 . settings . tabOut . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . Tabout ). onChange ( async ( value ) => {
this . plugin . settings . Tabout = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( section . bodyEl ). setName ( locale7 . settings . enhanceModA . name ). setDesc ( locale7 . settings . enhanceModA . desc ). addToggle (( toggle ) => {
toggle . setValue ( this . plugin . settings . EnhanceModA ). onChange ( async ( value ) => {
this . plugin . settings . EnhanceModA = value ;
await this . plugin . saveSettings ();
});
});
new import_obsidian5 . Setting ( section . bodyEl ). setName ( locale7 . settings . smartPaste . name ). setDesc ( locale7 . settings . smartPaste . desc ). addToggle (( toggle ) => {
toggle . setValue ( this . plugin . settings . SmartPaste ). onChange ( async ( value ) => {
this . plugin . settings . SmartPaste = value ;
await this . plugin . saveSettings ();
});
});
}
buildAutoFormatTab ( el ) {
const locale7 = getLocale ();
const overviewSection = this . createSection ( el , locale7 . headers . autoformatSetting );
new import_obsidian5 . Setting ( overviewSection . bodyEl ). setName ( locale7 . settings . autoFormatting . name ). setDesc ( locale7 . settings . autoFormatting . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . AutoFormat ). onChange ( async ( value ) => {
this . plugin . settings . AutoFormat = value ;
await this . plugin . saveSettings ();
2026-08-21 15:44:03 +08:00
syncAutoFormatState ( value );
2026-01-05 13:03:55 +08:00
});
});
2026-08-21 15:44:03 +08:00
const pasteSetting = new import_obsidian5 . Setting ( overviewSection . bodyEl ). setName ( locale7 . settings . autoFormatPaste . name ). setDesc ( locale7 . settings . autoFormatPaste . desc ). addToggle (( toggle ) => {
toggle . setValue ( this . plugin . settings . AutoFormatPaste ). onChange ( async ( value ) => {
this . plugin . settings . AutoFormatPaste = value ;
2026-01-05 13:03:55 +08:00
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
const autoCapitalSetting = new import_obsidian5 . Setting ( overviewSection . bodyEl ). setName ( locale7 . settings . capitalizeFirstLetter . name ). setDesc ( locale7 . settings . capitalizeFirstLetter . desc ). addToggle (( toggle ) => {
toggle . setTooltip ( locale7 . toolTip . switch );
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . AutoCapital ). onChange ( async ( value ) => {
this . plugin . settings . AutoCapital = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
const languageSection = this . createSection ( el , locale7 . headers . languagePairSection , locale7 . settings . languagePairSpacing . desc );
const scriptListContainer = languageSection . bodyEl . createDiv ({ cls : "et-custom-scripts" });
const capsuleContainer = languageSection . bodyEl . createDiv ({ cls : "et-lang-pair-capsules" });
const renderCapsules = () => {
capsuleContainer . empty ();
for ( let idx = 0 ; idx < this . plugin . settings . languagePairs . length ; idx ++ ) {
const pair = this . plugin . settings . languagePairs [ idx ];
const capsule = capsuleContainer . createSpan ({ cls : "et-lang-pair-capsule" });
const labelA = locale7 . scriptCategoryLabels [ pair . a ] || pair . a ;
const labelB = locale7 . scriptCategoryLabels [ pair . b ] || pair . b ;
capsule . createSpan ({ text : ` ${ labelA } \u2194 ${ labelB } ` });
const removeBtn = capsule . createEl ( "button" , {
cls : "et-capsule-remove" ,
text : "\xD7" ,
attr : {
type : "button" ,
"aria-label" : locale7 . toolTip . removeRule
}
});
removeBtn . addEventListener ( "click" , async () => {
this . plugin . settings . languagePairs . splice ( idx , 1 );
await this . plugin . saveSettings ();
renderCapsules ();
});
}
};
const renderScripts = () => {
scriptListContainer . empty ();
for ( let i = 0 ; i < this . plugin . settings . customScriptCategories . length ; i ++ ) {
const cat = this . plugin . settings . customScriptCategories [ i ];
const item = new import_obsidian5 . Setting ( scriptListContainer );
item . setName ( ` ${ cat . name } [ ${ cat . pattern } ]` );
item . addExtraButton (( btn ) => {
btn . setIcon ( "trash" ). setTooltip ( locale7 . toolTip . removeRule ). onClick ( async () => {
this . plugin . settings . languagePairs = this . plugin . settings . languagePairs . filter (( p ) => p . a !== cat . name && p . b !== cat . name );
this . plugin . settings . customScriptCategories . splice ( i , 1 );
await this . plugin . saveSettings ();
renderScripts ();
renderCapsules ();
});
});
}
};
renderScripts ();
renderCapsules ();
const addScriptRow = new import_obsidian5 . Setting ( languageSection . bodyEl );
addScriptRow . settingEl . addClass ( "et-inline-form-setting" );
let newScriptName = "" ;
let newScriptPattern = "" ;
addScriptRow . setName ( locale7 . headers . customScriptSection ). addText (( text ) => {
text . setPlaceholder ( locale7 . settings . customScriptCategories . namePlaceholder ). onChange (( v ) => {
newScriptName = v ;
2026-01-05 13:03:55 +08:00
});
2026-08-21 15:44:03 +08:00
}). addText (( text ) => {
text . setPlaceholder ( locale7 . settings . customScriptCategories . patternPlaceholder ). onChange (( v ) => {
newScriptPattern = v ;
});
}). addButton (( btn ) => {
btn . setButtonText ( "+" ). onClick ( async () => {
if ( ! newScriptName . trim () || ! newScriptPattern . trim ())
return ;
try {
new RegExp ( `[ ${ newScriptPattern } ]` );
} catch ( e ) {
return ;
}
this . plugin . settings . customScriptCategories . push ({
name : newScriptName . trim (),
pattern : newScriptPattern . trim ()
});
2026-01-05 13:03:55 +08:00
await this . plugin . saveSettings ();
2026-08-21 15:44:03 +08:00
renderScripts ();
this . display ();
2026-01-05 13:03:55 +08:00
});
});
2026-08-21 15:44:03 +08:00
const addRow = languageSection . bodyEl . createDiv ({ cls : "et-pair-selector-row" });
const allCategories = this . getAllScriptCategories ();
let selectedA = allCategories [ 0 ] || "" ;
let selectedB = allCategories [ 1 ] || "" ;
const selectorSetting = new import_obsidian5 . Setting ( addRow );
selectorSetting . settingEl . addClass ( "et-inline-form-setting" );
selectorSetting . setName ( locale7 . headers . addLanguagePair ). addDropdown (( dd ) => {
for ( const cat of allCategories ) {
dd . addOption ( cat , locale7 . scriptCategoryLabels [ cat ] || cat );
}
dd . setValue ( selectedA );
dd . onChange (( v ) => {
selectedA = v ;
});
}). addDropdown (( dd ) => {
for ( const cat of allCategories ) {
dd . addOption ( cat , locale7 . scriptCategoryLabels [ cat ] || cat );
}
dd . setValue ( selectedB );
dd . onChange (( v ) => {
selectedB = v ;
});
}). addButton (( btn ) => {
btn . setButtonText ( "+" ). onClick ( async () => {
if ( selectedA === selectedB )
return ;
const exists = this . plugin . settings . languagePairs . some (( p ) => p . a === selectedA && p . b === selectedB || p . a === selectedB && p . b === selectedA );
if ( exists )
return ;
this . plugin . settings . languagePairs . push ({ a : selectedA , b : selectedB });
await this . plugin . saveSettings ();
renderCapsules ();
});
});
const detailSection = this . createSection ( el , locale7 . headers . detailedSetting );
const introDiv = detailSection . bodyEl . createDiv ({ cls : "et-settings-note et-space-strategy-intro setting-item-description" });
introDiv . innerText = locale7 . headers . spaceStrategyIntro || "\u7A7A\u683C\u7B56\u7565\u8BF4\u660E\uFF1A\n\u65E0\u8981\u6C42\uFF1A\u5BF9\u76F8\u5173\u533A\u5757\u4E0E\u5DE6\u53F3\u6587\u672C\u6CA1\u6709\u7A7A\u683C\u8981\u6C42\u3002\n\u8F6F\u7A7A\u683C\uFF1A\u53EA\u8981\u6C42\u6709\u8F6F\u7A7A\u683C\u3002\n\u4E25\u683C\u7A7A\u683C\uFF1A\u4E25\u683C\u6DFB\u52A0\u771F\u5B9E\u7A7A\u683C\u3002" ;
new import_obsidian5 . Setting ( detailSection . bodyEl ). setName ( locale7 . settings . spaceStrategyInlineCode . name ). setDesc ( locale7 . settings . spaceStrategyInlineCode . desc ). addDropdown (( dropdown ) => {
dropdown . addOption ( String ( 0 /* none */ ), locale7 . dropdownOptions . noRequire );
dropdown . addOption ( String ( 1 /* soft */ ), locale7 . dropdownOptions . softSpace );
dropdown . addOption ( String ( 2 /* strict */ ), locale7 . dropdownOptions . strictSpace );
2026-01-05 13:03:55 +08:00
dropdown . setValue ( String ( this . plugin . settings . InlineCodeSpaceMode ));
dropdown . onChange ( async ( v ) => {
this . plugin . settings . InlineCodeSpaceMode = string2SpaceState ( v );
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( detailSection . bodyEl ). setName ( locale7 . settings . spaceStrategyInlineFormula . name ). setDesc ( locale7 . settings . spaceStrategyInlineFormula . desc ). addDropdown (( dropdown ) => {
dropdown . addOption ( String ( 0 /* none */ ), locale7 . dropdownOptions . noRequire );
dropdown . addOption ( String ( 1 /* soft */ ), locale7 . dropdownOptions . softSpace );
dropdown . addOption ( String ( 2 /* strict */ ), locale7 . dropdownOptions . strictSpace );
2026-01-05 13:03:55 +08:00
dropdown . setValue ( String ( this . plugin . settings . InlineFormulaSpaceMode ));
dropdown . onChange ( async ( v ) => {
this . plugin . settings . InlineFormulaSpaceMode = string2SpaceState ( v );
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( detailSection . bodyEl ). setName ( locale7 . settings . spaceStrategyLinkText . name ). setDesc ( locale7 . settings . spaceStrategyLinkText . desc ). addDropdown (( dropdown ) => {
dropdown . addOption ( "dummy" , locale7 . dropdownOptions . dummy );
dropdown . addOption ( "smart" , locale7 . dropdownOptions . smart );
2026-01-05 13:03:55 +08:00
dropdown . setValue ( this . plugin . settings . InlineLinkSmartSpace ? "smart" : "dummy" );
dropdown . onChange ( async ( v ) => {
this . plugin . settings . InlineLinkSmartSpace = v == "smart" ? true : false ;
await this . plugin . saveSettings ();
});
}). addDropdown (( dropdown ) => {
2026-08-21 15:44:03 +08:00
dropdown . addOption ( String ( 0 /* none */ ), locale7 . dropdownOptions . noRequire );
dropdown . addOption ( String ( 1 /* soft */ ), locale7 . dropdownOptions . softSpace );
dropdown . addOption ( String ( 2 /* strict */ ), locale7 . dropdownOptions . strictSpace );
2026-01-05 13:03:55 +08:00
dropdown . setValue ( String ( this . plugin . settings . InlineLinkSpaceMode ));
dropdown . onChange ( async ( v ) => {
this . plugin . settings . InlineLinkSpaceMode = string2SpaceState ( v );
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( detailSection . bodyEl ). setName ( locale7 . settings . softSpaceSymbols . leftName ). setDesc ( locale7 . settings . softSpaceSymbols . leftDesc ). addText (( text ) => {
text . setValue ( this . plugin . settings . SoftSpaceLeftSymbols ). onChange ( async ( value ) => {
this . plugin . settings . SoftSpaceLeftSymbols = value ;
2026-01-05 13:03:55 +08:00
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( detailSection . bodyEl ). setName ( locale7 . settings . softSpaceSymbols . rightName ). setDesc ( locale7 . settings . softSpaceSymbols . rightDesc ). addText (( text ) => {
text . setValue ( this . plugin . settings . SoftSpaceRightSymbols ). onChange ( async ( value ) => {
this . plugin . settings . SoftSpaceRightSymbols = value ;
await this . plugin . saveSettings ();
});
2026-01-05 13:03:55 +08:00
});
2026-08-21 15:44:03 +08:00
const prefixSection = this . createSection ( el , locale7 . headers . prefixDictSection , locale7 . settings . prefixDictionary . desc );
const prefixSetting = new import_obsidian5 . Setting ( prefixSection . bodyEl );
prefixSetting . settingEl . addClass ( "et-setting-full-width" );
const prefixArea = new import_obsidian5 . TextAreaComponent ( prefixSetting . controlEl );
prefixArea . inputEl . addClass ( "et-settings-textarea" , "et-settings-textarea-compact" );
prefixArea . setValue ( this . plugin . settings . PrefixDictionary ). onChange ( async ( value ) => {
this . plugin . settings . PrefixDictionary = value ;
this . plugin . saveSettings ();
2026-01-05 13:03:55 +08:00
});
2026-08-21 15:44:03 +08:00
const regexSection = this . createSection ( el , locale7 . headers . customRegexpBlock );
const regexInfoDiv = regexSection . bodyEl . createDiv ({ cls : "setting-item-description et-settings-section-desc" });
regexInfoDiv . appendChild ( createFragment (( frag ) => {
frag . appendText ( locale7 . headers . aboutRegexp . header );
frag . createEl ( "a" , { text : locale7 . headers . aboutRegexp . text , href : "https://javascript.ruanyifeng.com/stdlib/regexp.html#" });
}));
const regSwitchSetting = new import_obsidian5 . Setting ( regexSection . bodyEl ). setName ( locale7 . settings . userDefinedRegexpSwitch . name ). setDesc ( locale7 . settings . userDefinedRegexpSwitch . desc ). addToggle (( toggle ) => {
toggle . setValue ( this . plugin . settings . UserDefinedRegSwitch ). onChange ( async ( value ) => {
this . plugin . settings . UserDefinedRegSwitch = value ;
await this . plugin . saveSettings ();
syncRegexContentState ();
});
2026-01-05 13:03:55 +08:00
});
2026-08-21 15:44:03 +08:00
const regContentAreaSetting = new import_obsidian5 . Setting ( regexSection . bodyEl );
regContentAreaSetting . settingEl . addClass ( "et-setting-full-width" );
regContentAreaSetting . setName ( locale7 . settings . userDefinedRegexp . name ). setDesc ( locale7 . settings . userDefinedRegexp . desc );
const regContentArea = new import_obsidian5 . TextAreaComponent ( regContentAreaSetting . controlEl );
regContentArea . inputEl . addClass ( "et-settings-textarea" , "et-settings-textarea-tall" );
2026-01-05 13:03:55 +08:00
regContentArea . setValue ( this . plugin . settings . UserDefinedRegExp ). onChange ( async ( value ) => {
this . plugin . settings . UserDefinedRegExp = value ;
this . plugin . saveSettings ();
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( regexSection . bodyEl ). setName ( locale7 . settings . userRulesRespectUserDefinedRegexBlocks . name ). setDesc ( locale7 . settings . userRulesRespectUserDefinedRegexBlocks . desc ). addToggle (( toggle ) => {
toggle . setValue ( this . plugin . settings . UserRulesRespectUserDefinedRegexBlocks ). onChange ( async ( value ) => {
this . plugin . settings . UserRulesRespectUserDefinedRegexBlocks = value ;
await this . plugin . saveSettings ();
});
});
const excludeSection = this . createSection ( el , locale7 . headers . excludeFoldersFiles , locale7 . settings . excludeFoldersFiles . desc );
const excludeSetting = new import_obsidian5 . Setting ( excludeSection . bodyEl );
excludeSetting . settingEl . addClass ( "et-setting-full-width" );
excludeSetting . addTextArea (( text ) => {
text . setValue ( this . plugin . settings . ExcludeFiles );
text . inputEl . addClass ( "et-settings-textarea" );
text . onChange ( async ( value ) => {
this . plugin . settings . ExcludeFiles = value ;
this . plugin . saveSettings ();
});
});
const advancedSections = [
languageSection . sectionEl ,
detailSection . sectionEl ,
prefixSection . sectionEl ,
regexSection . sectionEl ,
excludeSection . sectionEl
];
const syncRegexContentState = () => {
this . setInteractiveDisabled ( regContentAreaSetting . settingEl , ! this . plugin . settings . AutoFormat || ! this . plugin . settings . UserDefinedRegSwitch );
};
const syncAutoFormatState = ( enabled ) => {
this . setInteractiveDisabled ( pasteSetting . settingEl , ! enabled );
this . setInteractiveDisabled ( autoCapitalSetting . settingEl , ! enabled );
advancedSections . forEach (( sectionEl ) => this . setInteractiveDisabled ( sectionEl , ! enabled ));
this . setInteractiveDisabled ( regSwitchSetting . settingEl , ! enabled );
syncRegexContentState ();
};
syncAutoFormatState ( this . plugin . settings . AutoFormat );
}
getAllScriptCategories () {
const builtin = [
"chinese" /* Chinese */ ,
"japanese" /* Japanese */ ,
"korean" /* Korean */ ,
"cjk" /* CJK */ ,
"english" /* English */ ,
"digit" /* Digit */ ,
"russian" /* Russian */
];
const custom = ( this . plugin . settings . customScriptCategories || []). map (( c ) => c . name );
return [... builtin , ... custom ];
}
buildBuiltinRulesSection ( el ) {
const locale7 = getLocale ();
const section = this . createSection ( el , locale7 . headers . builtinRulesSection , void 0 , ( actionsEl ) => {
const resetBtn = actionsEl . createEl ( "button" , {
text : locale7 . toolTip . resetAllRules ,
cls : "et-reset-btn et-section-action-btn"
});
resetBtn . addEventListener ( "click" , async () => {
await this . plugin . ruleManager . resetAllBuiltinRules ();
new import_obsidian5 . Notice ( locale7 . toolTip . resetSuccess );
this . display ();
});
}, "et-builtin-rules-section" );
for ( const rule of this . plugin . ruleManager . cachedBuiltinRules ) {
this . buildRuleItem ( section . bodyEl , rule , true );
}
const deletedIds = this . plugin . settings . deletedBuiltinRuleIds || [];
if ( deletedIds . length > 0 ) {
const details = section . bodyEl . createEl ( "details" , { cls : "et-deleted-rules" });
details . createEl ( "summary" , { text : ` ${ locale7 . headers . deletedRulesSection } ( ${ deletedIds . length } )` });
for ( const id of deletedIds ) {
const defaultRule = DEFAULT_BUILTIN_RULES . find (( r ) => r . id === id );
if ( ! defaultRule )
continue ;
const opts = RuleEngine . parseOptions ( defaultRule . options );
const typeLabel = this . getRuleTypeLabel ( opts . type );
const typeCls = this . getRuleTypeCls ( opts . type );
const preview = defaultRule . id && locale7 . builtinRuleDescriptions [ defaultRule . id ] || defaultRule . description || ` ${ RuleEngine . escapeText ( defaultRule . trigger , opts . isRegex ) } \u2192 ${ typeof defaultRule . replacement === "string" ? defaultRule . replacement : "(fn)" } ` ;
new import_obsidian5 . Setting ( details ). setName ( createFragment (( f ) => {
f . createSpan ({ cls : `et-rule-type-tag ${ typeCls } ` , text : typeLabel });
f . createSpan ({ text : preview });
})). addButton (( button ) => {
button . setButtonText ( locale7 . toolTip . restoreRule ). onClick ( async () => {
await this . plugin . ruleManager . restoreBuiltinRule ( id );
this . display ();
});
});
}
}
}
buildUserRulesSection ( el ) {
const locale7 = getLocale ();
const section = this . createSection ( el , locale7 . headers . userRulesSection , void 0 , ( actionsEl ) => {
const addBtn = actionsEl . createEl ( "button" , {
text : "+" ,
cls : "mod-cta et-section-action-btn"
});
addBtn . addEventListener ( "click" , () => {
new RuleEditModal ( this . app , "create" , {}, async ( rule ) => {
await this . plugin . ruleManager . addUserRule ( rule );
this . display ();
}). open ();
});
const exportBtn = actionsEl . createEl ( "button" , { cls : "clickable-icon et-section-icon-btn" });
exportBtn . setAttribute ( "aria-label" , locale7 . toolTip . exportRules );
( 0 , import_obsidian5 . setIcon )( exportBtn , "arrow-up-from-line" );
exportBtn . addEventListener ( "click" , () => {
const rules = this . plugin . ruleManager . cachedUserRules ;
if ( rules . length === 0 ) {
new import_obsidian5 . Notice ( locale7 . toolTip . noRulesToExport );
return ;
}
const json = JSON . stringify ( rules , null , 2 );
const blob = new Blob ([ json ], { type : "application/json" });
const url = URL . createObjectURL ( blob );
const a = document . createElement ( "a" );
a . href = url ;
a . download = "easy-typing-user-rules.json" ;
document . body . appendChild ( a );
a . click ();
document . body . removeChild ( a );
URL . revokeObjectURL ( url );
});
const importBtn = actionsEl . createEl ( "button" , { cls : "clickable-icon et-section-icon-btn" });
importBtn . setAttribute ( "aria-label" , locale7 . toolTip . importRules );
( 0 , import_obsidian5 . setIcon )( importBtn , "arrow-down-to-line" );
importBtn . addEventListener ( "click" , () => {
const input = document . createElement ( "input" );
input . type = "file" ;
input . accept = ".json" ;
input . style . display = "none" ;
input . addEventListener ( "change" , async () => {
var _a ;
const file = ( _a = input . files ) == null ? void 0 : _a [ 0 ];
if ( ! file )
return ;
try {
const text = await file . text ();
let parsed ;
try {
parsed = JSON . parse ( text );
} catch ( e ) {
new import_obsidian5 . Notice ( `[EasyTyping] ${ locale7 . toolTip . importInvalidJson } ` );
return ;
}
if ( ! Array . isArray ( parsed ) || parsed . length === 0 ) {
new import_obsidian5 . Notice ( `[EasyTyping] ${ locale7 . toolTip . importNoRules } ` );
return ;
}
const { imported , skipped } = await this . plugin . ruleManager . importUserRules ( parsed );
if ( imported === 0 && skipped > 0 ) {
new import_obsidian5 . Notice ( `[EasyTyping] ${ locale7 . toolTip . importNoRules } ` );
} else {
new import_obsidian5 . Notice ( `[EasyTyping] ${ ( 0 , import_sprintf_js . sprintf )( locale7 . toolTip . importSuccess , imported , skipped ) } ` );
}
this . display ();
} finally {
input . remove ();
}
});
document . body . appendChild ( input );
input . click ();
});
}, "et-user-rules-section" );
this . plugin . ruleManager . cachedUserRules . forEach (( rule , index ) => {
this . buildRuleItem ( section . bodyEl , rule , false , index );
});
}
buildRuleItem ( container , rule , isBuiltin , ruleIndex ) {
const locale7 = getLocale ();
const opts = RuleEngine . parseOptions ( rule . options );
const typeLabel = this . getRuleTypeLabel ( opts . type );
const typeCls = this . getRuleTypeCls ( opts . type );
const enabled = rule . enabled !== false ;
const isTab = opts . triggerMode === "tab" /* Tab */ ;
const isFn = opts . isFunctionReplacement ;
const scopeBadges = this . getRuleScopeBadges ( opts . scope , rule . scope_language , locale7 );
let preview ;
if ( rule . description ) {
preview = rule . description ;
} else {
const repl = typeof rule . replacement === "string" ? rule . replacement : "(fn)" ;
const renderMatch = ( text ) => RuleEngine . escapeText ( text , opts . isRegex );
preview = ` ${ renderMatch ( rule . trigger ) }${ rule . trigger_right ? " \u2026 " + renderMatch ( rule . trigger_right ) : "" } \u2192 ${ repl } ` ;
}
const setting = new import_obsidian5 . Setting ( container ). setClass ( "et-rule-item" ). setName ( createFragment (( f ) => {
f . createSpan ({ cls : `et-rule-type-tag ${ typeCls } ` , text : typeLabel });
scopeBadges . forEach (( badge ) => {
f . createSpan ({ cls : `et-rule-scope-tag ${ badge . cls } ` , text : badge . text });
});
if ( opts . type === "input" /* Input */ ) {
const modeTag = f . createSpan ({
cls : `et-rule-trigger-mode ${ isTab ? "et-trigger-mode-tab" : "et-trigger-mode-auto" } ` ,
text : isTab ? "Tab" : "Auto"
});
modeTag . setAttribute ( "aria-label" , locale7 . settings . ruleEditModal . fieldTriggerMode );
modeTag . addEventListener ( "click" , async ( e ) => {
e . stopPropagation ();
const newIsTab = ! isTab ;
await this . plugin . ruleManager . updateRuleTriggerMode ( rule . id , isBuiltin , newIsTab );
this . display ();
});
}
if ( isFn ) {
f . createSpan ({ cls : "et-rule-type-tag et-rule-type-fn" , text : "Fn" });
}
f . createSpan ({ cls : "et-rule-preview-text" , text : preview });
})). addToggle (( toggle ) => {
toggle . setValue ( enabled ). setTooltip ( locale7 . toolTip . enableRule ). onChange ( async ( value ) => {
setting . settingEl . style . opacity = value ? "" : "0.5" ;
await this . plugin . ruleManager . toggleRuleEnabled ( rule . id , isBuiltin , value );
});
}). addExtraButton (( button ) => {
button . setIcon ( "gear" ). setTooltip ( locale7 . toolTip . editRule ). onClick (() => {
new RuleEditModal ( this . app , "edit" , rule , async ( updated ) => {
if ( isBuiltin ) {
await this . plugin . ruleManager . updateBuiltinRule ( rule . id , updated );
} else {
await this . plugin . ruleManager . updateUserRule ( rule . id , updated );
}
this . display ();
}). open ();
});
}). addExtraButton (( button ) => {
button . setIcon ( "trash" ). setTooltip ( locale7 . toolTip . removeRule ). onClick ( async () => {
if ( isBuiltin ) {
await this . plugin . ruleManager . deleteBuiltinRule ( rule . id );
} else {
await this . plugin . ruleManager . deleteUserRule ( rule . id );
}
this . display ();
});
});
if ( ! enabled ) {
setting . settingEl . style . opacity = "0.5" ;
}
if ( ! isBuiltin && ruleIndex !== void 0 ) {
const el = setting . settingEl ;
el . dataset . ruleIndex = String ( ruleIndex );
const handle = el . createDiv ({ cls : "et-rule-drag-handle" });
( 0 , import_obsidian5 . setIcon )( handle , "grip-vertical" );
el . prepend ( handle );
handle . draggable = true ;
let cachedMidY = 0 ;
handle . addEventListener ( "dragstart" , ( e ) => {
this . dragSourceIndex = parseInt ( el . dataset . ruleIndex );
el . addClass ( "et-rule-dragging" );
e . dataTransfer . effectAllowed = "move" ;
});
handle . addEventListener ( "dragend" , () => {
var _a ;
this . dragSourceIndex = null ;
el . removeClass ( "et-rule-dragging" );
( _a = el . parentElement ) == null ? void 0 : _a . querySelectorAll ( ".et-rule-drag-over-top, .et-rule-drag-over-bottom" ). forEach (( item ) => item . removeClass ( "et-rule-drag-over-top" , "et-rule-drag-over-bottom" ));
});
el . addEventListener ( "dragenter" , () => {
const rect = el . getBoundingClientRect ();
cachedMidY = rect . top + rect . height / 2 ;
});
el . addEventListener ( "dragover" , ( e ) => {
if ( this . dragSourceIndex === null )
return ;
e . preventDefault ();
e . dataTransfer . dropEffect = "move" ;
const isTop = e . clientY < cachedMidY ;
const targetCls = isTop ? "et-rule-drag-over-top" : "et-rule-drag-over-bottom" ;
if ( ! el . hasClass ( targetCls )) {
el . removeClass ( "et-rule-drag-over-top" , "et-rule-drag-over-bottom" );
el . addClass ( targetCls );
}
});
el . addEventListener ( "dragleave" , () => {
el . removeClass ( "et-rule-drag-over-top" , "et-rule-drag-over-bottom" );
});
el . addEventListener ( "drop" , async ( e ) => {
e . preventDefault ();
el . removeClass ( "et-rule-drag-over-top" , "et-rule-drag-over-bottom" );
const fromIndex = this . dragSourceIndex ;
if ( fromIndex === null )
return ;
const currentIndex = parseInt ( el . dataset . ruleIndex );
const dropOnBottom = e . clientY >= cachedMidY ;
let toIndex ;
if ( fromIndex < currentIndex ) {
toIndex = dropOnBottom ? currentIndex : currentIndex - 1 ;
} else {
toIndex = dropOnBottom ? currentIndex + 1 : currentIndex ;
}
if ( fromIndex === toIndex )
return ;
await this . plugin . ruleManager . reorderUserRule ( fromIndex , toIndex );
const parent = el . parentElement ;
const ruleItems = Array . from ( parent . querySelectorAll ( ".et-rule-item[data-rule-index]" ));
const sourceEl = ruleItems [ fromIndex ];
if ( ! sourceEl )
return ;
if ( toIndex < fromIndex ) {
parent . insertBefore ( sourceEl , ruleItems [ toIndex ]);
} else {
const ref = ruleItems [ toIndex ];
if ( ref . nextSibling ) {
parent . insertBefore ( sourceEl , ref . nextSibling );
} else {
parent . appendChild ( sourceEl );
}
}
ruleItems . splice ( fromIndex , 1 );
ruleItems . splice ( toIndex , 0 , sourceEl );
ruleItems . forEach (( item , i ) => item . dataset . ruleIndex = String ( i ));
});
}
}
getRuleScopeBadges ( scopes , scopeLanguage , locale7 = getLocale ()) {
const badges = [];
if ( scopes . includes ( "code" /* Code */ )) {
badges . push ({
text : `< ${ scopeLanguage || locale7 . dropdownOptions . scopeCode } >` ,
cls : "et-rule-scope-code"
});
}
if ( scopes . includes ( "formula" /* Formula */ )) {
badges . push ({
text : "\u0192x" ,
cls : "et-rule-scope-formula"
});
}
return badges ;
}
getRuleTypeLabel ( type ) {
const locale7 = getLocale ();
switch ( type ) {
case "input" /* Input */ :
return locale7 . settings . ruleType . input ;
case "delete" /* Delete */ :
return locale7 . settings . ruleType . delete ;
case "selectKey" /* SelectKey */ :
return locale7 . settings . ruleType . selectKey ;
}
}
getRuleTypeCls ( type ) {
switch ( type ) {
case "input" /* Input */ :
return "et-rule-type-input" ;
case "delete" /* Delete */ :
return "et-rule-type-delete" ;
case "selectKey" /* SelectKey */ :
return "et-rule-type-selectkey" ;
}
}
buildOtherTab ( el ) {
const locale7 = getLocale ();
const experimentalSection = this . createSection ( el , locale7 . headers . experimentalFeatures );
new import_obsidian5 . Setting ( experimentalSection . bodyEl ). setName ( locale7 . settings . strictLineBreaks . name ). setDesc ( locale7 . settings . strictLineBreaks . desc ). addDropdown (( dropdown ) => {
dropdown . addOption ( "enter_twice" /* EnterTwice */ , locale7 . dropdownOptions . enterTwice );
dropdown . addOption ( "two_space" /* TwoSpace */ , locale7 . dropdownOptions . twoSpace );
dropdown . addOption ( "mix_mode" /* Mix */ , locale7 . dropdownOptions . mixMode );
2026-01-05 13:03:55 +08:00
dropdown . setValue ( this . plugin . settings . StrictLineMode );
dropdown . onChange ( async ( v ) => {
this . plugin . settings . StrictLineMode = v ;
await this . plugin . saveSettings ();
});
}). addToggle (( toggle ) => {
toggle . setValue ( this . plugin . settings . StrictModeEnter ). onChange ( async ( value ) => {
this . plugin . settings . StrictModeEnter = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( experimentalSection . bodyEl ). setName ( locale7 . settings . collapsePersistentEnter . name ). setDesc ( locale7 . settings . collapsePersistentEnter . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . CollapsePersistentEnter ). onChange ( async ( value ) => {
this . plugin . settings . CollapsePersistentEnter = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( experimentalSection . bodyEl ). setName ( locale7 . settings . fixMicrosoftIME . name ). setDesc ( locale7 . settings . fixMicrosoftIME . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . TryFixMSIME ). onChange ( async ( value ) => {
this . plugin . settings . TryFixMSIME = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( experimentalSection . bodyEl ). setName ( locale7 . settings . fixMacOSContextMenu . name ). setDesc ( locale7 . settings . fixMacOSContextMenu . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . FixMacOSContextMenu ). onChange ( async ( value ) => {
this . plugin . settings . FixMacOSContextMenu = value ;
await this . plugin . saveSettings ();
});
});
2026-08-21 15:44:03 +08:00
const miscSection = this . createSection ( el );
new import_obsidian5 . Setting ( miscSection . bodyEl ). setName ( locale7 . settings . rulesStoragePath . name ). setDesc ( locale7 . settings . rulesStoragePath . desc ). addText (( text ) => {
text . setPlaceholder ( locale7 . settings . rulesStoragePath . defaultOption ). setValue ( this . plugin . settings . rulesStoragePath );
new FolderSuggest ( this . app , text . inputEl , locale7 . settings . rulesStoragePath . defaultOption , async ( path ) => {
this . plugin . settings . rulesStoragePath = path ;
2026-01-05 13:03:55 +08:00
await this . plugin . saveSettings ();
2026-08-21 15:44:03 +08:00
await this . plugin . ruleManager . initRuleEngine ();
this . display ();
});
}). addButton (( btn ) => {
btn . setButtonText ( locale7 . settings . rulesStoragePath . migrateButton ). setTooltip ( locale7 . settings . rulesStoragePath . migrateDesc ). onClick ( async () => {
const oldPath = this . plugin . ruleManager . previousStoragePath ;
const newPath = this . plugin . settings . rulesStoragePath ;
await this . plugin . ruleManager . migrateRulesFiles ( oldPath , newPath );
await this . plugin . ruleManager . initRuleEngine ();
new import_obsidian5 . Notice ( locale7 . settings . rulesStoragePath . migrateSuccess );
this . display ();
2026-01-05 13:03:55 +08:00
});
});
2026-08-21 15:44:03 +08:00
new import_obsidian5 . Setting ( miscSection . bodyEl ). setName ( locale7 . settings . printDebugInfo . name ). setDesc ( locale7 . settings . printDebugInfo . desc ). addToggle (( toggle ) => {
2026-01-05 13:03:55 +08:00
toggle . setValue ( this . plugin . settings . debug ). onChange ( async ( value ) => {
this . plugin . settings . debug = value ;
setDebug ( value );
await this . plugin . saveSettings ();
});
});
}
};
// src/main.ts
2026-08-21 15:44:03 +08:00
var import_view5 = require ( "@codemirror/view" );
// src/tabstops_state_field.ts
var import_view2 = require ( "@codemirror/view" );
var import_state3 = require ( "@codemirror/state" );
var addTabstopsEffect = import_state3 . StateEffect . define ();
var removeTabstopEffect = import_state3 . StateEffect . define ();
var removeAllTabstopsEffect = import_state3 . StateEffect . define ();
var tabstopsStateField = import_state3 . StateField . define ({
create () {
return [];
},
update ( value , transaction ) {
let tabstopGroups = value ;
tabstopGroups . forEach (( grp ) => grp . map ( transaction . changes ));
for ( const effect of transaction . effects ) {
if ( effect . is ( addTabstopsEffect )) {
tabstopGroups = [];
tabstopGroups . unshift (... effect . value );
} else if ( effect . is ( removeTabstopEffect )) {
tabstopGroups . shift ();
} else if ( effect . is ( removeAllTabstopsEffect )) {
tabstopGroups = [];
}
}
return tabstopGroups ;
},
provide : ( field ) => {
return import_view2 . EditorView . decorations . of (( view ) => {
const tabstopGroups = view . state . field ( field );
const decos = [];
if ( tabstopGroups . length >= 2 ) {
decos . push (... tabstopGroups [ 1 ]. getDecoRanges ());
}
return import_view2 . Decoration . set ( decos , true );
});
}
});
function getTabstopGroupsFromView ( view ) {
const currentTabstopGroups = view . state . field ( tabstopsStateField , false );
return currentTabstopGroups != null ? currentTabstopGroups : [];
}
function hasTabstops ( view ) {
return getTabstopGroupsFromView ( view ). length > 0 ;
}
function removeTabstop ( view ) {
view . dispatch ({
effects : [ removeTabstopEffect . of ( null )]
});
}
function removeAllTabstops ( view ) {
view . dispatch ({
effects : [ removeAllTabstopsEffect . of ( null )]
});
}
function tidyTabstops ( view ) {
const currentTabstopGroups = getTabstopGroupsFromView ( view );
if ( currentTabstopGroups . length === 1 ) {
removeAllTabstops ( view );
}
}
function isInsideCurTabstop ( view ) {
const currentTabstopGroups = getTabstopGroupsFromView ( view );
if ( currentTabstopGroups . length > 1 && currentTabstopGroups [ 0 ]. containsSelection ( view . state . selection )) {
return true ;
}
return false ;
}
function consumeAndGotoNextTabstop ( view ) {
if ( getTabstopGroupsFromView ( view ). length === 0 )
return false ;
removeTabstop ( view );
const oldSel = view . state . selection ;
const nextGrp = getTabstopGroupsFromView ( view )[ 0 ];
if ( ! nextGrp )
return false ;
const shouldMoveToEndpoints = nextGrp . containsSelection ( oldSel );
nextGrp . select ( view , shouldMoveToEndpoints );
const newSel = view . state . selection ;
if ( oldSel . eq ( newSel ))
return consumeAndGotoNextTabstop ( view );
tidyTabstops ( view );
return true ;
}
// src/rule_manager.ts
var RuleManager = class {
constructor ( app , manifest , settings , savePluginSettings ) {
this . app = app ;
this . manifest = manifest ;
this . settings = settings ;
this . savePluginSettings = savePluginSettings ;
this . cachedBuiltinRules = [];
this . cachedUserRules = [];
this . previousStoragePath = "" ;
this . lastSaveTime = 0 ;
this . BUILTIN_RULES_FILE = "builtin-rules.json" ;
this . USER_RULES_FILE = "user-rules.json" ;
this . previousStoragePath = settings . rulesStoragePath ;
}
getLocalizedBuiltinRules ( rules = DEFAULT_BUILTIN_RULES ) {
const localeDescMap = getLocale (). builtinRuleDescriptions ;
return rules . map (( rule ) => {
var _a ;
return {
... rule ,
description : ( _a = localeDescMap [ rule . id ]) != null ? _a : rule . description
};
});
}
getImportDedupKey ( rule ) {
var _a , _b ;
const isRegex = (( _a = rule . options ) != null ? _a : "" ). includes ( "r" );
const normalizedFlags = isRegex ? RuleEngine . normalizeRegexFlags ( rule . regex_flags ) : "" ;
return ` ${ rule . trigger } \0 ${ ( _b = rule . trigger_right ) != null ? _b : "" } \0 ${ isRegex } \0 ${ normalizedFlags } ` ;
}
pluginPath ( filename ) {
const base = this . settings . rulesStoragePath ? this . settings . rulesStoragePath : this . manifest . dir ;
return ` ${ base } / ${ filename } ` . replace ( /\/+/g , "/" );
}
async loadRulesFile ( filename ) {
const path = this . pluginPath ( filename );
try {
const content = await this . app . vault . adapter . read ( path );
return JSON . parse ( content );
} catch ( e ) {
return [];
}
}
async saveRulesFile ( filename , rules ) {
const path = this . pluginPath ( filename );
this . lastSaveTime = Date . now ();
await this . app . vault . adapter . write ( path , JSON . stringify ( rules , null , 2 ));
}
async mergeBuiltinRules () {
const currentRules = await this . loadRulesFile ( this . BUILTIN_RULES_FILE );
const existingIds = new Set ( currentRules . map (( r ) => r . id ). filter ( Boolean ));
const deletedIds = new Set ( this . settings . deletedBuiltinRuleIds );
const newRules = DEFAULT_BUILTIN_RULES . filter (( r ) => ! existingIds . has ( r . id ) && ! deletedIds . has ( r . id ));
if ( newRules . length === 0 )
return ;
await this . saveRulesFile ( this . BUILTIN_RULES_FILE , [... currentRules , ... this . getLocalizedBuiltinRules ( newRules )]);
}
async initRuleEngine () {
this . ruleEngine = new RuleEngine ();
if ( this . settings . rulesStoragePath ) {
await this . app . vault . adapter . mkdir ( this . settings . rulesStoragePath );
}
const builtinPath = this . pluginPath ( this . BUILTIN_RULES_FILE );
const userPath = this . pluginPath ( this . USER_RULES_FILE );
if ( ! await this . app . vault . adapter . exists ( builtinPath )) {
await this . saveRulesFile ( this . BUILTIN_RULES_FILE , this . getLocalizedBuiltinRules ());
} else {
await this . mergeBuiltinRules ();
}
if ( ! await this . app . vault . adapter . exists ( userPath )) {
await this . saveRulesFile ( this . USER_RULES_FILE , []);
}
const builtinRules = await this . loadRulesFile ( this . BUILTIN_RULES_FILE );
const userRules = await this . loadRulesFile ( this . USER_RULES_FILE );
this . cachedBuiltinRules = builtinRules ;
this . cachedUserRules = userRules ;
this . ruleEngine . loadFromFiles ( builtinRules , userRules );
}
async deleteBuiltinRule ( id ) {
this . ruleEngine . removeRule ( id );
this . cachedBuiltinRules = this . cachedBuiltinRules . filter (( r ) => r . id !== id );
await this . saveRulesFile ( this . BUILTIN_RULES_FILE , this . cachedBuiltinRules );
this . settings . deletedBuiltinRuleIds . push ( id );
await this . savePluginSettings ();
}
async restoreBuiltinRule ( id ) {
const defaultRule = DEFAULT_BUILTIN_RULES . find (( r ) => r . id === id );
if ( ! defaultRule )
return ;
const localizedRule = this . getLocalizedBuiltinRules ([ defaultRule ])[ 0 ];
this . ruleEngine . addSimpleRule ( localizedRule );
this . cachedBuiltinRules . push ( localizedRule );
await this . saveRulesFile ( this . BUILTIN_RULES_FILE , this . cachedBuiltinRules );
this . settings . deletedBuiltinRuleIds = this . settings . deletedBuiltinRuleIds . filter (( i ) => i !== id );
await this . savePluginSettings ();
}
async resetAllBuiltinRules () {
this . cachedBuiltinRules = this . getLocalizedBuiltinRules ();
await this . saveRulesFile ( this . BUILTIN_RULES_FILE , this . cachedBuiltinRules );
this . settings . deletedBuiltinRuleIds = [];
await this . savePluginSettings ();
this . ruleEngine . loadFromFiles ( this . cachedBuiltinRules , this . cachedUserRules );
}
async addUserRule ( rule ) {
const id = `user- ${ Date . now () } - ${ Math . random (). toString ( 36 ). slice ( 2 , 6 ) } ` ;
rule . id = id ;
this . cachedUserRules . push ( rule );
await this . saveRulesFile ( this . USER_RULES_FILE , this . cachedUserRules );
this . ruleEngine . addSimpleRule ( rule );
return id ;
}
async importUserRules ( incoming ) {
var _a ;
const existingSet = new Set ( this . cachedUserRules . map (( r ) => this . getImportDedupKey ( r )));
let imported = 0 ;
let skipped = 0 ;
for ( const rule of incoming ) {
if ( ! rule . trigger || rule . replacement === void 0 ) {
skipped ++ ;
continue ;
}
const key = this . getImportDedupKey ( rule );
if ( existingSet . has ( key )) {
skipped ++ ;
continue ;
}
existingSet . add ( key );
const id = `user- ${ Date . now () } - ${ Math . random (). toString ( 36 ). slice ( 2 , 6 ) } ` ;
rule . id = id ;
rule . enabled = ( _a = rule . enabled ) != null ? _a : true ;
this . cachedUserRules . push ( rule );
this . ruleEngine . addSimpleRule ( rule );
imported ++ ;
}
if ( imported > 0 ) {
await this . saveRulesFile ( this . USER_RULES_FILE , this . cachedUserRules );
}
return { imported , skipped };
}
async updateUserRule ( id , rule ) {
const idx = this . cachedUserRules . findIndex (( r ) => r . id === id );
if ( idx === - 1 )
return ;
rule . id = id ;
this . cachedUserRules [ idx ] = rule ;
await this . saveRulesFile ( this . USER_RULES_FILE , this . cachedUserRules );
this . ruleEngine . removeRule ( id );
this . ruleEngine . addSimpleRule ( rule );
}
async deleteUserRule ( id ) {
this . cachedUserRules = this . cachedUserRules . filter (( r ) => r . id !== id );
await this . saveRulesFile ( this . USER_RULES_FILE , this . cachedUserRules );
this . ruleEngine . removeRule ( id );
}
async updateBuiltinRule ( id , rule ) {
const idx = this . cachedBuiltinRules . findIndex (( r ) => r . id === id );
if ( idx === - 1 )
return ;
rule . id = id ;
this . cachedBuiltinRules [ idx ] = rule ;
await this . saveRulesFile ( this . BUILTIN_RULES_FILE , this . cachedBuiltinRules );
this . ruleEngine . removeRule ( id );
this . ruleEngine . addSimpleRule ( rule );
}
async toggleRuleEnabled ( id , isBuiltin , enabled ) {
const cache = isBuiltin ? this . cachedBuiltinRules : this . cachedUserRules ;
const file = isBuiltin ? this . BUILTIN_RULES_FILE : this . USER_RULES_FILE ;
const rule = cache . find (( r ) => r . id === id );
if ( ! rule )
return ;
rule . enabled = enabled ;
await this . saveRulesFile ( file , cache );
this . ruleEngine . setEnabled ( id , enabled );
}
async reorderUserRule ( fromIndex , toIndex ) {
if ( fromIndex === toIndex )
return ;
if ( fromIndex < 0 || fromIndex >= this . cachedUserRules . length )
return ;
if ( toIndex < 0 || toIndex >= this . cachedUserRules . length )
return ;
const [ rule ] = this . cachedUserRules . splice ( fromIndex , 1 );
this . cachedUserRules . splice ( toIndex , 0 , rule );
await this . saveRulesFile ( this . USER_RULES_FILE , this . cachedUserRules );
}
async updateRuleTriggerMode ( id , isBuiltin , tabMode ) {
var _a ;
const cache = isBuiltin ? this . cachedBuiltinRules : this . cachedUserRules ;
const file = isBuiltin ? this . BUILTIN_RULES_FILE : this . USER_RULES_FILE ;
const rule = cache . find (( r ) => r . id === id );
if ( ! rule )
return ;
let opts = ( _a = rule . options ) != null ? _a : "" ;
if ( tabMode && ! opts . includes ( "T" ))
opts += "T" ;
else if ( ! tabMode )
opts = opts . replace ( /T/g , "" );
rule . options = opts || void 0 ;
await this . saveRulesFile ( file , cache );
this . ruleEngine . updateRule ( id , { triggerMode : tabMode ? "tab" /* Tab */ : "auto" /* Auto */ });
}
async migrateRulesFiles ( oldPath , newPath ) {
const oldBase = oldPath || this . manifest . dir ;
const newBase = newPath || this . manifest . dir ;
if ( oldBase === newBase )
return ;
if ( newPath ) {
await this . app . vault . adapter . mkdir ( newPath );
}
for ( const filename of [ this . BUILTIN_RULES_FILE , this . USER_RULES_FILE ]) {
const src = ` ${ oldBase } / ${ filename } ` ;
try {
const content = await this . app . vault . adapter . read ( src );
await this . app . vault . adapter . write ( ` ${ newBase } / ${ filename } ` , content );
} catch ( e ) {
}
}
this . previousStoragePath = newPath ;
}
};
2026-01-05 13:03:55 +08:00
// src/syntax.ts
var import_language2 = require ( "@codemirror/language" );
function isCodeBlockInPos ( state , pos ) {
let codeBlockInfos = getCodeBlocksInfos ( state );
for ( let i = 0 ; i < codeBlockInfos . length ; i ++ ) {
if ( pos >= codeBlockInfos [ i ]. start_pos && pos <= codeBlockInfos [ i ]. end_pos ) {
return true ;
}
}
return false ;
}
function getCodeBlockInfoInPos ( state , pos ) {
let codeBlockInfos = getCodeBlocksInfos ( state );
for ( let i = 0 ; i < codeBlockInfos . length ; i ++ ) {
if ( pos >= codeBlockInfos [ i ]. start_pos && pos <= codeBlockInfos [ i ]. end_pos ) {
return codeBlockInfos [ i ];
}
}
return null ;
}
function selectCodeBlockInPos ( view , selection ) {
let pos = selection . anchor ;
let codeBlockInfos = getCodeBlocksInfos ( view . state );
for ( let i = 0 ; i < codeBlockInfos . length ; i ++ ) {
if ( pos >= codeBlockInfos [ i ]. start_pos && pos <= codeBlockInfos [ i ]. end_pos ) {
if ( codeBlockInfos [ i ]. code_start_pos == codeBlockInfos [ i ]. code_end_pos ) {
view . dispatch ({
selection : {
anchor : codeBlockInfos [ i ]. start_pos ,
head : codeBlockInfos [ i ]. end_pos
}
});
return true ;
}
let code_line_start = view . state . doc . lineAt ( codeBlockInfos [ i ]. code_start_pos );
let isCodeSelected = selection . anchor == code_line_start . from && selection . head == codeBlockInfos [ i ]. code_end_pos ;
let isCodeBlockSelected = selection . anchor == codeBlockInfos [ i ]. start_pos && selection . head == codeBlockInfos [ i ]. end_pos ;
if ( isCodeSelected ) {
view . dispatch ({
selection : {
anchor : codeBlockInfos [ i ]. start_pos ,
head : codeBlockInfos [ i ]. end_pos
}
});
return true ;
}
if ( isCodeBlockSelected )
return false ;
view . dispatch ({
selection : {
anchor : code_line_start . from ,
head : codeBlockInfos [ i ]. code_end_pos
}
});
return true ;
}
}
return false ;
}
function getCodeBlocksInfos ( state ) {
let isCodeBlockBegin = false ;
let codeBlockInfos = [];
let curCodeBlockInfo = null ;
const doc = state . doc ;
( 0 , import_language2 . syntaxTree )( state ). iterate ({
enter ( node ) {
2026-08-21 15:44:03 +08:00
var _a ;
2026-01-05 13:03:55 +08:00
const nodeName = node . name ;
const nodeFrom = node . from ;
const nodeTo = node . to ;
const nodeText = state . sliceDoc ( nodeFrom , nodeTo );
if ( nodeName . includes ( "codeblock-begin" )) {
isCodeBlockBegin = true ;
2026-08-21 15:44:03 +08:00
const fenceMatch = nodeText . match ( /[`~]{3,}/ );
let start_pos = nodeFrom + (( _a = fenceMatch == null ? void 0 : fenceMatch . index ) != null ? _a : 0 );
2026-01-05 13:03:55 +08:00
let indent = start_pos - state . doc . lineAt ( start_pos ). from ;
2026-08-21 15:44:03 +08:00
let language = nodeText . trim (). replace ( /^[`~]{3,}/ , "" ). trim ();
2026-01-05 13:03:55 +08:00
curCodeBlockInfo = {
start_pos ,
end_pos : - 1 ,
code_start_pos : - 1 ,
code_end_pos : - 1 ,
language : language . toLowerCase (),
indent
};
} else if ( nodeName . includes ( "codeblock-end" )) {
isCodeBlockBegin = false ;
if ( curCodeBlockInfo != null ) {
curCodeBlockInfo . end_pos = nodeTo ;
if ( doc . lineAt ( curCodeBlockInfo . start_pos ). number == doc . lineAt ( curCodeBlockInfo . end_pos ). number - 1 ) {
curCodeBlockInfo . code_start_pos = doc . lineAt ( curCodeBlockInfo . start_pos ). to ;
curCodeBlockInfo . code_end_pos = doc . lineAt ( curCodeBlockInfo . start_pos ). to ;
} else {
let code_start_line = doc . lineAt ( curCodeBlockInfo . start_pos ). number + 1 ;
let code_end_line = doc . lineAt ( curCodeBlockInfo . end_pos ). number - 1 ;
curCodeBlockInfo . code_start_pos = doc . line ( code_start_line ). from + curCodeBlockInfo . indent ;
curCodeBlockInfo . code_end_pos = doc . line ( code_end_line ). to ;
}
codeBlockInfos . push ( curCodeBlockInfo );
curCodeBlockInfo = null ;
}
}
}
});
if ( isCodeBlockBegin && curCodeBlockInfo ) {
curCodeBlockInfo . end_pos = doc . length ;
curCodeBlockInfo . code_end_pos = doc . length ;
if ( doc . lines > doc . lineAt ( curCodeBlockInfo . start_pos ). number ) {
let start_line = doc . lineAt ( curCodeBlockInfo . start_pos ). number + 1 ;
let code_start_pos = doc . line ( start_line ). from + curCodeBlockInfo . indent ;
curCodeBlockInfo . code_start_pos = code_start_pos < doc . length ? code_start_pos : doc . lineAt ( curCodeBlockInfo . start_pos + 1 ). from ;
} else {
curCodeBlockInfo . code_start_pos = doc . lineAt ( curCodeBlockInfo . start_pos ). to ;
}
codeBlockInfos . push ( curCodeBlockInfo );
curCodeBlockInfo = null ;
}
return codeBlockInfos ;
}
function getQuoteInfoInPos ( state , pos ) {
let quote_regex = /^(\s*)(>+) ?/ ;
let callout_regex = /^(\s*)(>)+ \[![^\s]+\][+-]? ?/ ;
let cur_line = state . doc . lineAt ( pos );
let match = cur_line . text . match ( quote_regex );
let is_callout = false ;
let cur_start_pos = - 1 ;
let cur_end_pos = - 1 ;
if ( match ) {
let match_callout = cur_line . text . match ( callout_regex );
cur_start_pos = cur_line . from + ( match_callout ? match_callout [ 0 ]. length : match [ 0 ]. length );
cur_end_pos = cur_line . to ;
let quote_start_line = cur_line . number ;
let quote_end_line = quote_start_line ;
for ( let i = quote_start_line + 1 ; i <= state . doc . lines ; i += 1 ) {
let line = state . doc . line ( i );
if ( line . text . match ( quote_regex )) {
quote_end_line = i ;
} else
break ;
}
for ( let i = quote_start_line ; i >= 1 ; i -= 1 ) {
let line = state . doc . line ( i );
let match_callout2 = line . text . match ( callout_regex );
let match_quote = line . text . match ( quote_regex );
if ( match_callout2 ) {
is_callout = true ;
quote_start_line = i ;
} else if ( match_quote ) {
quote_start_line = i ;
} else
break ;
}
return {
start_pos : state . doc . line ( quote_start_line ). from ,
end_pos : state . doc . line ( quote_end_line ). to ,
is_callout ,
cur_start_pos ,
cur_end_pos
};
} else {
return null ;
}
}
2026-08-21 15:44:03 +08:00
function detectRuleScope ( state , pos ) {
const tree = ( 0 , import_language2 . syntaxTree )( state );
const node = tree . resolveInner ( pos , - 1 );
const name = node . name ;
if ( name . contains ( "math" )) {
return { scope : "formula" /* Formula */ };
}
if ( name . contains ( "code" ) && ! name . contains ( "link" )) {
const codeBlockInfo = getCodeBlockInfoInPos ( state , pos );
return {
scope : "code" /* Code */ ,
language : ( codeBlockInfo == null ? void 0 : codeBlockInfo . language ) || void 0
};
}
return { scope : "text" /* Text */ };
}
2026-01-05 13:03:55 +08:00
2026-08-21 15:44:03 +08:00
// src/comment_toggle.ts
function toggleComment ( view ) {
const state = view . state ;
const selection = state . selection . main ;
const codeBlockInfo = getCodeBlockInfoInPos ( state , selection . from );
if ( codeBlockInfo ) {
return toggleCodeBlockComment ( view );
}
return toggleMarkdownComment ( selection . from , selection . to , view );
}
function toggleCodeBlockComment ( view ) {
const state = view . state ;
const selection = state . selection . main ;
const codeBlockInfo = getCodeBlockInfoInPos ( state , selection . from );
if ( ! codeBlockInfo )
return false ;
const language = codeBlockInfo . language ;
const commentSymbol = getCommentSymbol ( language . toLowerCase ());
if ( ! commentSymbol )
return false ;
let changes = [];
if ( selection . from === selection . to ) {
const line = state . doc . lineAt ( selection . from );
let change = toggleCodeBlockLineComment ( line . from , line . to , state . doc . sliceString ( line . from , line . to ), commentSymbol , selection . from );
if ( change && change . selection ) {
changes . push ( change );
view . dispatch ({
changes ,
selection : change . selection ,
userEvent : "EasyTyping.toggleComment"
});
return true ;
} else if ( change ) {
changes . push ( change );
}
} else {
const fromLine = state . doc . lineAt ( selection . from );
const toLine = state . doc . lineAt ( selection . to );
for ( let i = fromLine . number ; i <= toLine . number ; i ++ ) {
const line = state . doc . line ( i );
let change = toggleCodeBlockLineComment ( line . from , line . to , state . doc . sliceString ( line . from , line . to ), commentSymbol );
if ( change ) {
changes . push ( change );
2026-01-05 13:03:55 +08:00
}
}
2026-08-21 15:44:03 +08:00
}
view . dispatch ({ changes , userEvent : "EasyTyping.toggleComment" });
return true ;
}
function toggleCodeBlockLineComment ( from , to , text , commentSymbol , cursor_pos ) {
if ( text . trim () == "" && cursor_pos ) {
if ( typeof commentSymbol === "string" ) {
let new_pos = cursor_pos + commentSymbol . length + 1 ;
return {
from : cursor_pos ,
to : cursor_pos ,
insert : commentSymbol + " " ,
selection : { anchor : new_pos , head : new_pos }
};
} else {
let new_pos = cursor_pos + commentSymbol . start . length + 1 ;
return {
from : cursor_pos ,
to : cursor_pos ,
insert : commentSymbol . start + " " + commentSymbol . end ,
selection : { anchor : new_pos , head : new_pos }
};
}
}
if ( text . trim () == "" )
return null ;
if ( typeof commentSymbol === "string" ) {
const trimmedText = text . trimStart ();
if ( trimmedText . startsWith ( commentSymbol )) {
const commentIndex = text . indexOf ( commentSymbol );
return {
from : from + commentIndex ,
to : from + commentIndex + commentSymbol . length + ( trimmedText . startsWith ( commentSymbol + " " ) ? 1 : 0 ),
insert : ""
};
} else {
const indent = text . length - trimmedText . length ;
return {
from : from + indent ,
to : from + indent ,
insert : commentSymbol + " "
};
}
} else {
const trimmedText = text . trim ();
if ( trimmedText . startsWith ( commentSymbol . start ) && trimmedText . endsWith ( commentSymbol . end )) {
const commentStartIndex = text . indexOf ( commentSymbol . start );
return {
from : from + commentStartIndex ,
to ,
insert : trimmedText . slice ( commentSymbol . start . length + 1 , - commentSymbol . end . length - 1 )
};
} else {
const indent = text . length - text . trimStart (). length ;
return {
from : from + indent ,
to ,
insert : ` ${ commentSymbol . start } ${ trimmedText } ${ commentSymbol . end } `
};
}
}
}
function toggleMarkdownComment ( from , to , view ) {
const state = view . state ;
const doc = state . doc ;
const changes = [];
if ( from === to ) {
const currentText = doc . sliceString ( from - 3 , to + 3 );
if ( currentText === "%% %%" ) {
changes . push ({
from : from - 3 ,
to : to + 3 ,
insert : ""
});
view . dispatch ({
changes ,
selection : { anchor : from - 3 , head : from - 3 },
userEvent : "EasyTyping.toggleComment"
});
return true ;
}
changes . push ({
from ,
to ,
insert : "%% %%"
2026-01-05 13:03:55 +08:00
});
2026-08-21 15:44:03 +08:00
const newPos = from + 3 ;
view . dispatch ({
changes ,
selection : { anchor : newPos , head : newPos },
userEvent : "EasyTyping.toggleComment"
});
} else {
const selectedText = doc . sliceString ( from , to );
if ( selectedText . startsWith ( "%%" ) && selectedText . endsWith ( "%%" )) {
changes . push ({
from ,
to ,
insert : selectedText . slice ( 2 , - 2 )
});
} else {
changes . push ({
from ,
to ,
insert : `%% ${ selectedText } %%`
});
}
view . dispatch ({ changes , userEvent : "EasyTyping.toggleComment" });
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
return true ;
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
function getCommentSymbol ( language ) {
const commentSymbols = {
"js" : "//" ,
"javascript" : "//" ,
"ts" : "//" ,
"typescript" : "//" ,
"py" : "#" ,
"python" : "#" ,
"rb" : "#" ,
"ruby" : "#" ,
"java" : "//" ,
"c" : "//" ,
"cpp" : "//" ,
"cs" : "//" ,
"go" : "//" ,
"rust" : "//" ,
"swift" : "//" ,
"kotlin" : "//" ,
"php" : "//" ,
"css" : { start : "/*" , end : "*/" },
"scss" : { start : "/*" , end : "*/" },
"sql" : "--" ,
"shell" : "#" ,
"bash" : "#" ,
"powershell" : "#" ,
"html" : { start : "<!--" , end : "-->" },
"matlab" : "%" ,
"markdown" : { start : "%%" , end : "%%" }
};
return commentSymbols [ language ] || null ;
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
// src/formatting_commands.ts
var import_obsidian6 = require ( "obsidian" );
var import_language3 = require ( "@codemirror/language" );
function isCurrentFileExclude ( ctx ) {
if ( ctx . CurActiveMarkdown == "" ) {
let file = ctx . app . workspace . getActiveFile ();
if ( file != null && ctx . CurActiveMarkdown != file . path ) {
ctx . CurActiveMarkdown = file . path ;
} else {
return true ;
}
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
let excludePaths = ctx . settings . ExcludeFiles . split ( "\n" );
for ( let epath of excludePaths ) {
if ( epath . charAt ( 0 ) == "/" )
epath = epath . substring ( 1 );
if ( ctx . CurActiveMarkdown == epath )
return true ;
let len = epath . length ;
if ( ctx . CurActiveMarkdown . substring ( 0 , len ) == epath && ( ctx . CurActiveMarkdown . charAt ( len ) == "/" || ctx . CurActiveMarkdown . charAt ( len ) == "\\" || epath . charAt ( len - 1 ) == "/" || epath . charAt ( len - 1 ) == "\\" )) {
return true ;
}
2026-01-05 13:03:55 +08:00
}
return false ;
}
2026-08-21 15:44:03 +08:00
function formatArticle ( ctx , editor , view ) {
const editorView = editor . cm ;
const tree = ( 0 , import_language3 . ensureSyntaxTree )( editorView . state , editorView . state . doc . length );
if ( ! tree ) {
new import_obsidian6 . Notice ( "EasyTyping: Syntax tree is not ready yet, please wait a moment and try again later!" , 5e3 );
return ;
}
ctx . onFormatArticle = true ;
let lineCount = editor . lineCount ();
let new_article = "" ;
let cs = editor . getCursor ();
let ch = 0 ;
for ( let i = 0 ; i < lineCount ; i ++ ) {
if ( i != 0 )
new_article += "\n" ;
if ( i != cs . line ) {
new_article += preFormatOneLine ( ctx , editor , i + 1 )[ 0 ];
} else {
let newData = preFormatOneLine ( ctx , editor , i + 1 , cs . ch );
new_article += newData [ 0 ];
ch = newData [ 1 ];
}
}
editor . setValue ( new_article );
editor . setCursor ({ line : cs . line , ch });
ctx . onFormatArticle = false ;
new import_obsidian6 . Notice ( "EasyTyping: Format Article Done!" );
}
function formatSelectionOrCurLine ( ctx , editor , view ) {
if ( ! editor . somethingSelected () || editor . getSelection () === "" ) {
let lineNumber = editor . getCursor (). line ;
let newLineData = preFormatOneLine ( ctx , editor , lineNumber + 1 , editor . getCursor (). ch );
editor . replaceRange ( newLineData [ 0 ], { line : lineNumber , ch : 0 }, { line : lineNumber , ch : editor . getLine ( lineNumber ). length });
editor . setSelection ({ line : lineNumber , ch : newLineData [ 1 ] });
return ;
}
let selection = editor . listSelections ()[ 0 ];
let begin = selection . anchor . line ;
let end = selection . head . line ;
if ( begin > end ) {
let temp = begin ;
begin = end ;
end = temp ;
}
let new_lines = "" ;
for ( let i = begin ; i <= end ; i ++ ) {
if ( i != begin )
new_lines += "\n" ;
new_lines += preFormatOneLine ( ctx , editor , i + 1 )[ 0 ];
}
editor . replaceRange ( new_lines , { line : begin , ch : 0 }, { line : end , ch : editor . getLine ( end ). length });
if ( selection . anchor . line < selection . head . line ) {
editor . setSelection ({ line : selection . anchor . line , ch : 0 }, { line : selection . head . line , ch : editor . getLine ( selection . head . line ). length });
} else {
editor . setSelection ({ line : selection . anchor . line , ch : editor . getLine ( selection . anchor . line ). length }, { line : selection . head . line , ch : 0 });
}
}
function preFormatOneLine ( ctx , editor , lineNumber , ch = - 1 ) {
const editorView = editor . cm ;
let state = editorView . state ;
let line = state . doc . line ( lineNumber );
let newLine = line . text ;
let newCh = 0 ;
let curCh = line . text . length ;
if ( ch != - 1 ) {
curCh = ch ;
}
const lineType = getPosLineType ( state , line . from );
if ( lineType == "text" /* text */ || lineType == "table" /* table */ ) {
let newLineData = ctx . Formater . formatLine ( state , lineNumber , { ... ctx . settings , AutoCapital : false }, curCh , 0 );
newLine = newLineData [ 0 ];
newCh = newLineData [ 1 ];
}
return [ newLine , newCh ];
}
function deleteBlankLines ( ctx , editor ) {
var _a ;
if (( _a = ctx . settings ) == null ? void 0 : _a . debug ) {
console . log ( "config.strictLineBreaks" , ctx . app . vault . getConfig ( "strictLineBreaks" ));
}
let strictLineBreaks = ctx . app . vault . config . strictLineBreaks || false ;
const editorView = editor . cm ;
let state = editorView . state ;
let doc = state . doc ;
const RE_BLANK = /^\s*$/ ;
const RE_LIST = /^\s*(?:[-*+]|\d+[.)]) / ;
const RE_QUOTE = /^\s*>/ ;
const RE_BLOCKID = /\s\^[\w-]+\s*$/ ;
const RE_HR = /^\s*(?:---+|\*\*\*+|___+)\s*$/ ;
const getTrailingBlankType = ( text ) => {
if ( RE_LIST . test ( text ))
return "list" ;
if ( RE_QUOTE . test ( text ))
return "quote" ;
if ( RE_BLOCKID . test ( text ))
return "blockid" ;
return null ;
};
const needsTrailingBlank = ( text ) => getTrailingBlankType ( text ) !== null ;
let start_line = 1 ;
let end_line = doc . lines ;
let line_num = doc . lines ;
const selected = editor . somethingSelected () && editor . getSelection () != "" ;
if ( selected ) {
let selection = editor . listSelections ()[ 0 ];
let begin = selection . anchor . line + 1 ;
let end = selection . head . line + 1 ;
if ( begin > end ) {
let temp = begin ;
begin = end ;
end = temp ;
}
start_line = begin ;
end_line = end ;
}
let delete_index = [];
let remain_next_blank = false ;
let remain_next_blank_type = null ;
let consecutiveBlanks = 0 ;
if ( start_line != 1 ) {
const prevText = doc . line ( start_line - 1 ). text ;
const prevType = getTrailingBlankType ( prevText );
if ( prevType ) {
remain_next_blank = true ;
remain_next_blank_type = prevType ;
}
}
if ( end_line != line_num && ! RE_BLANK . test ( doc . line ( end_line + 1 ). text )) {
end_line += 1 ;
}
for ( let i = start_line ; i <= end_line ; i ++ ) {
let line = doc . line ( i );
let text = line . text ;
if ( RE_BLANK . test ( text )) {
consecutiveBlanks ++ ;
if ( remain_next_blank ) {
let nextNonBlankType = null ;
for ( let j = i + 1 ; j <= end_line ; j ++ ) {
const jText = doc . line ( j ). text ;
if ( ! RE_BLANK . test ( jText )) {
nextNonBlankType = getTrailingBlankType ( jText );
break ;
}
}
if ( remain_next_blank_type && nextNonBlankType === remain_next_blank_type ) {
delete_index . push ( i );
}
remain_next_blank = false ;
remain_next_blank_type = null ;
continue ;
}
if ( strictLineBreaks && consecutiveBlanks === 1 ) {
continue ;
}
delete_index . push ( i );
continue ;
}
consecutiveBlanks = 0 ;
if ( RE_HR . test ( text ) && delete_index [ delete_index . length - 1 ] == i - 1 ) {
delete_index . pop ();
} else if ( needsTrailingBlank ( text )) {
remain_next_blank = true ;
remain_next_blank_type = getTrailingBlankType ( text );
} else {
remain_next_blank = false ;
remain_next_blank_type = null ;
}
}
let newContent = "" ;
for ( let i = 1 ; i < line_num ; i ++ ) {
if ( ! delete_index . contains ( i )) {
newContent += doc . line ( i ). text + "\n" ;
}
}
if ( ! delete_index . contains ( line_num )) {
newContent += doc . line ( line_num ). text ;
}
editor . setValue ( newContent );
}
function switchAutoFormatting ( ctx ) {
ctx . settings . AutoFormat = ! ctx . settings . AutoFormat ;
let status = ctx . settings . AutoFormat ? "on" : "off" ;
new import_obsidian6 . Notice ( "EasyTyping: Autoformat is " + status + "!" );
}
function convert2CodeBlock ( ctx , editor ) {
var _a ;
if (( _a = ctx . settings ) == null ? void 0 : _a . debug )
console . log ( "----- EasyTyping: insert code block-----" );
if ( editor . somethingSelected && editor . getSelection () != "" ) {
let selected = editor . getSelection ();
let selectedRange = editor . listSelections ()[ 0 ];
let anchor = selectedRange . anchor ;
let head = selectedRange . head ;
let replacement = "```\n" + selected + "\n```" ;
if ( anchor . line > head . line || anchor . line == head . line && anchor . ch > head . ch ) {
let temp = anchor ;
anchor = head ;
head = temp ;
}
let dstLine = anchor . line ;
if ( anchor . ch != 0 ) {
replacement = "\n" + replacement ;
dstLine += 1 ;
}
if ( head . ch != editor . getLine ( head . line ). length ) {
replacement = replacement + "\n" ;
}
editor . replaceSelection ( replacement );
editor . setCursor ({ line : dstLine , ch : 3 });
} else {
let cs = editor . getCursor ();
let replace = "```\n```" ;
let dstLine = cs . line ;
if ( cs . ch != 0 ) {
replace = "\n" + replace ;
dstLine += 1 ;
}
if ( cs . ch != editor . getLine ( cs . line ). length ) {
replace = replace + "\n" ;
}
editor . replaceRange ( replace , cs );
editor . setCursor ({ line : dstLine , ch : 3 });
}
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
// src/keyboard_handlers.ts
var import_language4 = require ( "@codemirror/language" );
var import_obsidian7 = require ( "obsidian" );
2026-01-05 13:03:55 +08:00
// src/tabstop.ts
2026-08-21 15:44:03 +08:00
var import_state4 = require ( "@codemirror/state" );
var import_view3 = require ( "@codemirror/view" );
2026-01-05 13:03:55 +08:00
var TABSTOP_DECO_CLASS = "easy-typing-tabstops" ;
var CURSOR_WIDGET_CLASS = "easy-typing-cursor-widget" ;
function getMarkerDecoration ( from , to ) {
const className = ` ${ TABSTOP_DECO_CLASS } ` ;
if ( from == to ) {
2026-08-21 15:44:03 +08:00
return import_view3 . Decoration . widget ({
2026-01-05 13:03:55 +08:00
widget : new CursorWidget (),
side : 0
}). range ( from );
}
2026-08-21 15:44:03 +08:00
return import_view3 . Decoration . mark ({
2026-01-05 13:03:55 +08:00
inclusive : true ,
class : className
}). range ( from , to );
}
var TabstopGroup = class {
constructor ( tabstopSpecs ) {
const decos = tabstopSpecs . map (( spec ) => getMarkerDecoration ( spec . from , spec . to ));
2026-08-21 15:44:03 +08:00
this . selections = tabstopSpecs . map (( spec ) => import_state4 . EditorSelection . range ( spec . from , spec . to ));
this . decos = import_view3 . Decoration . set ( decos , true );
2026-01-05 13:03:55 +08:00
}
select ( view , selectEndpoints ) {
const sel = this . toEditorSelection ();
const toSelect = selectEndpoints ? getEditorSelectionEndpoints ( sel ) : sel ;
view . dispatch ({
selection : toSelect
});
}
toSelectionRanges () {
return this . selections ;
}
toEditorSelection () {
2026-08-21 15:44:03 +08:00
return import_state4 . EditorSelection . create ( this . toSelectionRanges ());
2026-01-05 13:03:55 +08:00
}
containsSelection ( selection ) {
function rangeLiesWithinSelection ( range , sel ) {
for ( const selRange of sel ) {
if ( selRange . from <= range . from && selRange . to >= range . to ) {
return true ;
}
}
return false ;
}
const tabstopRanges = this . toSelectionRanges ();
let result = true ;
for ( const range of selection . ranges ) {
if ( ! rangeLiesWithinSelection ( range , tabstopRanges )) {
result = false ;
break ;
}
}
return result ;
}
map ( changes ) {
this . decos = this . decos . map ( changes );
this . selections = this . selections . map (( range ) => {
let rangeFrom = changes . mapPos ( range . from , - 1 );
let rangeTo = changes . mapPos ( range . to , 1 );
2026-08-21 15:44:03 +08:00
return import_state4 . EditorSelection . range ( rangeFrom , rangeTo );
2026-01-05 13:03:55 +08:00
});
}
getDecoRanges () {
const ranges = [];
const cur = this . decos . iter ();
while ( cur . value != null ) {
if ( cur . from != cur . to ) {
ranges . push ( cur . value . range ( cur . from , cur . to ));
} else {
ranges . push ( cur . value . range ( cur . from ));
}
cur . next ();
}
return ranges ;
}
};
function tabstopSpecsToTabstopGroups ( tabstops ) {
const tabstopsByNumber = {};
for ( const tabstop of tabstops ) {
const n = String ( tabstop . number );
if ( tabstopsByNumber [ n ]) {
tabstopsByNumber [ n ]. push ( tabstop );
} else {
tabstopsByNumber [ n ] = [ tabstop ];
}
}
const result = [];
const numbers = Object . keys ( tabstopsByNumber );
numbers . sort (( a , b ) => parseInt ( a ) - parseInt ( b ));
for ( const number of numbers ) {
const grp = new TabstopGroup ( tabstopsByNumber [ number ]);
result . push ( grp );
}
return result ;
}
function getEditorSelectionEndpoints ( sel ) {
2026-08-21 15:44:03 +08:00
const endpoints = sel . ranges . map (( range ) => import_state4 . EditorSelection . range ( range . to , range . to ));
return import_state4 . EditorSelection . create ( endpoints );
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
var CursorWidget = class extends import_view3 . WidgetType {
2026-01-05 13:03:55 +08:00
eq ( widget ) {
return true ;
}
toDOM ( view ) {
const cursorEl = document . createElement ( "span" );
cursorEl . className = ` ${ CURSOR_WIDGET_CLASS } ` ;
cursorEl . textContent = "" ;
return cursorEl ;
}
};
2026-08-21 15:44:03 +08:00
// src/rule_processor.ts
function triggerCvtRule ( ctx , view , cursor_pos , changeType = "input.type" ) {
var _a , _b , _c ;
const inputScope = detectRuleScope ( view . state , cursor_pos );
const cvtCtx = {
kind : "input" /* Input */ ,
docText : view . state . doc . toString (),
selection : { from : cursor_pos , to : cursor_pos },
inserted : "" ,
changeType ,
scopeHint : inputScope . scope ,
scopeLanguage : inputScope . language ,
debug : ( _a = ctx . settings ) == null ? void 0 : _a . debug
};
if ((( _b = ctx . settings ) == null ? void 0 : _b . UserDefinedRegSwitch ) && (( _c = ctx . settings ) == null ? void 0 : _c . UserRulesRespectUserDefinedRegexBlocks )) {
const line = view . state . doc . lineAt ( cursor_pos );
const column = cursor_pos - line . from ;
const checkColumn = changeType . startsWith ( "input" ) ? Math . max ( 0 , column - 1 ) : column ;
if ( isCursorInUserDefinedRegexBlock ( line . text , checkColumn , ctx . settings . UserDefinedRegExp )) {
return false ;
}
}
const cvtResult = ctx . ruleEngine . process ( cvtCtx );
if ( cvtResult ) {
const tabstopGroups = tabstopSpecsToTabstopGroups ( cvtResult . tabstops );
if ( tabstopGroups . length > 0 ) {
view . dispatch ({
changes : {
from : cvtResult . matchRange . from ,
to : cvtResult . matchRange . to ,
insert : cvtResult . newText
},
selection : tabstopGroups [ 0 ]. toEditorSelection (),
effects : [ addTabstopsEffect . of ( tabstopGroups )],
userEvent : "EasyTyping.change"
});
} else {
view . dispatch ({
changes : {
from : cvtResult . matchRange . from ,
to : cvtResult . matchRange . to ,
insert : cvtResult . newText
},
selection : { anchor : cvtResult . cursor },
userEvent : "EasyTyping.change"
});
}
return true ;
}
return false ;
}
// src/keyboard_handlers.ts
function tabTabstopJump ( view ) {
if ( consumeAndGotoNextTabstop ( view )) {
return true ;
}
return false ;
}
function tabTriggerRule ( ctx , view ) {
const sel = view . state . selection ;
if ( sel . ranges . length === 1 && sel . main . from === sel . main . to ) {
if ( triggerCvtRule ( ctx , view , sel . main . to , "tab" ))
return true ;
}
return false ;
}
function tabCodeBlockIndent ( ctx , view ) {
if ( ! ctx . settings . Tabout )
return false ;
const state = view . state ;
const s = view . state . selection ;
if ( s . ranges . length > 1 )
return false ;
const pos = s . main . to ;
if ( s . main . from == s . main . to && isCodeBlockInPos ( state , pos )) {
const default_indent = ctx . getDefaultIndentChar ();
view . dispatch ({
changes : {
from : s . main . from ,
insert : default_indent
},
selection : {
anchor : s . main . from + default_indent . length
}
});
return true ;
}
return false ;
}
function tabInlineCodeEscape ( ctx , view ) {
if ( ! ctx . settings . Tabout )
return false ;
if ( ! ctx . settings . BetterCodeEdit )
return false ;
const state = view . state ;
const doc = state . doc ;
const tree = ( 0 , import_language4 . syntaxTree )( state );
const s = view . state . selection ;
if ( s . ranges . length > 1 )
return false ;
const pos = s . main . to ;
const line = doc . lineAt ( pos );
if ( pos - line . from != 0 && tree . resolve ( pos - 1 , 1 ). name . contains ( "inline-code" )) {
if ( tree . resolve ( pos , 1 ). name . contains ( "formatting-code_inline-code" )) {
view . dispatch ({
selection : { anchor : pos + 1 , head : pos + 1 }
});
return true ;
}
for ( let p = pos + 1 ; p < line . to && tree . resolve ( p , 1 ). name . contains ( "inline-code" ); p += 1 ) {
if ( tree . resolve ( p , 1 ). name . contains ( "formatting-code_inline-code" )) {
view . dispatch ({
selection : { anchor : p , head : p }
});
return true ;
}
if ( p == line . to - 1 && tree . resolve ( p , 1 ). name . contains ( "inline-code" )) {
view . dispatch ({
selection : { anchor : p + 1 , head : p + 1 }
});
return true ;
}
}
}
return false ;
}
function tabPairStringTabout ( ctx , view ) {
if ( ! ctx . settings . Tabout )
return false ;
const state = view . state ;
const doc = state . doc ;
const s = view . state . selection ;
if ( s . ranges . length > 1 )
return false ;
const pos = s . main . to ;
const line = doc . lineAt ( pos );
let selection = view . state . selection . asSingle (). main ;
let selected = selection . anchor != selection . head ;
if ( selected ) {
let new_anchor = selection . anchor < selection . head ? selection . anchor : selection . head ;
let new_head = selection . anchor > selection . head ? selection . anchor : selection . head ;
for ( let pstr of ctx . TaboutPairStrs ) {
if ( doc . sliceString ( new_anchor - pstr . left . length , new_anchor ) == pstr . left && doc . sliceString ( new_head , new_head + pstr . right . length ) == pstr . right ) {
view . dispatch ({
selection : { anchor : new_head + pstr . right . length , head : new_head + pstr . right . length }
});
return true ;
}
}
} else {
let taboutRes = taboutCursorInPairedString ( line . text , pos - line . from , ctx . TaboutPairStrs );
if ( taboutRes . isSuccess ) {
view . dispatch ({
selection : { anchor : taboutRes . newPosition + line . from }
});
return true ;
}
}
return false ;
}
function handleTabDown ( ctx , view ) {
return tabTabstopJump ( view ) || tabTriggerRule ( ctx , view ) || tabCodeBlockIndent ( ctx , view ) || tabInlineCodeEscape ( ctx , view ) || tabPairStringTabout ( ctx , view );
}
function enterCollapsedHeading ( ctx , view ) {
var _a ;
if ( ! ctx . settings . CollapsePersistentEnter )
return false ;
const state = view . state ;
const doc = state . doc ;
const s = view . state . selection ;
const pos = s . main . to ;
const editor = ctx . app . workspace . getActiveViewOfType ( import_obsidian7 . MarkdownView ). editor ;
let fold_offsets = editor . getFoldOffsets ();
let all_foldable_lines = editor . getAllFoldableLines ();
let folded_lines = [];
for ( let offset of fold_offsets ) {
let folded = all_foldable_lines . find (( l ) => l . from == offset );
if ( folded ) {
folded_lines . push ( folded );
}
}
let folded_line = folded_lines . find (( l ) => pos >= l . from && pos <= l . to );
if ( folded_line ) {
let folded_first_line = doc . lineAt ( folded_line . from ). text ;
let reg_headings = /^#+ / ;
if ( reg_headings . test ( folded_first_line )) {
let heading_level = ( _a = folded_first_line . match ( /^#+/ )) == null ? void 0 : _a [ 0 ]. length ;
let new_heading_level = heading_level ;
let new_heading_line = "\n" + "#" . repeat ( new_heading_level ) + " " ;
let folded_last_line = doc . lineAt ( folded_line . to ). text ;
let folded_last_line_is_blank = /^\s*$/ . test ( folded_last_line );
let new_heading_line_pos = editor . offsetToPos ( folded_line . to );
let new_cursor_pos = { line : new_heading_line_pos . line + 1 , ch : new_heading_level + 1 };
if ( ctx . settings . StrictModeEnter && ! folded_last_line_is_blank && ( ctx . app . vault . config . strictLineBreaks || false )) {
new_heading_line = "\n\n" + "#" . repeat ( new_heading_level ) + " " ;
new_cursor_pos = { line : new_heading_line_pos . line + 2 , ch : new_heading_level + 1 };
}
editor . replaceRange ( new_heading_line , new_heading_line_pos );
editor . setCursor ( editor . offsetToPos ( folded_line . from ));
editor . exec ( "toggleFold" );
editor . setCursor ( new_cursor_pos );
return true ;
}
}
return false ;
}
function enterCodeBlockIndent ( ctx , view ) {
var _a ;
if ( ! ctx . settings . BetterCodeEdit )
return false ;
const state = view . state ;
const doc = state . doc ;
const s = view . state . selection ;
const pos = s . main . to ;
const line = doc . lineAt ( pos );
const codeBlockInfo = getCodeBlockInfoInPos ( state , pos );
if ( codeBlockInfo && codeBlockInfo . code_start_pos !== doc . lineAt ( codeBlockInfo . start_pos ). to && pos >= codeBlockInfo . code_start_pos && pos <= codeBlockInfo . code_end_pos ) {
let line_indent_str = (( _a = line . text . match ( /^\s*/ )) == null ? void 0 : _a [ 0 ]) || "" ;
view . dispatch ({
changes : { from : pos , to : pos , insert : "\n" + line_indent_str },
selection : { anchor : pos + line_indent_str . length + 1 , head : pos + line_indent_str . length + 1 },
userEvent : "EasyTyping.handleEnter"
});
return true ;
}
return false ;
}
function enterStrictLineBreak ( ctx , view ) {
if ( ! ctx . settings . StrictModeEnter )
return false ;
let strictLineBreaks = ctx . app . vault . config . strictLineBreaks || false ;
if ( ! strictLineBreaks )
return false ;
const state = view . state ;
const doc = state . doc ;
const s = view . state . selection ;
const pos = s . main . to ;
const line = doc . lineAt ( pos );
const codeBlockInfo = getCodeBlockInfoInPos ( state , pos );
const lineType = getPosLineType2 ( state , pos );
if ( /^\s*$/ . test ( line . text ))
return false ;
if ( pos == line . from )
return false ;
if ( lineType == "quote" /* quote */ ) {
let reg_quote = /^(\s*)(>+ ?)/ ;
let quote_match = line . text . match ( reg_quote );
if ( ! quote_match )
return false ;
let quote_content = line . text . slice ( quote_match [ 0 ]. length );
if ( quote_content . trim () == "" )
return false ;
else {
let space_str2 = " " ;
if ( quote_content . endsWith ( " " ))
space_str2 = "" ;
let inserted_str = space_str2 + "\n" + quote_match [ 0 ];
if ( ctx . settings . StrictLineMode == "enter_twice" /* EnterTwice */ ) {
inserted_str = "\n" + quote_match [ 0 ] + "\n" + quote_match [ 0 ];
}
view . dispatch ({
changes : { from : pos , to : pos , insert : inserted_str },
selection : { anchor : pos + inserted_str . length },
userEvent : "EasyTyping.handleEnter"
});
return true ;
}
}
let space_str = " " ;
if ( line . text . endsWith ( " " ))
space_str = "" ;
if ( line . number < doc . lines && ! /^\s*$/ . test ( doc . line ( line . number + 1 ). text )) {
if ( ctx . settings . StrictLineMode != "two_space" /* TwoSpace */ )
return false ;
}
if ( ctx . settings . StrictLineMode == "two_space" /* TwoSpace */ && lineType == "text" /* text */ ) {
let inserted_str = space_str + "\n" ;
view . dispatch ({
changes : { from : pos , to : pos , insert : inserted_str },
selection : { anchor : pos + inserted_str . length , head : pos + inserted_str . length },
userEvent : "EasyTyping.handleEnter"
});
return true ;
}
if ( lineType == "text" /* text */ || codeBlockInfo && pos == codeBlockInfo . end_pos && codeBlockInfo . indent == 0 ) {
view . dispatch ({
changes : {
from : pos ,
to : pos ,
insert : "\n\n"
},
selection : { anchor : pos + 2 },
userEvent : "EasyTyping.handleEnter"
});
return true ;
}
return false ;
}
function handleEnter ( ctx , view ) {
const s = view . state . selection ;
if ( s . ranges . length > 1 )
return false ;
return enterCollapsedHeading ( ctx , view ) || enterCodeBlockIndent ( ctx , view ) || enterStrictLineBreak ( ctx , view );
}
function backspaceEmptyQuote ( view , state , doc , line , lineContent , quoteMatchEmpty ) {
let changes = [];
let newCursorPos ;
const quote_indent_str = quoteMatchEmpty [ 1 ];
const quoteLevel = quoteMatchEmpty [ 2 ]. length ;
if ( quoteLevel > 1 ) {
if ( line . number > 1 ) {
const prevLine = doc . line ( line . number - 1 );
const prevLineContent = prevLine . text ;
const prevQuoteMatchEmpty = prevLineContent . match ( /^(\s*)(>+) ?$/ );
if ( prevQuoteMatchEmpty && prevQuoteMatchEmpty [ 1 ] == quote_indent_str && prevQuoteMatchEmpty [ 2 ]. length == quoteLevel ) {
let temp_line = quote_indent_str + ">" . repeat ( quoteLevel - 1 ) + " " ;
let inseted = temp_line + "\n" + temp_line ;
changes = [{ from : prevLine . from , to : line . to , insert : inseted }];
newCursorPos = prevLine . from + inseted . length ;
} else {
const newQuotePrefix = ">" . repeat ( quoteLevel - 1 ) + " " ;
changes = [{ from : line . from , to : line . to , insert : newQuotePrefix }];
newCursorPos = line . from + newQuotePrefix . length ;
}
} else {
const newQuotePrefix = ">" . repeat ( quoteLevel - 1 ) + " " ;
changes = [{ from : line . from , to : line . to , insert : newQuotePrefix }];
newCursorPos = line . from + newQuotePrefix . length ;
}
} else {
if ( line . number > 1 ) {
const prevLine = doc . line ( line . number - 1 );
const prevLineContent = prevLine . text ;
const prevQuoteMatch = prevLineContent . match ( /^\s*(>+)/ );
if ( prevQuoteMatch ) {
changes = [{ from : prevLine . to , to : line . to , insert : "" }];
newCursorPos = prevLine . to ;
} else {
changes = [{ from : line . from , to : line . to , insert : "" }];
newCursorPos = line . from ;
}
} else {
changes = [{ from : line . from , to : line . to , insert : "" }];
newCursorPos = line . from ;
}
}
return { changes , newCursorPos };
}
function backspaceEmptyListItem ( view , state , doc , line , lineContent ) {
let changes = [];
let newCursorPos ;
if ( line . number > 1 ) {
const prevLine = doc . line ( line . number - 1 );
const prevLineContent = prevLine . text ;
const prevListMatch = prevLineContent . match ( /^\s*([-*+]|\d+\.)\s/ );
if ( prevListMatch ) {
changes = [{ from : prevLine . to , to : line . to , insert : "" }];
newCursorPos = prevLine . to ;
} else {
changes = [{ from : line . from , to : line . to , insert : "" }];
newCursorPos = line . from ;
}
} else {
changes = [{ from : line . from , to : line . to , insert : "" }];
newCursorPos = line . from ;
}
let nextLineNumber = line . number + 1 ;
const currentIndent = lineContent . match ( /^\s*/ )[ 0 ];
const currentListMatch = lineContent . match ( /^\s*(\d+)\.\s/ );
let expectedNextNumber = currentListMatch ? parseInt ( currentListMatch [ 1 ], 10 ) + 1 : null ;
while ( nextLineNumber <= doc . lines && expectedNextNumber !== null ) {
const nextLine = doc . line ( nextLineNumber );
const nextLineContent = nextLine . text ;
const nextListMatch = nextLineContent . match ( /^\s*(\d+)\.\s/ );
if ( nextListMatch ) {
const nextIndent = nextLineContent . match ( /^\s*/ )[ 0 ];
if ( nextIndent !== currentIndent ) {
break ;
}
const nextListNumber = parseInt ( nextListMatch [ 1 ], 10 );
if ( nextListNumber === expectedNextNumber ) {
const newNextLineContent = nextLineContent . replace ( /^\s*\d+\.\s/ , ` ${ nextIndent }${ nextListNumber - 1 } . ` );
changes . push ({ from : nextLine . from , to : nextLine . to , insert : newNextLineContent });
expectedNextNumber ++ ;
} else {
break ;
}
} else {
break ;
}
nextLineNumber ++ ;
}
return { changes , newCursorPos };
}
function handleBackspace ( view ) {
const state = view . state ;
const doc = state . doc ;
const selection = state . selection . main ;
if ( selection . anchor != selection . head )
return false ;
const line = doc . lineAt ( selection . from );
const lineContent = line . text ;
const listMatchEmpty = lineContent . match ( /^\s*([-*+]|\d+\.) $/ );
const quoteMatchEmpty = lineContent . match ( /^(\s*)(>+) ?$/ );
if (( listMatchEmpty || quoteMatchEmpty ) && selection . anchor == line . to ) {
let result ;
if ( quoteMatchEmpty ) {
result = backspaceEmptyQuote ( view , state , doc , line , lineContent , quoteMatchEmpty );
} else {
result = backspaceEmptyListItem ( view , state , doc , line , lineContent );
}
const tr = state . update ({
changes : result . changes ,
selection : { anchor : result . newCursorPos , head : result . newCursorPos },
userEvent : "EasyTyping.handleBackspace"
});
view . dispatch ( tr );
return true ;
}
return false ;
}
function handleShiftEnter ( ctx , view ) {
const state = view . state ;
const doc = state . doc ;
const selection = state . selection . main ;
if ( selection . anchor != selection . head )
return false ;
const line = doc . lineAt ( selection . head );
const lineContent = line . text ;
const taskListMatch = lineContent . match ( /^(\s*)([-*+] \[.\])\s/ );
if ( taskListMatch ) {
const [, indent , listMarker ] = taskListMatch ;
let inserted = "\n" + indent + " " ;
view . dispatch ({
changes : [{ from : selection . anchor , insert : inserted }],
selection : { anchor : selection . anchor + inserted . length , head : selection . anchor + inserted . length },
userEvent : "EasyTyping.handleShiftEnter"
});
return true ;
}
return false ;
}
function handleModA ( ctx , view ) {
var _a ;
let selection = view . state . selection . main ;
let line = view . state . doc . lineAt ( selection . anchor );
let line_type = getPosLineType2 ( view . state , selection . anchor );
let is_in_code_block = isCodeBlockInPos ( view . state , selection . anchor );
if ( ctx . settings . EnhanceModA && line_type == "text" /* text */ && ! is_in_code_block ) {
let [ block_start , block_end ] = getBlockLinesInPos ( ctx , view . state , selection . head );
if ( selection . anchor <= view . state . doc . line ( block_start ). from && selection . head >= view . state . doc . line ( block_end ). to ) {
return false ;
}
if ( selection . anchor == line . from && selection . head == line . to ) {
if ( block_start != block_end ) {
view . dispatch ({
selection : {
anchor : view . state . doc . line ( block_start ). from ,
head : view . state . doc . line ( block_end ). to
},
userEvent : "EasyTyping.handleModA"
});
return true ;
}
return false ;
}
view . dispatch ({
selection : { anchor : line . from , head : line . to },
userEvent : "EasyTyping.handleModA"
});
return true ;
}
let quote_info = getQuoteInfoInPos ( view . state , selection . head );
if ( ctx . settings . EnhanceModA && quote_info ) {
if ( selection . anchor == quote_info . start_pos && selection . head == quote_info . end_pos ) {
return false ;
} else if ( selection . anchor == quote_info . cur_start_pos && selection . head == quote_info . cur_end_pos ) {
view . dispatch ({
selection : { anchor : quote_info . start_pos , head : quote_info . end_pos },
userEvent : "EasyTyping.handleModA"
});
return true ;
} else {
view . dispatch ({
selection : { anchor : quote_info . cur_start_pos , head : quote_info . cur_end_pos },
userEvent : "EasyTyping.handleModA"
});
return true ;
}
}
if ( ctx . settings . EnhanceModA && line_type == "list" /* list */ ) {
const reg_list = /^(\s*)([-*+] \[[^\]]\]|[-*+]|\d+\.)\s/ ;
let reg_code_block = /^\s+```/ ;
const listMatch = line . text . match ( reg_list );
if ( ! listMatch ) {
if ( ! reg_code_block . test ( line . text )) {
let cur_indent = (( _a = line . text . match ( /^\s*/ )) == null ? void 0 : _a [ 0 ]. length ) || 0 ;
let selection_list = [];
selection_list . push ({ anchor : line . from + cur_indent , head : line . to });
let list_start_line = line . number ;
for ( let i = line . number - 1 ; i >= 1 ; i -- ) {
const prevLine = view . state . doc . line ( i );
if ( getPosLineType2 ( view . state , prevLine . from ) == "list" /* list */ ) {
list_start_line = i ;
break ;
}
}
let list_s_match = view . state . doc . line ( list_start_line ). text . match ( reg_list );
let list_s_start_idx = ( list_s_match == null ? void 0 : list_s_match [ 0 ]. length ) || 0 ;
selection_list . push ({ anchor : view . state . doc . line ( list_start_line ). from + list_s_start_idx , head : line . to });
if ( selection . anchor <= selection_list [ 0 ]. anchor && selection . head >= selection_list [ 0 ]. head ) {
view . dispatch ({ selection : selection_list [ 1 ], userEvent : "EasyTyping.handleModA" });
return true ;
} else {
view . dispatch ({ selection : selection_list [ 0 ], userEvent : "EasyTyping.handleModA" });
return true ;
}
}
} else {
const cur_indent = listMatch [ 1 ]. length ;
let selection_list = [];
const contentStart = line . from + listMatch [ 0 ]. length ;
selection_list . push ({ anchor : contentStart , head : line . to });
let endLine = line . number ;
for ( let i = line . number + 1 ; i <= view . state . doc . lines ; i ++ ) {
const nextLine = view . state . doc . line ( i );
const nextMatch = nextLine . text . match ( /^(\s*)/ );
if ( ! nextMatch || nextMatch [ 0 ]. length <= cur_indent )
break ;
endLine = i ;
}
let list_block_selection = { anchor : line . from , head : view . state . doc . line ( endLine ). to };
selection_list . push ( list_block_selection );
let list_start_line = line . number ;
for ( let i = line . number - 1 ; i >= 1 ; i -- ) {
const prevLine = view . state . doc . line ( i );
const prevMatch = prevLine . text . match ( /^(\s*)/ );
if ( getPosLineType2 ( view . state , prevLine . from ) == "list" /* list */ || prevMatch && prevMatch [ 0 ]. length >= 2 ) {
list_start_line = i ;
} else {
break ;
}
}
let list_end_line = line . number ;
for ( let i = line . number + 1 ; i <= view . state . doc . lines ; i ++ ) {
const nextLine = view . state . doc . line ( i );
const nextMatch = nextLine . text . match ( /^(\s*)/ );
if ( getPosLineType2 ( view . state , nextLine . from ) == "list" /* list */ || nextMatch && nextMatch [ 0 ]. length >= 2 ) {
list_end_line = i ;
} else {
break ;
}
}
let list_all_selection = { anchor : view . state . doc . line ( list_start_line ). from , head : view . state . doc . line ( list_end_line ). to };
if ( list_all_selection . anchor != list_block_selection . anchor || list_all_selection . head != list_block_selection . head ) {
selection_list . push ( list_all_selection );
}
selection_list . push ({ anchor : 0 , head : view . state . doc . length });
let hit_idx = - 1 ;
for ( let i = selection_list . length - 1 ; i >= 0 ; i -- ) {
const sel = selection_list [ i ];
if ( selection . anchor <= sel . anchor && selection . head >= sel . head ) {
hit_idx = i ;
break ;
}
}
hit_idx += 1 ;
if ( hit_idx < selection_list . length ) {
view . dispatch ({ selection : selection_list [ hit_idx ], userEvent : "EasyTyping.handleModA" });
return true ;
}
return false ;
}
}
if ( ! ctx . settings . BetterCodeEdit )
return false ;
let mainSelection = view . state . selection . asSingle (). main ;
return selectCodeBlockInPos ( view , mainSelection );
}
function goNewLineAfterCurLine ( ctx , view ) {
const state = view . state ;
const doc = state . doc ;
const selection = state . selection . main ;
const line = doc . lineAt ( selection . head );
const lineContent = line . text ;
if ( /^\s*$/ . test ( lineContent )) {
const insertStr2 = "\n" ;
view . dispatch ({
changes : { from : line . to , insert : insertStr2 },
selection : { anchor : line . to + insertStr2 . length },
userEvent : "EasyTyping.goNewLineAfterCurLine"
});
return true ;
}
const listMatch = lineContent . match ( /^(\s*)([-*+] \[.\]|[-*+]|\d+\.)\s/ );
const quoteMatch = lineContent . match ( /^(\s*)(>+ ?)/ );
let changes ;
let newCursorPos ;
let prefix = "" ;
if ( listMatch ) {
const [, indent , listMarker ] = listMatch ;
if ([ "-" , "*" , "+" ]. includes ( listMarker )) {
prefix = indent + listMarker + " " ;
} else if ( listMarker . match ( /[-*+] \[.\]/ )) {
prefix = indent + listMarker . replace ( /\[.\]/g , "[ ]" ) + " " ;
} else {
prefix = indent + ( parseInt ( listMarker ) + 1 ) + ". " ;
}
} else if ( quoteMatch ) {
prefix = quoteMatch [ 1 ] + quoteMatch [ 2 ];
}
const strictLineBreaks = ctx . app . vault . config . strictLineBreaks || false ;
let useStrictBreak = ctx . settings . StrictModeEnter && strictLineBreaks ;
if ( useStrictBreak ) {
const lineType = getPosLineType2 ( state , line . from );
if ( lineType === "codeblock" /* codeblock */ || lineType === "formula" /* formula */ || lineType === "code_block_start" /* code_start */ || lineType === "code_block_end" /* code_end */ ) {
useStrictBreak = false ;
}
}
let insertStr ;
if ( ! useStrictBreak ) {
insertStr = "\n" + prefix ;
} else {
const mode = ctx . settings . StrictLineMode ;
const spaceStr = lineContent . endsWith ( " " ) ? "" : " " ;
if ( listMatch ) {
insertStr = "\n" + prefix ;
} else if ( mode === "two_space" /* TwoSpace */ ) {
insertStr = spaceStr + "\n" + prefix ;
} else if ( quoteMatch ) {
if ( mode === "enter_twice" /* EnterTwice */ ) {
insertStr = "\n" + prefix + "\n" + prefix ;
} else {
insertStr = spaceStr + "\n" + prefix ;
}
} else {
insertStr = "\n\n" + prefix ;
}
}
changes = [{ from : line . to , insert : insertStr }];
newCursorPos = line . to + insertStr . length ;
const tr = state . update ({
changes ,
selection : { anchor : newCursorPos , head : newCursorPos },
userEvent : "EasyTyping.goNewLineAfterCurLine"
});
view . dispatch ( tr );
return true ;
}
function getBlockLinesInPos ( ctx , state , pos ) {
const strictLineBreaks = ctx . app . vault . config . strictLineBreaks || false ;
let line = state . doc . lineAt ( pos );
let block_start = line . number ;
let block_end = line . number ;
let reg_headings = /^#+ / ;
for ( let i = line . number - 1 ; i >= 1 ; i -- ) {
let line2 = state . doc . line ( i );
if ( getPosLineType2 ( state , line2 . from ) == "text" /* text */ && line2 . text !== "" && ! reg_headings . test ( line2 . text )) {
block_start = i ;
continue ;
}
break ;
}
for ( let i = line . number + 1 ; i <= state . doc . lines ; i ++ ) {
let line2 = state . doc . line ( i );
if ( getPosLineType2 ( state , line2 . from ) == "text" /* text */ && line2 . text !== "" && ! reg_headings . test ( line2 . text )) {
block_end = i ;
continue ;
}
break ;
}
return [ block_start , block_end ];
}
function selectBlockInCursor ( ctx , view ) {
let selection = view . state . selection . main ;
let line = view . state . doc . lineAt ( selection . head );
if ( /^\s*$/ . test ( line . text ))
return false ;
let [ block_start , block_end ] = getBlockLinesInPos ( ctx , view . state , selection . head );
view . dispatch ({
selection : { anchor : view . state . doc . line ( block_start ). from , head : view . state . doc . line ( block_end ). to },
userEvent : "EasyTyping.selectBlockInCursor"
});
return true ;
}
// src/cm_extensions.ts
var import_state5 = require ( "@codemirror/state" );
var import_obsidian8 = require ( "obsidian" );
var import_view4 = require ( "@codemirror/view" );
function createTransactionFilter ( ctx ) {
return import_state5 . EditorState . transactionFilter . of (( tr ) => {
const changes = [];
if ( ! tr . docChanged )
return tr ;
let selected = tr . startState . selection . asSingle (). main . anchor != tr . startState . selection . asSingle (). main . head ;
let changeTypeStr = getTypeStrOfTransac ( tr );
tr . changes . iterChanges (( fromA , toA , fromB , toB , inserted ) => {
var _a , _b , _c , _d ;
let changedStr = tr . startState . sliceDoc ( fromA , toA );
let changestr_ = changedStr . replace ( /\s/g , "0" );
let insertedStr = inserted . sliceString ( 0 );
if (( _a = ctx . settings ) == null ? void 0 : _a . debug ) {
console . log ( "[TransactionFilter] type, fromA, toA, changed, fromB, toB, inserted" );
console . log ( changeTypeStr , fromA , toA , changedStr , fromB , toB , insertedStr );
}
if ( getPosLineType ( tr . startState , fromA ) == "table" /* table */ )
return tr ;
if (( changeTypeStr == "input.type" || changeTypeStr == "input.type.compose" ) && fromA != toA && ( fromB + 1 === toB || insertedStr == "\u2014\u2014" || insertedStr == "\u2026\u2026" )) {
const selScope = detectRuleScope ( tr . startState , fromA );
const selCtx = {
kind : "selectKey" /* SelectKey */ ,
docText : tr . startState . doc . toString (),
selection : { from : fromA , to : toA },
inserted : insertedStr ,
changeType : changeTypeStr ,
scopeHint : selScope . scope ,
scopeLanguage : selScope . language ,
key : insertedStr ,
debug : ( _b = ctx . settings ) == null ? void 0 : _b . debug
};
const selResult = ctx . ruleEngine . process ( selCtx );
if ( selResult ) {
const tabstopGroups = tabstopSpecsToTabstopGroups ( selResult . tabstops );
if ( tabstopGroups . length > 0 ) {
changes . push ({
changes : {
from : selResult . matchRange . from ,
to : selResult . matchRange . to ,
insert : selResult . newText
},
selection : tabstopGroups [ 0 ]. toEditorSelection (),
effects : [ addTabstopsEffect . of ( tabstopGroups )],
userEvent : "EasyTyping.change"
});
} else {
changes . push ({
changes : {
from : selResult . matchRange . from ,
to : selResult . matchRange . to ,
insert : selResult . newText
},
selection : { anchor : selResult . cursor },
userEvent : "EasyTyping.change"
});
}
tr = tr . startState . update (... changes );
return tr ;
}
}
if ( ctx . settings . BetterCodeEdit && changeTypeStr . contains ( "paste" ) && fromA == fromB && isCodeBlockInPos ( tr . startState , fromA )) {
print ( "\u68C0\u6D4B\u5230\u5728\u4EE3\u7801\u5757\u4E2D\u7C98\u8D34" );
let line = tr . startState . doc . lineAt ( fromB ). text ;
let base_indent_num = ( _c = getCodeBlockInfoInPos ( tr . startState , fromA )) == null ? void 0 : _c . indent ;
let base_indent = base_indent_num == 0 ? "" : " " . repeat ( base_indent_num );
let inserted_lines = insertedStr . split ( "\n" );
if ( inserted_lines . length > 1 ) {
let min_indent_space = Infinity ;
for ( let line2 of inserted_lines ) {
if ( ! /^\s*$/ . test ( line2 )) {
let indent = line2 . match ( /^\s*/ )[ 0 ]. length ;
min_indent_space = Math . min ( min_indent_space , indent );
}
}
let adjusted_lines = inserted_lines . map (( line2 , index ) => {
let trimmed_line = line2 . substring ( min_indent_space );
trimmed_line = trimmed_line . replace ( /[\t]/g , ctx . getDefaultIndentChar ());
if ( index === 0 ) {
return trimmed_line ;
} else {
return base_indent + trimmed_line ;
}
});
let new_insertedStr = adjusted_lines . join ( "\n" );
changes . push ({
changes : { from : fromA , to : toA , insert : new_insertedStr },
selection : { anchor : fromA + new_insertedStr . length },
userEvent : "EasyTyping.change"
});
tr = tr . startState . update (... changes );
return tr ;
}
}
if ( ctx . settings . SmartPaste && changeTypeStr . contains ( "paste" ) && fromA == fromB && fromA == tr . startState . doc . lineAt ( toA ). to ) {
const lineContent = tr . startState . doc . lineAt ( toA ). text ;
const listMatch = lineContent . match ( /^(\s*)([-*+] \[.\]|[-*+]|\d+\.)\s/ );
const quoteMatch = lineContent . match ( /^(\s*)(>+)(\s)?/ );
if ( listMatch || quoteMatch ) {
let prefix = listMatch ? listMatch [ 1 ] + listMatch [ 2 ] + " " : quoteMatch [ 1 ] + quoteMatch [ 2 ] + " " ;
let indent_num = listMatch ? listMatch [ 1 ]. length : quoteMatch [ 1 ]. length ;
let indent_str = indent_num == 0 ? "" : " " . repeat ( indent_num );
let inserted_lines = insertedStr . split ( "\n" );
let min_indent_space = Infinity ;
for ( let line of inserted_lines ) {
if ( ! /^\s*$/ . test ( line )) {
let indent = line . match ( /^\s*/ )[ 0 ]. length ;
min_indent_space = Math . min ( min_indent_space , indent );
}
}
let paste_list = true ;
for ( let line of inserted_lines ) {
if ( line . match ( /^(\s*)([-*+] \[.\]|[-*+]|\d+\.)\s/ ) || /^\s*$/ . test ( line )) {
continue ;
} else {
let indent = line . match ( /^\s*/ )[ 0 ]. length ;
if ( indent < min_indent_space + 2 ) {
paste_list = false ;
break ;
}
}
}
let adjusted_lines = [];
if ( paste_list && listMatch ) {
adjusted_lines = inserted_lines . map (( line , index ) => {
let trimmed_line = line . substring ( min_indent_space );
trimmed_line = trimmed_line . replace ( /[\t]/g , ctx . getDefaultIndentChar ());
if ( index === 0 ) {
trimmed_line = trimmed_line . replace ( /^([-*+] \[.\]|[-*+]|\d+\.)\s/ , "" );
return trimmed_line ;
} else {
return indent_str + trimmed_line ;
}
});
} else {
adjusted_lines = inserted_lines . map (( line , index ) => {
let trimmed_line = line . substring ( min_indent_space );
trimmed_line = trimmed_line . replace ( /[\t]/g , ctx . getDefaultIndentChar ());
if ( index === 0 ) {
return trimmed_line ;
} else {
return prefix + trimmed_line ;
}
});
}
let new_insertedStr = adjusted_lines . join ( "\n" );
changes . push ({
changes : { from : fromA , to : toA , insert : new_insertedStr },
selection : { anchor : fromA + new_insertedStr . length },
userEvent : "EasyTyping.change"
});
tr = tr . startState . update (... changes );
return tr ;
}
}
if ( selected )
return tr ;
if ( ctx . settings . TryFixMSIME && changeTypeStr == "input.type.compose" && changedStr == "" && /^[\u4e00-\u9fa5]+$/ . test ( insertedStr )) {
print ( "MS-IME Compose detected:" , insertedStr );
tr = tr . startState . update (... changes );
return tr ;
}
let codeblockinfo = getCodeBlockInfoInPos ( tr . startState , toA );
if ( ctx . settings . BetterCodeEdit && changeTypeStr == "delete.backward" && ! selected && codeblockinfo && toA > tr . startState . doc . lineAt ( codeblockinfo . start_pos ). to ) {
let line_number = tr . startState . doc . lineAt ( toA ). number ;
let cur_line = tr . startState . doc . lineAt ( toA );
let list_code_indent = codeblockinfo . indent ;
if ( list_code_indent !== 0 ) {
print ( "list_code, indent: " , list_code_indent );
if ( toA == cur_line . from + list_code_indent ) {
changes . push ({
changes : {
from : tr . startState . doc . line ( line_number - 1 ). to ,
to : toA ,
insert : ""
},
userEvent : "EasyTyping.change"
});
tr = tr . startState . update (... changes );
return tr ;
}
if ( fromA >= cur_line . from && fromA < cur_line . from + list_code_indent && toA > cur_line . from + list_code_indent ) {
changes . push ({
changes : {
from : cur_line . from + list_code_indent ,
to : toA ,
insert : ""
},
userEvent : "EasyTyping.change"
});
tr = tr . startState . update (... changes );
return tr ;
}
}
}
if ( changeTypeStr === "delete.backward" ) {
const delScope = detectRuleScope ( tr . startState , toA );
const delCtx = {
kind : "delete" /* Delete */ ,
docText : tr . startState . doc . toString (),
selection : { from : toA , to : toA },
inserted : "" ,
changeType : changeTypeStr ,
scopeHint : delScope . scope ,
scopeLanguage : delScope . language ,
debug : ( _d = ctx . settings ) == null ? void 0 : _d . debug
};
const delResult = ctx . ruleEngine . process ( delCtx );
if ( delResult ) {
const tabstopGroups = tabstopSpecsToTabstopGroups ( delResult . tabstops );
if ( tabstopGroups . length > 0 ) {
changes . push ({
changes : {
from : delResult . matchRange . from ,
to : delResult . matchRange . to ,
insert : delResult . newText
},
selection : tabstopGroups [ 0 ]. toEditorSelection (),
effects : [ addTabstopsEffect . of ( tabstopGroups )],
userEvent : "EasyTyping.change"
});
} else {
changes . push ({
changes : {
from : delResult . matchRange . from ,
to : delResult . matchRange . to ,
insert : delResult . newText
},
selection : { anchor : delResult . cursor },
userEvent : "EasyTyping.change"
});
}
tr = tr . startState . update (... changes );
return tr ;
}
}
});
return tr ;
});
}
function tryProcessInput ( ctx , update , changeFrom , cursorPos , changeType = "input.type" ) {
const lineType = getPosLineType ( update . view . state , cursorPos );
if ( lineType === "table" /* table */ )
return false ;
if ( ! changeType . includes ( "paste" ) && changeType !== "unknown" && ! ctx . pasteDetected && triggerCvtRule ( ctx , update . view , cursorPos , changeType ))
return true ;
if ( ! ctx . settings . AutoFormat || isCurrentFileExclude ( ctx ))
return false ;
if ( lineType !== "text" /* text */ )
return false ;
if ( changeType . includes ( "paste" ) || changeType === "unknown" || ctx . pasteDetected )
return false ;
const insertedStr = update . view . state . doc . sliceString ( changeFrom , cursorPos );
const changes = ctx . Formater . formatLineOfDoc ( update . state , ctx . settings , changeFrom , cursorPos , insertedStr );
if ( changes ) {
const allSpecs = changes [ 0 ];
if ( allSpecs . length > 0 ) {
allSpecs [ allSpecs . length - 1 ] = {
... allSpecs [ allSpecs . length - 1 ],
... changes [ 1 ]
};
}
update . view . dispatch (... allSpecs );
return true ;
}
return false ;
}
function createViewUpdatePlugin ( ctx ) {
return import_view4 . EditorView . updateListener . of (( update ) => {
var _a ;
if ( ctx . onFormatArticle )
return ;
if ( hasTabstops ( update . view )) {
const cursor_changed = update . transactions . some (( tr2 ) => tr2 . selection );
if (( update . docChanged || cursor_changed ) && ! update . view . composing && ! isInsideCurTabstop ( update . view )) {
removeAllTabstops ( update . view );
}
if ( update . transactions . some (( tr2 ) => tr2 . isUserEvent ( "undo" ))) {
removeAllTabstops ( update . view );
}
}
const inTable = getPosLineType ( update . view . state , update . view . state . selection . asSingle (). main . anchor ) === "table" /* table */ ;
if ( inTable )
return ;
if ( update . view . composing ) {
if ( update . docChanged ) {
let tr2 = update . transactions [ 0 ];
tr2 . changes . iterChanges (( fromA2 ) => {
if ( ! ctx . compose_need_handle ) {
ctx . compose_need_handle = true ;
ctx . compose_begin_pos = fromA2 ;
}
ctx . compose_end_pos = update . view . state . selection . asSingle (). main . anchor ;
});
}
return ;
}
if ( ctx . compose_need_handle ) {
ctx . compose_need_handle = false ;
const cursor2 = update . view . state . selection . asSingle (). main ;
if ( cursor2 . head === cursor2 . anchor && cursor2 . anchor > ctx . compose_begin_pos ) {
if ( tryProcessInput ( ctx , update , ctx . compose_begin_pos , cursor2 . anchor ))
return ;
}
}
if ( ! update . docChanged )
return ;
const tr = update . transactions [ 0 ];
const changeType = getTypeStrOfTransac ( tr );
let fromA = 0 , toA = 0 , fromB = 0 , toB = 0 , insertedStr = "" , changedStr = "" ;
tr . changes . iterChanges (( _fromA , _toA , _fromB , _toB , inserted ) => {
fromA = _fromA ;
toA = _toA ;
fromB = _fromB ;
toB = _toB ;
insertedStr = inserted . sliceString ( 0 );
changedStr = tr . startState . doc . sliceString ( _fromA , _toA );
});
if (( _a = ctx . settings ) == null ? void 0 : _a . debug ) {
console . log ( "[ViewUpdate] type, fromA, toA, changed, fromB, toB, inserted" );
console . log ( changeType , fromA , toA , changedStr , fromB , toB , insertedStr );
}
if ( getPosLineType ( update . view . state , fromB ) === "table" /* table */ )
return ;
if ( changeType . includes ( "EasyTyping" ) || changeType === "undo" || changeType === "redo" )
return ;
const cursor = update . view . state . selection . asSingle (). main ;
const notSelected = cursor . anchor === cursor . head ;
if ( notSelected && changedStr . length < 1 && ! changeType . includes ( "delete" )) {
if ( tryProcessInput ( ctx , update , fromB , cursor . anchor , changeType ))
return ;
}
const isPaste = changeType . contains ( "paste" ) || ctx . pasteDetected ;
const isFormattedPaste = isPaste && ! ctx . plainPasteInProgress ;
const isPlainPaste = isPaste && ctx . plainPasteInProgress ;
if ( isPlainPaste )
ctx . plainPasteInProgress = false ;
const isExcludeFile = isCurrentFileExclude ( ctx );
if ( ctx . settings . AutoFormat && ctx . settings . AutoFormatPaste && ! isExcludeFile && isFormattedPaste && ! import_obsidian8 . Platform . isIosApp ) {
let updateLineStart = update . state . doc . lineAt ( fromB ). number ;
let updateLineEnd = update . state . doc . lineAt ( toB ). number ;
if ( updateLineStart === updateLineEnd && getPosLineType ( update . view . state , toB ) === "text" /* text */ ) {
let changes = ctx . Formater . formatLineOfDoc ( update . state , { ... ctx . settings , AutoCapital : false }, fromB , toB , insertedStr );
if ( changes ) {
update . view . dispatch (... changes [ 0 ]);
return ;
}
} else {
let all_changes = [];
let inserted_array = insertedStr . split ( "\n" );
let update_start = fromB ;
for ( let i = updateLineStart ; i <= updateLineEnd ; i ++ ) {
let real_inserted = inserted_array [ i - updateLineStart ];
let changes = ctx . Formater . formatLineOfDoc ( update . state , { ... ctx . settings , AutoCapital : false }, update_start , update_start + real_inserted . length , real_inserted );
if ( changes ) {
all_changes . push (... changes [ 0 ]);
}
update_start += real_inserted . length + 1 ;
}
if ( all_changes . length > 0 ) {
update . view . dispatch (... all_changes );
return ;
}
}
}
});
}
2026-01-05 13:03:55 +08:00
// src/main.ts
2026-08-21 15:44:03 +08:00
var EasyTypingPlugin = class extends import_obsidian9 . Plugin {
2026-01-05 13:03:55 +08:00
constructor () {
super (... arguments );
2026-08-21 15:44:03 +08:00
this . pasteTimerId = null ;
this . configReloadTimerId = null ;
2026-01-05 13:03:55 +08:00
this . getDefaultIndentChar = () => {
let useTab = this . app . vault . config . useTab === void 0 ? true : false ;
let tabSize = this . app . vault . config . tabSize == void 0 ? 4 : this . app . vault . config . tabSize ;
let default_indent = useTab ? " " : " " . repeat ( tabSize );
return default_indent ;
};
this . getEditor = () => {
let editor = null ;
2026-08-21 15:44:03 +08:00
let markdownView = this . app . workspace . getActiveViewOfType ( import_obsidian9 . MarkdownView );
2026-01-05 13:03:55 +08:00
if ( markdownView ) {
editor = markdownView . editor ;
}
if ( editor === null )
console . log ( "can't get editor" );
return editor ;
};
}
2026-08-21 15:44:03 +08:00
get ruleEngine () {
return this . ruleManager . ruleEngine ;
}
2026-01-05 13:03:55 +08:00
async onload () {
await this . loadSettings ();
2026-08-21 15:44:03 +08:00
this . ruleManager = new RuleManager ( this . app , this . manifest , this . settings , () => this . saveSettings ());
await this . ruleManager . initRuleEngine ();
2026-01-05 13:03:55 +08:00
let TaboutPairStrs = [
"\u3010|\u3011" ,
"\uFF08|\uFF09" ,
"\u300A|\u300B" ,
"\u201C|\u201D" ,
"\u2018|\u2019" ,
"\u300C|\u300D" ,
"\u300E|\u300F" ,
"'|'" ,
'"|"' ,
"$$|$$" ,
"$|$" ,
"__|__" ,
"_|_" ,
"==|==" ,
"~~|~~" ,
"**|**" ,
"*|*" ,
"[[|]]" ,
"[|]" ,
"{|}" ,
"(|)" ,
"<|>"
];
this . TaboutPairStrs = TaboutPairStrs . map (( s ) => string2pairstring ( s ));
this . CurActiveMarkdown = "" ;
this . compose_need_handle = false ;
this . Formater = new LineFormater ();
this . onFormatArticle = false ;
2026-08-21 15:44:03 +08:00
this . plainPasteInProgress = false ;
this . pasteDetected = false ;
2026-01-05 13:03:55 +08:00
if ( ! this . settings ) {
console . error ( "EasyTyping: Settings not loaded properly, using defaults" );
this . settings = Object . assign ({}, DEFAULT_SETTINGS );
}
setDebug ( this . settings . debug );
this . registerEditorExtension ([
2026-08-21 15:44:03 +08:00
createTransactionFilter ( this ),
createViewUpdatePlugin ( this ),
2026-01-05 13:03:55 +08:00
tabstopsStateField . extension
]);
2026-08-21 15:44:03 +08:00
this . registerEditorExtension ( import_state6 . Prec . highest ( import_view5 . keymap . of ([
{
key : "Mod-v" ,
run : () => {
this . markPaste ( false );
return false ;
}
},
{
key : "Mod-Shift-v" ,
run : () => {
this . markPaste ( true );
return false ;
}
},
2026-01-05 13:03:55 +08:00
{
key : "Tab" ,
2026-08-21 15:44:03 +08:00
run : ( v ) => handleTabDown ( this , v )
2026-01-05 13:03:55 +08:00
},
{
key : "Enter" ,
2026-08-21 15:44:03 +08:00
run : ( v ) => handleEnter ( this , v )
2026-01-05 13:03:55 +08:00
},
{
key : "Mod-a" ,
2026-08-21 15:44:03 +08:00
run : ( v ) => handleModA ( this , v )
2026-01-05 13:03:55 +08:00
},
{
key : "Backspace" ,
2026-08-21 15:44:03 +08:00
run : ( v ) => {
2026-01-05 13:03:55 +08:00
if ( ! this . settings . BetterBackspace )
return false ;
2026-08-21 15:44:03 +08:00
return handleBackspace ( v );
2026-01-05 13:03:55 +08:00
}
},
{
key : "Shift-Enter" ,
2026-08-21 15:44:03 +08:00
run : ( v ) => handleShiftEnter ( this , v )
2026-01-05 13:03:55 +08:00
}
])));
2026-08-21 15:44:03 +08:00
const locale7 = getLocale ();
2026-01-05 13:03:55 +08:00
this . addCommand ({
id : "easy-typing-format-article" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . formatArticle ,
2026-01-05 13:03:55 +08:00
editorCallback : ( editor , view ) => {
2026-08-21 15:44:03 +08:00
formatArticle ( this , editor , view );
2026-01-05 13:03:55 +08:00
},
hotkeys : [{
modifiers : [ "Mod" , "Shift" ],
key : "s"
}]
});
this . addCommand ({
id : "easy-typing-select-block" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . selectBlock ,
2026-01-05 13:03:55 +08:00
editorCallback : ( editor , view ) => {
2026-08-21 15:44:03 +08:00
selectBlockInCursor ( this , editor . cm );
2026-01-05 13:03:55 +08:00
}
});
this . addCommand ({
id : "easy-typing-format-selection" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . formatSelection ,
2026-01-05 13:03:55 +08:00
editorCallback : ( editor , view ) => {
2026-08-21 15:44:03 +08:00
formatSelectionOrCurLine ( this , editor , view );
2026-01-05 13:03:55 +08:00
},
hotkeys : [{
modifiers : [ "Mod" , "Shift" ],
key : "l"
}]
});
this . addCommand ({
id : "easy-typing-delete-blank-line" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . deleteBlankLine ,
2026-01-05 13:03:55 +08:00
editorCallback : ( editor , view ) => {
2026-08-21 15:44:03 +08:00
deleteBlankLines ( this , editor );
2026-01-05 13:03:55 +08:00
},
hotkeys : [{
modifiers : [ "Mod" , "Shift" ],
key : "k"
}]
});
this . addCommand ({
id : "easy-typing-goto-new-line-after-cur-line" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . gotoNewLine ,
2026-01-05 13:03:55 +08:00
editorCallback : ( editor , view ) => {
2026-08-21 15:44:03 +08:00
goNewLineAfterCurLine ( this , editor . cm );
2026-01-05 13:03:55 +08:00
},
hotkeys : [{ modifiers : [ "Mod" ], key : "Enter" }]
});
this . addCommand ({
id : "easy-typing-insert-codeblock" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . insertCodeblock ,
2026-01-05 13:03:55 +08:00
editorCallback : ( editor , view ) => {
2026-08-21 15:44:03 +08:00
convert2CodeBlock ( this , editor );
2026-01-05 13:03:55 +08:00
},
hotkeys : [{
modifiers : [ "Mod" , "Shift" ],
key : "n"
}]
});
this . addCommand ({
id : "easy-typing-format-switch" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . switchAutoformat ,
callback : () => switchAutoFormatting ( this ),
2026-01-05 13:03:55 +08:00
hotkeys : [{
modifiers : [ "Ctrl" ],
key : "tab"
}]
});
this . addCommand ({
id : "easy-typing-toggle-comment" ,
2026-08-21 15:44:03 +08:00
name : locale7 . commands . toggleComment ,
editorCallback : ( editor , view ) => toggleComment ( editor . cm ),
2026-01-05 13:03:55 +08:00
hotkeys : [{ modifiers : [ "Mod" ], key : "/" }]
});
this . addSettingTab ( new EasyTypingSettingTab ( this . app , this ));
2026-08-21 15:44:03 +08:00
this . registerEvent ( this . app . vault . on ( "raw" , ( path ) => {
this . onConfigFileChange ( path );
}));
2026-01-05 13:03:55 +08:00
this . registerEvent ( this . app . workspace . on ( "active-leaf-change" , ( leaf ) => {
var _a ;
if ( leaf . view . getViewType () == "markdown" ) {
let file = this . app . workspace . getActiveFile ();
if ( file != null && this . CurActiveMarkdown != file . path ) {
this . CurActiveMarkdown = file . path ;
if (( _a = this . settings ) == null ? void 0 : _a . debug )
2026-08-21 15:44:03 +08:00
new import_obsidian9 . Notice ( "new md-file open: " + file . path );
2026-01-05 13:03:55 +08:00
}
}
}));
2026-08-21 15:44:03 +08:00
if ( import_obsidian9 . Platform . isMacOS && this . settings . FixMacOSContextMenu ) {
2026-01-05 13:03:55 +08:00
this . registerEvent ( this . app . workspace . on ( "editor-menu" , ( menu , editor , view ) => {
if ( editor . listSelections (). length != 1 )
return ;
let selection = editor . listSelections ()[ 0 ];
let selected = editor . getSelection ();
if ( selected == "\n" ) {
editor . setSelection ( selection . anchor , selection . anchor );
}
}));
}
console . log ( "Easy Typing Plugin loaded." );
}
onunload () {
2026-08-21 15:44:03 +08:00
if ( this . pasteTimerId )
clearTimeout ( this . pasteTimerId );
if ( this . configReloadTimerId )
clearTimeout ( this . configReloadTimerId );
2026-01-05 13:03:55 +08:00
console . log ( "Easy Typing Plugin unloaded." );
}
2026-08-21 15:44:03 +08:00
onConfigFileChange ( path ) {
if ( Date . now () - this . ruleManager . lastSaveTime < 2e3 )
2026-01-05 13:03:55 +08:00
return ;
2026-08-21 15:44:03 +08:00
const builtinRulesPath = this . ruleManager . pluginPath ( "builtin-rules.json" );
const userRulesPath = this . ruleManager . pluginPath ( "user-rules.json" );
if ( path !== builtinRulesPath && path !== userRulesPath )
return ;
if ( this . configReloadTimerId )
clearTimeout ( this . configReloadTimerId );
this . configReloadTimerId = setTimeout ( async () => {
this . configReloadTimerId = null ;
try {
await this . ruleManager . initRuleEngine ();
if ( this . settings . debug ) {
console . log ( "[EasyTyping] Rules reloaded from external change:" , path );
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
} catch ( e ) {
console . error ( "[EasyTyping] Failed to reload rules:" , e );
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
}, 1e3 );
2026-01-05 13:03:55 +08:00
}
2026-08-21 15:44:03 +08:00
markPaste ( plain ) {
this . pasteDetected = true ;
if ( plain )
this . plainPasteInProgress = true ;
if ( this . pasteTimerId )
clearTimeout ( this . pasteTimerId );
this . pasteTimerId = setTimeout (() => {
this . pasteDetected = false ;
this . plainPasteInProgress = false ;
this . pasteTimerId = null ;
}, 500 );
2026-01-05 13:03:55 +08:00
}
isCurrentFileExclude () {
2026-08-21 15:44:03 +08:00
return isCurrentFileExclude ( this );
2026-01-05 13:03:55 +08:00
}
async loadSettings () {
try {
const userData = await this . loadData ();
this . settings = Object . assign ({}, DEFAULT_SETTINGS , userData || {});
} catch ( error ) {
console . error ( "EasyTyping: Failed to load settings, using defaults:" , error );
this . settings = Object . assign ({}, DEFAULT_SETTINGS );
}
}
async saveSettings () {
await this . saveData ( this . settings );
}
};
/* nosourcemap */