Something went wrong. Try again.
Markdown editor
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167const std = @import("std");
pub const Run = extern struct { start: u32, end: u32, flags: u32, marker_width: u32,};
/// Resolve a projected boundary. Zero prefers continuing non-code styles,/// but leaving code; negative/positive choose the earliest/latest source side./// Interior visible positions remain exact. Callers validate scalar alignment.pub fn resolve(runs: []const Run, offset: u32, bias: i32) u32 { // A boundary is the entire gap between visible runs, not the individual // empty anchors emitted for nested delimiters. var low: u32 = 0; var high: u32 = std.math.maxInt(u32); var source_end: u32 = 0; for (runs) |run| { source_end = @max(source_end, run.end + run.marker_width); if (run.start == run.end) { continue; } if (offset > run.start and offset < run.end) { return offset; } if (run.end <= offset) { low = @max(low, run.end); } if (run.start >= offset) { high = @min(high, run.start); } } high = @min(high, source_end); if (bias < 0) { return low; } if (bias > 0) { return high; }
// Restrict the default to positions outside adjacent code spans. Choosing // the opposite visible edge directly could enter a second code span. const boundary_low = low; const boundary_high = high; for (runs) |run| { if (run.marker_width == 0) { continue; } if (run.end == boundary_low) { low = @max(low, run.end + run.marker_width); } if (run.start == boundary_high) { high = @min(high, run.start - run.marker_width); } } var preferred = high; var best_styles: u32 = 0; for (runs) |run| { if (run.marker_width > 0) { continue; } if (run.start >= low and run.start <= high and @popCount(run.flags & 7) > best_styles) { best_styles = @popCount(run.flags & 7); preferred = run.start; } if (run.end >= low and run.end <= high and @popCount(run.flags & 7) > best_styles) { best_styles = @popCount(run.flags & 7); preferred = run.end; } } return preferred;}
pub const Span = struct { start: u32, content_start: u32, content_end: u32, end: u32,};
const Token = struct { start: usize, end: usize, marker: u8, styles: u32, opening: bool = true, matched: bool = false, content_end: ?usize = null,};
const Backtick = struct { width: usize, start: usize,
fn less_than(_: void, a: Backtick, b: Backtick) bool { return a.width < b.width or (a.width == b.width and a.start < b.start); }};
fn whitespace(c: u21) bool { return switch (c) { 0x09...0x0d, 0x20, 0xa0, 0x1680, 0x2000...0x200a, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, 0xfeff, => true, else => false, };}
fn word(c: u21) bool { if (c == '_') { return true; } var low: usize = 0; var high: usize = word_ranges.len; while (low < high) { const middle = low + (high - low) / 2; const range = word_ranges[middle]; if (c < range[0]) { high = middle; } else if (c > range[1]) { low = middle + 1; } else { return true; } } return false;}
fn after(source: []const u8, index: usize) u21 { if (index == source.len) { return 0; } const width = std.unicode.utf8ByteSequenceLength(source[index]) catch return 0xfffd; if (width > source.len - index) { return 0xfffd; } return std.unicode.utf8Decode(source[index..][0..width]) catch 0xfffd;}
fn before(source: []const u8, index: usize) u21 { if (index == 0) { return 0; } var start = index - 1; while (start > 0 and source[start] & 0xc0 == 0x80) { start -= 1; } return after(source, start);}
fn emit(runs: *std.ArrayList(Run), allocator: std.mem.Allocator, start: usize, end: usize, active: [3]u32, marker_width: usize) !void { var flags: u32 = if (marker_width > 0) 8 else 0; for (active, 0..) |count, style| { if (count > 0) { flags |= @as(u32, 1) << @intCast(style); } } try runs.append(allocator, .{ .start = @intCast(start), .end = @intCast(end), .flags = flags, .marker_width = @intCast(marker_width), });}
// All offsets refer to the original UTF-8 body, including empty delimiter anchors.// Sorting code markers bounds lookup cost; delimiter matching inspects at most 32 frames.pub fn parse(allocator: std.mem.Allocator, source: []const u8, code_block: bool) ![]Run { return parse_with_spans(allocator, source, code_block, null);}
/// Optional matched source spans support edits that remove an emptied wrapper.pub fn parse_with_spans(allocator: std.mem.Allocator, source: []const u8, code_block: bool, spans: ?*std.ArrayList(Span)) ![]Run { if (source.len > std.math.maxInt(u32)) { return error.SourceTooLong; } var runs: std.ArrayList(Run) = .empty; errdefer runs.deinit(allocator); if (code_block) { try emit(&runs, allocator, 0, source.len, .{ 0, 0, 0 }, 0); return runs.toOwnedSlice(allocator); }
var backticks: std.ArrayList(Backtick) = .empty; defer backticks.deinit(allocator); var cursor: usize = 0; while (cursor < source.len) { if (source[cursor] != '`') { cursor += 1; continue; } const start = cursor; while (cursor < source.len and source[cursor] == '`') { cursor += 1; } try backticks.append(allocator, .{ .width = cursor - start, .start = start }); } std.mem.sort(Backtick, backticks.items, {}, Backtick.less_than);
var tokens: std.ArrayList(Token) = .empty; defer tokens.deinit(allocator); var stack: [32]usize = undefined; var stack_len: usize = 0; cursor = 0; while (cursor < source.len) { const character = source[cursor]; if (character == '\\') { cursor += @min(@as(usize, 2), source.len - cursor); continue; } if (character != '`' and character != '*' and character != '_' and character != '~') { cursor += 1; continue; } const start = cursor; while (cursor < source.len and source[cursor] == character) { cursor += 1; } const width = cursor - start; if (character == '`') { var low: usize = 0; var high = backticks.items.len; const key: Backtick = .{ .width = width, .start = cursor }; while (low < high) { const middle = low + (high - low) / 2; if (Backtick.less_than({}, backticks.items[middle], key)) { low = middle + 1; } else { high = middle; } } if (low < backticks.items.len and backticks.items[low].width == width) { const closing = backticks.items[low].start; if (spans) |out| { try out.append(allocator, .{ .start = @intCast(start), .content_start = @intCast(cursor), .content_end = @intCast(closing), .end = @intCast(closing + width), }); } try tokens.append(allocator, .{ .start = start, .end = closing + width, .marker = character, .styles = 0, .matched = true, .content_end = closing, }); cursor = closing + width; } continue; } if (width > 3 or (character == '~' and width != 2)) { continue; } const preceding = before(source, start); const following = after(source, cursor); const can_open = cursor < source.len and !whitespace(following) and (character != '_' or !word(preceding)); const can_close = start > 0 and !whitespace(preceding) and (character != '_' or !word(following)); var token: Token = .{ .start = start, .end = cursor, .marker = character, .styles = if (character == '~') 4 else if (width == 3) 3 else if (width == 2) 1 else 2, }; if (can_close) { var depth = stack_len; while (depth > 0) { depth -= 1; const opening = &tokens.items[stack[depth]]; if (opening.marker == character and opening.end - opening.start == width and opening.end < start) { if (spans) |out| { try out.append(allocator, .{ .start = @intCast(opening.start), .content_start = @intCast(opening.end), .content_end = @intCast(start), .end = @intCast(cursor), }); } opening.matched = true; token.opening = false; token.matched = true; stack_len = depth; break; } } } if (!token.matched and can_open and stack_len < stack.len) { stack[stack_len] = tokens.items.len; stack_len += 1; } try tokens.append(allocator, token); }
var active: [3]u32 = .{ 0, 0, 0 }; var literal_start: usize = 0; for (tokens.items) |token| { if (!token.matched) { continue; } if (literal_start < token.start) { try emit(&runs, allocator, literal_start, token.start, active, 0); } if (token.content_end) |content_end| { const width = token.end - content_end; try emit(&runs, allocator, token.start + width, content_end, active, width); } else { try emit(&runs, allocator, token.start, token.start, active, 0); for (&active, 0..) |*count, style| { if (token.styles & (@as(u32, 1) << @intCast(style)) != 0) { if (token.opening) { count.* += 1; } else { count.* -= 1; } } } try emit(&runs, allocator, token.end, token.end, active, 0); } literal_start = token.end; } if (literal_start < source.len) { try emit(&runs, allocator, literal_start, source.len, active, 0); } return runs.toOwnedSlice(allocator);}
// Unicode 17.0 Letter, Number, and Mark categories, matching JavaScript Unicode property escapes.const word_ranges = [_][2]u21{ .{ 0x30, 0x39 }, .{ 0x41, 0x5a }, .{ 0x61, 0x7a }, .{ 0xaa, 0xaa }, .{ 0xb2, 0xb3 }, .{ 0xb5, 0xb5 }, .{ 0xb9, 0xba }, .{ 0xbc, 0xbe }, .{ 0xc0, 0xd6 }, .{ 0xd8, 0xf6 }, .{ 0xf8, 0x2c1 }, .{ 0x2c6, 0x2d1 }, .{ 0x2e0, 0x2e4 }, .{ 0x2ec, 0x2ec }, .{ 0x2ee, 0x2ee }, .{ 0x300, 0x374 }, .{ 0x376, 0x377 }, .{ 0x37a, 0x37d }, .{ 0x37f, 0x37f }, .{ 0x386, 0x386 }, .{ 0x388, 0x38a }, .{ 0x38c, 0x38c }, .{ 0x38e, 0x3a1 }, .{ 0x3a3, 0x3f5 }, .{ 0x3f7, 0x481 }, .{ 0x483, 0x52f }, .{ 0x531, 0x556 }, .{ 0x559, 0x559 }, .{ 0x560, 0x588 }, .{ 0x591, 0x5bd }, .{ 0x5bf, 0x5bf }, .{ 0x5c1, 0x5c2 }, .{ 0x5c4, 0x5c5 }, .{ 0x5c7, 0x5c7 }, .{ 0x5d0, 0x5ea }, .{ 0x5ef, 0x5f2 }, .{ 0x610, 0x61a }, .{ 0x620, 0x669 }, .{ 0x66e, 0x6d3 }, .{ 0x6d5, 0x6dc }, .{ 0x6df, 0x6e8 }, .{ 0x6ea, 0x6fc }, .{ 0x6ff, 0x6ff }, .{ 0x710, 0x74a }, .{ 0x74d, 0x7b1 }, .{ 0x7c0, 0x7f5 }, .{ 0x7fa, 0x7fa }, .{ 0x7fd, 0x7fd }, .{ 0x800, 0x82d }, .{ 0x840, 0x85b }, .{ 0x860, 0x86a }, .{ 0x870, 0x887 }, .{ 0x889, 0x88f }, .{ 0x897, 0x8e1 }, .{ 0x8e3, 0x963 }, .{ 0x966, 0x96f }, .{ 0x971, 0x983 }, .{ 0x985, 0x98c }, .{ 0x98f, 0x990 }, .{ 0x993, 0x9a8 }, .{ 0x9aa, 0x9b0 }, .{ 0x9b2, 0x9b2 }, .{ 0x9b6, 0x9b9 }, .{ 0x9bc, 0x9c4 }, .{ 0x9c7, 0x9c8 }, .{ 0x9cb, 0x9ce }, .{ 0x9d7, 0x9d7 }, .{ 0x9dc, 0x9dd }, .{ 0x9df, 0x9e3 }, .{ 0x9e6, 0x9f1 }, .{ 0x9f4, 0x9f9 }, .{ 0x9fc, 0x9fc }, .{ 0x9fe, 0x9fe }, .{ 0xa01, 0xa03 }, .{ 0xa05, 0xa0a }, .{ 0xa0f, 0xa10 }, .{ 0xa13, 0xa28 }, .{ 0xa2a, 0xa30 }, .{ 0xa32, 0xa33 }, .{ 0xa35, 0xa36 }, .{ 0xa38, 0xa39 }, .{ 0xa3c, 0xa3c }, .{ 0xa3e, 0xa42 }, .{ 0xa47, 0xa48 }, .{ 0xa4b, 0xa4d }, .{ 0xa51, 0xa51 }, .{ 0xa59, 0xa5c }, .{ 0xa5e, 0xa5e }, .{ 0xa66, 0xa75 }, .{ 0xa81, 0xa83 }, .{ 0xa85, 0xa8d }, .{ 0xa8f, 0xa91 }, .{ 0xa93, 0xaa8 }, .{ 0xaaa, 0xab0 }, .{ 0xab2, 0xab3 }, .{ 0xab5, 0xab9 }, .{ 0xabc, 0xac5 }, .{ 0xac7, 0xac9 }, .{ 0xacb, 0xacd }, .{ 0xad0, 0xad0 }, .{ 0xae0, 0xae3 }, .{ 0xae6, 0xaef }, .{ 0xaf9, 0xaff }, .{ 0xb01, 0xb03 }, .{ 0xb05, 0xb0c }, .{ 0xb0f, 0xb10 }, .{ 0xb13, 0xb28 }, .{ 0xb2a, 0xb30 }, .{ 0xb32, 0xb33 }, .{ 0xb35, 0xb39 }, .{ 0xb3c, 0xb44 }, .{ 0xb47, 0xb48 }, .{ 0xb4b, 0xb4d }, .{ 0xb55, 0xb57 }, .{ 0xb5c, 0xb5d }, .{ 0xb5f, 0xb63 }, .{ 0xb66, 0xb6f }, .{ 0xb71, 0xb77 }, .{ 0xb82, 0xb83 }, .{ 0xb85, 0xb8a }, .{ 0xb8e, 0xb90 }, .{ 0xb92, 0xb95 }, .{ 0xb99, 0xb9a }, .{ 0xb9c, 0xb9c }, .{ 0xb9e, 0xb9f }, .{ 0xba3, 0xba4 }, .{ 0xba8, 0xbaa }, .{ 0xbae, 0xbb9 }, .{ 0xbbe, 0xbc2 }, .{ 0xbc6, 0xbc8 }, .{ 0xbca, 0xbcd }, .{ 0xbd0, 0xbd0 }, .{ 0xbd7, 0xbd7 }, .{ 0xbe6, 0xbf2 }, .{ 0xc00, 0xc0c }, .{ 0xc0e, 0xc10 }, .{ 0xc12, 0xc28 }, .{ 0xc2a, 0xc39 }, .{ 0xc3c, 0xc44 }, .{ 0xc46, 0xc48 }, .{ 0xc4a, 0xc4d }, .{ 0xc55, 0xc56 }, .{ 0xc58, 0xc5a }, .{ 0xc5c, 0xc5d }, .{ 0xc60, 0xc63 }, .{ 0xc66, 0xc6f }, .{ 0xc78, 0xc7e }, .{ 0xc80, 0xc83 }, .{ 0xc85, 0xc8c }, .{ 0xc8e, 0xc90 }, .{ 0xc92, 0xca8 }, .{ 0xcaa, 0xcb3 }, .{ 0xcb5, 0xcb9 }, .{ 0xcbc, 0xcc4 }, .{ 0xcc6, 0xcc8 }, .{ 0xcca, 0xccd }, .{ 0xcd5, 0xcd6 }, .{ 0xcdc, 0xcde }, .{ 0xce0, 0xce3 }, .{ 0xce6, 0xcef }, .{ 0xcf1, 0xcf3 }, .{ 0xd00, 0xd0c }, .{ 0xd0e, 0xd10 }, .{ 0xd12, 0xd44 }, .{ 0xd46, 0xd48 }, .{ 0xd4a, 0xd4e }, .{ 0xd54, 0xd63 }, .{ 0xd66, 0xd78 }, .{ 0xd7a, 0xd7f }, .{ 0xd81, 0xd83 }, .{ 0xd85, 0xd96 }, .{ 0xd9a, 0xdb1 }, .{ 0xdb3, 0xdbb }, .{ 0xdbd, 0xdbd }, .{ 0xdc0, 0xdc6 }, .{ 0xdca, 0xdca }, .{ 0xdcf, 0xdd4 }, .{ 0xdd6, 0xdd6 }, .{ 0xdd8, 0xddf }, .{ 0xde6, 0xdef }, .{ 0xdf2, 0xdf3 }, .{ 0xe01, 0xe3a }, .{ 0xe40, 0xe4e }, .{ 0xe50, 0xe59 }, .{ 0xe81, 0xe82 }, .{ 0xe84, 0xe84 }, .{ 0xe86, 0xe8a }, .{ 0xe8c, 0xea3 }, .{ 0xea5, 0xea5 }, .{ 0xea7, 0xebd }, .{ 0xec0, 0xec4 }, .{ 0xec6, 0xec6 }, .{ 0xec8, 0xece }, .{ 0xed0, 0xed9 }, .{ 0xedc, 0xedf }, .{ 0xf00, 0xf00 }, .{ 0xf18, 0xf19 }, .{ 0xf20, 0xf33 }, .{ 0xf35, 0xf35 }, .{ 0xf37, 0xf37 }, .{ 0xf39, 0xf39 }, .{ 0xf3e, 0xf47 }, .{ 0xf49, 0xf6c }, .{ 0xf71, 0xf84 }, .{ 0xf86, 0xf97 }, .{ 0xf99, 0xfbc }, .{ 0xfc6, 0xfc6 }, .{ 0x1000, 0x1049 }, .{ 0x1050, 0x109d }, .{ 0x10a0, 0x10c5 }, .{ 0x10c7, 0x10c7 }, .{ 0x10cd, 0x10cd }, .{ 0x10d0, 0x10fa }, .{ 0x10fc, 0x1248 }, .{ 0x124a, 0x124d }, .{ 0x1250, 0x1256 }, .{ 0x1258, 0x1258 }, .{ 0x125a, 0x125d }, .{ 0x1260, 0x1288 }, .{ 0x128a, 0x128d }, .{ 0x1290, 0x12b0 }, .{ 0x12b2, 0x12b5 }, .{ 0x12b8, 0x12be }, .{ 0x12c0, 0x12c0 }, .{ 0x12c2, 0x12c5 }, .{ 0x12c8, 0x12d6 }, .{ 0x12d8, 0x1310 }, .{ 0x1312, 0x1315 }, .{ 0x1318, 0x135a }, .{ 0x135d, 0x135f }, .{ 0x1369, 0x137c }, .{ 0x1380, 0x138f }, .{ 0x13a0, 0x13f5 }, .{ 0x13f8, 0x13fd }, .{ 0x1401, 0x166c }, .{ 0x166f, 0x167f }, .{ 0x1681, 0x169a }, .{ 0x16a0, 0x16ea }, .{ 0x16ee, 0x16f8 }, .{ 0x1700, 0x1715 }, .{ 0x171f, 0x1734 }, .{ 0x1740, 0x1753 }, .{ 0x1760, 0x176c }, .{ 0x176e, 0x1770 }, .{ 0x1772, 0x1773 }, .{ 0x1780, 0x17d3 }, .{ 0x17d7, 0x17d7 }, .{ 0x17dc, 0x17dd }, .{ 0x17e0, 0x17e9 }, .{ 0x17f0, 0x17f9 }, .{ 0x180b, 0x180d }, .{ 0x180f, 0x1819 }, .{ 0x1820, 0x1878 }, .{ 0x1880, 0x18aa }, .{ 0x18b0, 0x18f5 }, .{ 0x1900, 0x191e }, .{ 0x1920, 0x192b }, .{ 0x1930, 0x193b }, .{ 0x1946, 0x196d }, .{ 0x1970, 0x1974 }, .{ 0x1980, 0x19ab }, .{ 0x19b0, 0x19c9 }, .{ 0x19d0, 0x19da }, .{ 0x1a00, 0x1a1b }, .{ 0x1a20, 0x1a5e }, .{ 0x1a60, 0x1a7c }, .{ 0x1a7f, 0x1a89 }, .{ 0x1a90, 0x1a99 }, .{ 0x1aa7, 0x1aa7 }, .{ 0x1ab0, 0x1add }, .{ 0x1ae0, 0x1aeb }, .{ 0x1b00, 0x1b4c }, .{ 0x1b50, 0x1b59 }, .{ 0x1b6b, 0x1b73 }, .{ 0x1b80, 0x1bf3 }, .{ 0x1c00, 0x1c37 }, .{ 0x1c40, 0x1c49 }, .{ 0x1c4d, 0x1c7d }, .{ 0x1c80, 0x1c8a }, .{ 0x1c90, 0x1cba }, .{ 0x1cbd, 0x1cbf }, .{ 0x1cd0, 0x1cd2 }, .{ 0x1cd4, 0x1cfa }, .{ 0x1d00, 0x1f15 }, .{ 0x1f18, 0x1f1d }, .{ 0x1f20, 0x1f45 }, .{ 0x1f48, 0x1f4d }, .{ 0x1f50, 0x1f57 }, .{ 0x1f59, 0x1f59 }, .{ 0x1f5b, 0x1f5b }, .{ 0x1f5d, 0x1f5d }, .{ 0x1f5f, 0x1f7d }, .{ 0x1f80, 0x1fb4 }, .{ 0x1fb6, 0x1fbc }, .{ 0x1fbe, 0x1fbe }, .{ 0x1fc2, 0x1fc4 }, .{ 0x1fc6, 0x1fcc }, .{ 0x1fd0, 0x1fd3 }, .{ 0x1fd6, 0x1fdb }, .{ 0x1fe0, 0x1fec }, .{ 0x1ff2, 0x1ff4 }, .{ 0x1ff6, 0x1ffc }, .{ 0x2070, 0x2071 }, .{ 0x2074, 0x2079 }, .{ 0x207f, 0x2089 }, .{ 0x2090, 0x209c }, .{ 0x20d0, 0x20f0 }, .{ 0x2102, 0x2102 }, .{ 0x2107, 0x2107 }, .{ 0x210a, 0x2113 }, .{ 0x2115, 0x2115 }, .{ 0x2119, 0x211d }, .{ 0x2124, 0x2124 }, .{ 0x2126, 0x2126 }, .{ 0x2128, 0x2128 }, .{ 0x212a, 0x212d }, .{ 0x212f, 0x2139 }, .{ 0x213c, 0x213f }, .{ 0x2145, 0x2149 }, .{ 0x214e, 0x214e }, .{ 0x2150, 0x2189 }, .{ 0x2460, 0x249b }, .{ 0x24ea, 0x24ff }, .{ 0x2776, 0x2793 }, .{ 0x2c00, 0x2ce4 }, .{ 0x2ceb, 0x2cf3 }, .{ 0x2cfd, 0x2cfd }, .{ 0x2d00, 0x2d25 }, .{ 0x2d27, 0x2d27 }, .{ 0x2d2d, 0x2d2d }, .{ 0x2d30, 0x2d67 }, .{ 0x2d6f, 0x2d6f }, .{ 0x2d7f, 0x2d96 }, .{ 0x2da0, 0x2da6 }, .{ 0x2da8, 0x2dae }, .{ 0x2db0, 0x2db6 }, .{ 0x2db8, 0x2dbe }, .{ 0x2dc0, 0x2dc6 }, .{ 0x2dc8, 0x2dce }, .{ 0x2dd0, 0x2dd6 }, .{ 0x2dd8, 0x2dde }, .{ 0x2de0, 0x2dff }, .{ 0x2e2f, 0x2e2f }, .{ 0x3005, 0x3007 }, .{ 0x3021, 0x302f }, .{ 0x3031, 0x3035 }, .{ 0x3038, 0x303c }, .{ 0x3041, 0x3096 }, .{ 0x3099, 0x309a }, .{ 0x309d, 0x309f }, .{ 0x30a1, 0x30fa }, .{ 0x30fc, 0x30ff }, .{ 0x3105, 0x312f }, .{ 0x3131, 0x318e }, .{ 0x3192, 0x3195 }, .{ 0x31a0, 0x31bf }, .{ 0x31f0, 0x31ff }, .{ 0x3220, 0x3229 }, .{ 0x3248, 0x324f }, .{ 0x3251, 0x325f }, .{ 0x3280, 0x3289 }, .{ 0x32b1, 0x32bf }, .{ 0x3400, 0x4dbf }, .{ 0x4e00, 0xa48c }, .{ 0xa4d0, 0xa4fd }, .{ 0xa500, 0xa60c }, .{ 0xa610, 0xa62b }, .{ 0xa640, 0xa672 }, .{ 0xa674, 0xa67d }, .{ 0xa67f, 0xa6f1 }, .{ 0xa717, 0xa71f }, .{ 0xa722, 0xa788 }, .{ 0xa78b, 0xa7dc }, .{ 0xa7f1, 0xa827 }, .{ 0xa82c, 0xa82c }, .{ 0xa830, 0xa835 }, .{ 0xa840, 0xa873 }, .{ 0xa880, 0xa8c5 }, .{ 0xa8d0, 0xa8d9 }, .{ 0xa8e0, 0xa8f7 }, .{ 0xa8fb, 0xa8fb }, .{ 0xa8fd, 0xa92d }, .{ 0xa930, 0xa953 }, .{ 0xa960, 0xa97c }, .{ 0xa980, 0xa9c0 }, .{ 0xa9cf, 0xa9d9 }, .{ 0xa9e0, 0xa9fe }, .{ 0xaa00, 0xaa36 }, .{ 0xaa40, 0xaa4d }, .{ 0xaa50, 0xaa59 }, .{ 0xaa60, 0xaa76 }, .{ 0xaa7a, 0xaac2 }, .{ 0xaadb, 0xaadd }, .{ 0xaae0, 0xaaef }, .{ 0xaaf2, 0xaaf6 }, .{ 0xab01, 0xab06 }, .{ 0xab09, 0xab0e }, .{ 0xab11, 0xab16 }, .{ 0xab20, 0xab26 }, .{ 0xab28, 0xab2e }, .{ 0xab30, 0xab5a }, .{ 0xab5c, 0xab69 }, .{ 0xab70, 0xabea }, .{ 0xabec, 0xabed }, .{ 0xabf0, 0xabf9 }, .{ 0xac00, 0xd7a3 }, .{ 0xd7b0, 0xd7c6 }, .{ 0xd7cb, 0xd7fb }, .{ 0xf900, 0xfa6d }, .{ 0xfa70, 0xfad9 }, .{ 0xfb00, 0xfb06 }, .{ 0xfb13, 0xfb17 }, .{ 0xfb1d, 0xfb28 }, .{ 0xfb2a, 0xfb36 }, .{ 0xfb38, 0xfb3c }, .{ 0xfb3e, 0xfb3e }, .{ 0xfb40, 0xfb41 }, .{ 0xfb43, 0xfb44 }, .{ 0xfb46, 0xfbb1 }, .{ 0xfbd3, 0xfd3d }, .{ 0xfd50, 0xfd8f }, .{ 0xfd92, 0xfdc7 }, .{ 0xfdf0, 0xfdfb }, .{ 0xfe00, 0xfe0f }, .{ 0xfe20, 0xfe2f }, .{ 0xfe70, 0xfe74 }, .{ 0xfe76, 0xfefc }, .{ 0xff10, 0xff19 }, .{ 0xff21, 0xff3a }, .{ 0xff41, 0xff5a }, .{ 0xff66, 0xffbe }, .{ 0xffc2, 0xffc7 }, .{ 0xffca, 0xffcf }, .{ 0xffd2, 0xffd7 }, .{ 0xffda, 0xffdc }, .{ 0x10000, 0x1000b }, .{ 0x1000d, 0x10026 }, .{ 0x10028, 0x1003a }, .{ 0x1003c, 0x1003d }, .{ 0x1003f, 0x1004d }, .{ 0x10050, 0x1005d }, .{ 0x10080, 0x100fa }, .{ 0x10107, 0x10133 }, .{ 0x10140, 0x10178 }, .{ 0x1018a, 0x1018b }, .{ 0x101fd, 0x101fd }, .{ 0x10280, 0x1029c }, .{ 0x102a0, 0x102d0 }, .{ 0x102e0, 0x102fb }, .{ 0x10300, 0x10323 }, .{ 0x1032d, 0x1034a }, .{ 0x10350, 0x1037a }, .{ 0x10380, 0x1039d }, .{ 0x103a0, 0x103c3 }, .{ 0x103c8, 0x103cf }, .{ 0x103d1, 0x103d5 }, .{ 0x10400, 0x1049d }, .{ 0x104a0, 0x104a9 }, .{ 0x104b0, 0x104d3 }, .{ 0x104d8, 0x104fb }, .{ 0x10500, 0x10527 }, .{ 0x10530, 0x10563 }, .{ 0x10570, 0x1057a }, .{ 0x1057c, 0x1058a }, .{ 0x1058c, 0x10592 }, .{ 0x10594, 0x10595 }, .{ 0x10597, 0x105a1 }, .{ 0x105a3, 0x105b1 }, .{ 0x105b3, 0x105b9 }, .{ 0x105bb, 0x105bc }, .{ 0x105c0, 0x105f3 }, .{ 0x10600, 0x10736 }, .{ 0x10740, 0x10755 }, .{ 0x10760, 0x10767 }, .{ 0x10780, 0x10785 }, .{ 0x10787, 0x107b0 }, .{ 0x107b2, 0x107ba }, .{ 0x10800, 0x10805 }, .{ 0x10808, 0x10808 }, .{ 0x1080a, 0x10835 }, .{ 0x10837, 0x10838 }, .{ 0x1083c, 0x1083c }, .{ 0x1083f, 0x10855 }, .{ 0x10858, 0x10876 }, .{ 0x10879, 0x1089e }, .{ 0x108a7, 0x108af }, .{ 0x108e0, 0x108f2 }, .{ 0x108f4, 0x108f5 }, .{ 0x108fb, 0x1091b }, .{ 0x10920, 0x10939 }, .{ 0x10940, 0x10959 }, .{ 0x10980, 0x109b7 }, .{ 0x109bc, 0x109cf }, .{ 0x109d2, 0x10a03 }, .{ 0x10a05, 0x10a06 }, .{ 0x10a0c, 0x10a13 }, .{ 0x10a15, 0x10a17 }, .{ 0x10a19, 0x10a35 }, .{ 0x10a38, 0x10a3a }, .{ 0x10a3f, 0x10a48 }, .{ 0x10a60, 0x10a7e }, .{ 0x10a80, 0x10a9f }, .{ 0x10ac0, 0x10ac7 }, .{ 0x10ac9, 0x10ae6 }, .{ 0x10aeb, 0x10aef }, .{ 0x10b00, 0x10b35 }, .{ 0x10b40, 0x10b55 }, .{ 0x10b58, 0x10b72 }, .{ 0x10b78, 0x10b91 }, .{ 0x10ba9, 0x10baf }, .{ 0x10c00, 0x10c48 }, .{ 0x10c80, 0x10cb2 }, .{ 0x10cc0, 0x10cf2 }, .{ 0x10cfa, 0x10d27 }, .{ 0x10d30, 0x10d39 }, .{ 0x10d40, 0x10d65 }, .{ 0x10d69, 0x10d6d }, .{ 0x10d6f, 0x10d85 }, .{ 0x10e60, 0x10e7e }, .{ 0x10e80, 0x10ea9 }, .{ 0x10eab, 0x10eac }, .{ 0x10eb0, 0x10eb1 }, .{ 0x10ec2, 0x10ec7 }, .{ 0x10efa, 0x10f27 }, .{ 0x10f30, 0x10f54 }, .{ 0x10f70, 0x10f85 }, .{ 0x10fb0, 0x10fcb }, .{ 0x10fe0, 0x10ff6 }, .{ 0x11000, 0x11046 }, .{ 0x11052, 0x11075 }, .{ 0x1107f, 0x110ba }, .{ 0x110c2, 0x110c2 }, .{ 0x110d0, 0x110e8 }, .{ 0x110f0, 0x110f9 }, .{ 0x11100, 0x11134 }, .{ 0x11136, 0x1113f }, .{ 0x11144, 0x11147 }, .{ 0x11150, 0x11173 }, .{ 0x11176, 0x11176 }, .{ 0x11180, 0x111c4 }, .{ 0x111c9, 0x111cc }, .{ 0x111ce, 0x111da }, .{ 0x111dc, 0x111dc }, .{ 0x111e1, 0x111f4 }, .{ 0x11200, 0x11211 }, .{ 0x11213, 0x11237 }, .{ 0x1123e, 0x11241 }, .{ 0x11280, 0x11286 }, .{ 0x11288, 0x11288 }, .{ 0x1128a, 0x1128d }, .{ 0x1128f, 0x1129d }, .{ 0x1129f, 0x112a8 }, .{ 0x112b0, 0x112ea }, .{ 0x112f0, 0x112f9 }, .{ 0x11300, 0x11303 }, .{ 0x11305, 0x1130c }, .{ 0x1130f, 0x11310 }, .{ 0x11313, 0x11328 }, .{ 0x1132a, 0x11330 }, .{ 0x11332, 0x11333 }, .{ 0x11335, 0x11339 }, .{ 0x1133b, 0x11344 }, .{ 0x11347, 0x11348 }, .{ 0x1134b, 0x1134d }, .{ 0x11350, 0x11350 }, .{ 0x11357, 0x11357 }, .{ 0x1135d, 0x11363 }, .{ 0x11366, 0x1136c }, .{ 0x11370, 0x11374 }, .{ 0x11380, 0x11389 }, .{ 0x1138b, 0x1138b }, .{ 0x1138e, 0x1138e }, .{ 0x11390, 0x113b5 }, .{ 0x113b7, 0x113c0 }, .{ 0x113c2, 0x113c2 }, .{ 0x113c5, 0x113c5 }, .{ 0x113c7, 0x113ca }, .{ 0x113cc, 0x113d3 }, .{ 0x113e1, 0x113e2 }, .{ 0x11400, 0x1144a }, .{ 0x11450, 0x11459 }, .{ 0x1145e, 0x11461 }, .{ 0x11480, 0x114c5 }, .{ 0x114c7, 0x114c7 }, .{ 0x114d0, 0x114d9 }, .{ 0x11580, 0x115b5 }, .{ 0x115b8, 0x115c0 }, .{ 0x115d8, 0x115dd }, .{ 0x11600, 0x11640 }, .{ 0x11644, 0x11644 }, .{ 0x11650, 0x11659 }, .{ 0x11680, 0x116b8 }, .{ 0x116c0, 0x116c9 }, .{ 0x116d0, 0x116e3 }, .{ 0x11700, 0x1171a }, .{ 0x1171d, 0x1172b }, .{ 0x11730, 0x1173b }, .{ 0x11740, 0x11746 }, .{ 0x11800, 0x1183a }, .{ 0x118a0, 0x118f2 }, .{ 0x118ff, 0x11906 }, .{ 0x11909, 0x11909 }, .{ 0x1190c, 0x11913 }, .{ 0x11915, 0x11916 }, .{ 0x11918, 0x11935 }, .{ 0x11937, 0x11938 }, .{ 0x1193b, 0x11943 }, .{ 0x11950, 0x11959 }, .{ 0x119a0, 0x119a7 }, .{ 0x119aa, 0x119d7 }, .{ 0x119da, 0x119e1 }, .{ 0x119e3, 0x119e4 }, .{ 0x11a00, 0x11a3e }, .{ 0x11a47, 0x11a47 }, .{ 0x11a50, 0x11a99 }, .{ 0x11a9d, 0x11a9d }, .{ 0x11ab0, 0x11af8 }, .{ 0x11b60, 0x11b67 }, .{ 0x11bc0, 0x11be0 }, .{ 0x11bf0, 0x11bf9 }, .{ 0x11c00, 0x11c08 }, .{ 0x11c0a, 0x11c36 }, .{ 0x11c38, 0x11c40 }, .{ 0x11c50, 0x11c6c }, .{ 0x11c72, 0x11c8f }, .{ 0x11c92, 0x11ca7 }, .{ 0x11ca9, 0x11cb6 }, .{ 0x11d00, 0x11d06 }, .{ 0x11d08, 0x11d09 }, .{ 0x11d0b, 0x11d36 }, .{ 0x11d3a, 0x11d3a }, .{ 0x11d3c, 0x11d3d }, .{ 0x11d3f, 0x11d47 }, .{ 0x11d50, 0x11d59 }, .{ 0x11d60, 0x11d65 }, .{ 0x11d67, 0x11d68 }, .{ 0x11d6a, 0x11d8e }, .{ 0x11d90, 0x11d91 }, .{ 0x11d93, 0x11d98 }, .{ 0x11da0, 0x11da9 }, .{ 0x11db0, 0x11ddb }, .{ 0x11de0, 0x11de9 }, .{ 0x11ee0, 0x11ef6 }, .{ 0x11f00, 0x11f10 }, .{ 0x11f12, 0x11f3a }, .{ 0x11f3e, 0x11f42 }, .{ 0x11f50, 0x11f5a }, .{ 0x11fb0, 0x11fb0 }, .{ 0x11fc0, 0x11fd4 }, .{ 0x12000, 0x12399 }, .{ 0x12400, 0x1246e }, .{ 0x12480, 0x12543 }, .{ 0x12f90, 0x12ff0 }, .{ 0x13000, 0x1342f }, .{ 0x13440, 0x13455 }, .{ 0x13460, 0x143fa }, .{ 0x14400, 0x14646 }, .{ 0x16100, 0x16139 }, .{ 0x16800, 0x16a38 }, .{ 0x16a40, 0x16a5e }, .{ 0x16a60, 0x16a69 }, .{ 0x16a70, 0x16abe }, .{ 0x16ac0, 0x16ac9 }, .{ 0x16ad0, 0x16aed }, .{ 0x16af0, 0x16af4 }, .{ 0x16b00, 0x16b36 }, .{ 0x16b40, 0x16b43 }, .{ 0x16b50, 0x16b59 }, .{ 0x16b5b, 0x16b61 }, .{ 0x16b63, 0x16b77 }, .{ 0x16b7d, 0x16b8f }, .{ 0x16d40, 0x16d6c }, .{ 0x16d70, 0x16d79 }, .{ 0x16e40, 0x16e96 }, .{ 0x16ea0, 0x16eb8 }, .{ 0x16ebb, 0x16ed3 }, .{ 0x16f00, 0x16f4a }, .{ 0x16f4f, 0x16f87 }, .{ 0x16f8f, 0x16f9f }, .{ 0x16fe0, 0x16fe1 }, .{ 0x16fe3, 0x16fe4 }, .{ 0x16ff0, 0x16ff6 }, .{ 0x17000, 0x18cd5 }, .{ 0x18cff, 0x18d1e }, .{ 0x18d80, 0x18df2 }, .{ 0x1aff0, 0x1aff3 }, .{ 0x1aff5, 0x1affb }, .{ 0x1affd, 0x1affe }, .{ 0x1b000, 0x1b122 }, .{ 0x1b132, 0x1b132 }, .{ 0x1b150, 0x1b152 }, .{ 0x1b155, 0x1b155 }, .{ 0x1b164, 0x1b167 }, .{ 0x1b170, 0x1b2fb }, .{ 0x1bc00, 0x1bc6a }, .{ 0x1bc70, 0x1bc7c }, .{ 0x1bc80, 0x1bc88 }, .{ 0x1bc90, 0x1bc99 }, .{ 0x1bc9d, 0x1bc9e }, .{ 0x1ccf0, 0x1ccf9 }, .{ 0x1cf00, 0x1cf2d }, .{ 0x1cf30, 0x1cf46 }, .{ 0x1d165, 0x1d169 }, .{ 0x1d16d, 0x1d172 }, .{ 0x1d17b, 0x1d182 }, .{ 0x1d185, 0x1d18b }, .{ 0x1d1aa, 0x1d1ad }, .{ 0x1d242, 0x1d244 }, .{ 0x1d2c0, 0x1d2d3 }, .{ 0x1d2e0, 0x1d2f3 }, .{ 0x1d360, 0x1d378 }, .{ 0x1d400, 0x1d454 }, .{ 0x1d456, 0x1d49c }, .{ 0x1d49e, 0x1d49f }, .{ 0x1d4a2, 0x1d4a2 }, .{ 0x1d4a5, 0x1d4a6 }, .{ 0x1d4a9, 0x1d4ac }, .{ 0x1d4ae, 0x1d4b9 }, .{ 0x1d4bb, 0x1d4bb }, .{ 0x1d4bd, 0x1d4c3 }, .{ 0x1d4c5, 0x1d505 }, .{ 0x1d507, 0x1d50a }, .{ 0x1d50d, 0x1d514 }, .{ 0x1d516, 0x1d51c }, .{ 0x1d51e, 0x1d539 }, .{ 0x1d53b, 0x1d53e }, .{ 0x1d540, 0x1d544 }, .{ 0x1d546, 0x1d546 }, .{ 0x1d54a, 0x1d550 }, .{ 0x1d552, 0x1d6a5 }, .{ 0x1d6a8, 0x1d6c0 }, .{ 0x1d6c2, 0x1d6da }, .{ 0x1d6dc, 0x1d6fa }, .{ 0x1d6fc, 0x1d714 }, .{ 0x1d716, 0x1d734 }, .{ 0x1d736, 0x1d74e }, .{ 0x1d750, 0x1d76e }, .{ 0x1d770, 0x1d788 }, .{ 0x1d78a, 0x1d7a8 }, .{ 0x1d7aa, 0x1d7c2 }, .{ 0x1d7c4, 0x1d7cb }, .{ 0x1d7ce, 0x1d7ff }, .{ 0x1da00, 0x1da36 }, .{ 0x1da3b, 0x1da6c }, .{ 0x1da75, 0x1da75 }, .{ 0x1da84, 0x1da84 }, .{ 0x1da9b, 0x1da9f }, .{ 0x1daa1, 0x1daaf }, .{ 0x1df00, 0x1df1e }, .{ 0x1df25, 0x1df2a }, .{ 0x1e000, 0x1e006 }, .{ 0x1e008, 0x1e018 }, .{ 0x1e01b, 0x1e021 }, .{ 0x1e023, 0x1e024 }, .{ 0x1e026, 0x1e02a }, .{ 0x1e030, 0x1e06d }, .{ 0x1e08f, 0x1e08f }, .{ 0x1e100, 0x1e12c }, .{ 0x1e130, 0x1e13d }, .{ 0x1e140, 0x1e149 }, .{ 0x1e14e, 0x1e14e }, .{ 0x1e290, 0x1e2ae }, .{ 0x1e2c0, 0x1e2f9 }, .{ 0x1e4d0, 0x1e4f9 }, .{ 0x1e5d0, 0x1e5fa }, .{ 0x1e6c0, 0x1e6de }, .{ 0x1e6e0, 0x1e6f5 }, .{ 0x1e6fe, 0x1e6ff }, .{ 0x1e7e0, 0x1e7e6 }, .{ 0x1e7e8, 0x1e7eb }, .{ 0x1e7ed, 0x1e7ee }, .{ 0x1e7f0, 0x1e7fe }, .{ 0x1e800, 0x1e8c4 }, .{ 0x1e8c7, 0x1e8d6 }, .{ 0x1e900, 0x1e94b }, .{ 0x1e950, 0x1e959 }, .{ 0x1ec71, 0x1ecab }, .{ 0x1ecad, 0x1ecaf }, .{ 0x1ecb1, 0x1ecb4 }, .{ 0x1ed01, 0x1ed2d }, .{ 0x1ed2f, 0x1ed3d }, .{ 0x1ee00, 0x1ee03 }, .{ 0x1ee05, 0x1ee1f }, .{ 0x1ee21, 0x1ee22 }, .{ 0x1ee24, 0x1ee24 }, .{ 0x1ee27, 0x1ee27 }, .{ 0x1ee29, 0x1ee32 }, .{ 0x1ee34, 0x1ee37 }, .{ 0x1ee39, 0x1ee39 }, .{ 0x1ee3b, 0x1ee3b }, .{ 0x1ee42, 0x1ee42 }, .{ 0x1ee47, 0x1ee47 }, .{ 0x1ee49, 0x1ee49 }, .{ 0x1ee4b, 0x1ee4b }, .{ 0x1ee4d, 0x1ee4f }, .{ 0x1ee51, 0x1ee52 }, .{ 0x1ee54, 0x1ee54 }, .{ 0x1ee57, 0x1ee57 }, .{ 0x1ee59, 0x1ee59 }, .{ 0x1ee5b, 0x1ee5b }, .{ 0x1ee5d, 0x1ee5d }, .{ 0x1ee5f, 0x1ee5f }, .{ 0x1ee61, 0x1ee62 }, .{ 0x1ee64, 0x1ee64 }, .{ 0x1ee67, 0x1ee6a }, .{ 0x1ee6c, 0x1ee72 }, .{ 0x1ee74, 0x1ee77 }, .{ 0x1ee79, 0x1ee7c }, .{ 0x1ee7e, 0x1ee7e }, .{ 0x1ee80, 0x1ee89 }, .{ 0x1ee8b, 0x1ee9b }, .{ 0x1eea1, 0x1eea3 }, .{ 0x1eea5, 0x1eea9 }, .{ 0x1eeab, 0x1eebb }, .{ 0x1f100, 0x1f10c }, .{ 0x1fbf0, 0x1fbf9 }, .{ 0x20000, 0x2a6df }, .{ 0x2a700, 0x2b81d }, .{ 0x2b820, 0x2cead }, .{ 0x2ceb0, 0x2ebe0 }, .{ 0x2ebf0, 0x2ee5d }, .{ 0x2f800, 0x2fa1d }, .{ 0x30000, 0x3134a }, .{ 0x31350, 0x33479 }, .{ 0xe0100, 0xe01ef },};