منبع منتشرشده
دانلود ZIP منبع
CH-J SM Mobile
پوشهها و فایلهای یک نسخهٔ مشخص از برنامه را مرور کنید.
CH-J / SM Mobile
175 فایل
sm-mobile-20261016T185235Z-8e93ecc1b59a
افزودهشده: · ساختهشده:
1
import 'dart:convert';2
import 'dart:typed_data';3
import 'package:flutter_test/flutter_test.dart';4
import 'package:sm_mobile/services/editor/languages.dart';5
import 'package:sm_mobile/services/editor/text_codec.dart';6
import 'package:sm_mobile/services/editor/validation.dart';8
Uint8List b(List<int> v) => Uint8List.fromList(v);10
/// Decodes, then encodes the same text with the detected settings: the11
/// bytes must come back unchanged.12
void roundTrip(Uint8List bytes, TextEncoding expected, {LineBreak? lineBreak}) {13
final d = decodeDocument(bytes);14
expect(d.encoding, expected);15
expect(d.exact, true);16
if (lineBreak != null) expect(d.lineBreaks.dominant, lineBreak);17
final again = encodeText(18
withLineBreaks(d.text, d.lineBreaks.dominant),19
d.encoding,20
);21
expect(again, bytes);22
}24
void main() {25
group('encodings are preserved byte for byte', () {26
const text = 'Příliš žluťoučký kůň úpěl ďábelské ódy – €\n';27
test('UTF-8 with and without BOM', () {28
roundTrip(b(utf8.encode(text)), TextEncoding.utf8);29
roundTrip(30
b([0xef, 0xbb, 0xbf, ...utf8.encode(text)]),31
TextEncoding.utf8Bom,32
);33
});34
test('UTF-16 LE/BE with BOM and LE without BOM', () {35
for (final e in [TextEncoding.utf16le, TextEncoding.utf16be]) {36
roundTrip(encodeText('A😀$text', e), e);37
}38
final noBom = encodeText(39
'plain ascii text\n',40
TextEncoding.utf16le,41
).sublist(2);42
expect(detectEncoding(noBom), TextEncoding.utf16le);43
});44
test('legacy 8-bit text is never guessed silently', () {45
final cp1250 = encodeText(text, TextEncoding.windows1250);46
expect(detectEncoding(cp1250), isNull);47
expect(() => decodeDocument(cp1250), throwsA(isA<UnknownEncoding>()));48
final d = decodeDocument(cp1250, encoding: TextEncoding.windows1250);49
expect(d.text, text);50
expect(encodeText(d.text, TextEncoding.windows1250), cp1250);51
final iso = encodeText('Žluťoučký\n', TextEncoding.iso88592);52
expect(53
decodeDocument(iso, encoding: TextEncoding.iso88592).text,54
'Žluťoučký\n',55
);56
expect(decodeText(b([0xe9]), TextEncoding.latin1), 'é');57
});58
test('undefined bytes and unrepresentable characters are reported', () {59
expect(60
() => decodeText(b([0x81]), TextEncoding.windows1252),61
throwsFormatException,62
);63
expect(64
() => encodeText('日本', TextEncoding.windows1250),65
throwsA(isA<UnencodableText>().having((u) => u.count, 'count', 2)),66
);67
expect(68
() => decodeText(b([0xc3]), TextEncoding.utf8),69
throwsFormatException,70
);71
});72
});74
group('line endings and final newline', () {75
test('LF, CRLF and CR are kept; final newline presence is kept', () {76
roundTrip(77
b(utf8.encode('a\nb\n')),78
TextEncoding.utf8,79
lineBreak: LineBreak.lf,80
);81
roundTrip(82
b(utf8.encode('a\r\nb\r\n')),83
TextEncoding.utf8,84
lineBreak: LineBreak.crlf,85
);86
roundTrip(87
b(utf8.encode('a\rb\r')),88
TextEncoding.utf8,89
lineBreak: LineBreak.cr,90
);91
roundTrip(b(utf8.encode('a\nb')), TextEncoding.utf8);92
expect(decodeDocument(b(utf8.encode('a\nb'))).finalNewline, false);93
expect(decodeDocument(b(utf8.encode('a\nb\n'))).finalNewline, true);94
});95
test('mixed endings are detected and not reported as exact', () {96
final d = decodeDocument(b(utf8.encode('a\r\nb\nc\r\n')));97
expect(d.lineBreaks.mixed, true);98
expect(d.lineBreaks.dominant, LineBreak.crlf);99
expect(d.exact, false);100
});101
});103
test('binary data is recognised, UTF-16 text is not binary', () {104
expect(looksBinary(b([0x89, 0x50, 0x4e, 0x47, 0, 0, 0, 0x0d])), true);105
expect(looksBinary(b(utf8.encode('server {\n listen 80;\n}\n'))), false);106
expect(looksBinary(encodeText('hello world', TextEncoding.utf16le)), false);107
});109
group('syntax detection', () {110
final cases = {111
'index.html': 'HTML',112
'page.xhtml': 'HTML',113
'index.php': 'PHP',114
'style.scss': 'SCSS',115
'style.sass': 'Sass (indented)',116
'app.mjs': 'JavaScript',117
'App.tsx': 'TypeScript',118
'data.jsonl': 'JSON Lines',119
'schema.xsd': 'XML',120
'compose.yml': 'YAML',121
'README.md': 'Markdown',122
'main.py': 'Python',123
'main.dart': 'Dart',124
'Main.kt': 'Kotlin',125
'lib.rs': 'Rust',126
'main.go': 'Go',127
'x.hpp': 'C++',128
'P.cs': 'C#',129
'a.rb': 'Ruby',130
'a.pm': 'Perl',131
'a.lua': 'Lua',132
'a.psm1': 'PowerShell',133
'a.zsh': 'Shell (Bash/sh/zsh)',134
'a.fish': 'fish',135
'q.sql': 'SQL',136
's.gql': 'GraphQL',137
'app.toml': 'TOML',138
'nginx.service': 'systemd unit',139
'app.desktop': 'systemd unit',140
'Info.plist': 'Property list (XML)',141
'.htaccess': 'Apache config',142
'.gitignore': 'Unix config',143
'.editorconfig': 'INI / config',144
'.env': '.env',145
'.env.production': '.env',146
'Dockerfile': 'Dockerfile',147
'Dockerfile.dev': 'Dockerfile',148
'Makefile': 'Makefile',149
'CMakeLists.txt': 'CMake',150
'nginx.conf': 'NGINX',151
'/etc/nginx/sites-available/site.conf': 'NGINX',152
'httpd.conf': 'Apache config',153
'sshd_config': 'SSH config',154
'/home/u/.ssh/config': 'SSH config',155
'hosts': 'Unix config',156
'fstab': 'Unix config',157
'crontab': 'Unix config',158
'.bashrc': 'Shell (Bash/sh/zsh)',159
'x.patch': 'Diff / patch',160
'main.tf': 'Terraform (HCL)',161
'build.gradle': 'Gradle',162
'a.proto': 'Protocol Buffers',163
'run.bat': 'Batch (cmd)',164
'server.pem': 'PEM / key / certificate',165
'notes.txt': 'Text',166
'app.log': 'Log',167
'table.tsv': 'CSV / TSV',168
};169
test('by name, extension and path', () {170
cases.forEach((name, label) {171
expect(detectSyntax(name).label, label, reason: name);172
});173
});174
test('files without extension: shebang and content', () {175
expect(176
detectSyntax('deploy', content: '#!/usr/bin/env bash\n').id,177
'bash',178
);179
expect(180
detectSyntax('tool', content: '#!/usr/bin/python3\n').id,181
'python',182
);183
expect(184
detectSyntax('unit', content: '[Unit]\nDescription=x\n').id,185
'systemd',186
);187
expect(detectSyntax('page', content: '<!DOCTYPE html><html>').id, 'html');188
expect(detectSyntax('README').id, 'text');189
});190
test('every highlighted syntax has a bundled grammar', () {191
for (final s in syntaxes) {192
if (s.grammar != null) {193
expect(grammars[s.grammar], isNotNull, reason: s.id);194
}195
}196
});197
test('viewer kinds', () {198
expect(fileKind('a.HEIC'), FileKind.image);199
expect(fileKind('a.svg'), FileKind.svg);200
expect(fileKind('a.docx'), FileKind.office);201
expect(fileKind('a.tar.gz'), FileKind.archive);202
expect(fileKind('a.ipynb'), FileKind.notebook);203
expect(fileKind('a.crt'), FileKind.certificate);204
expect(fileKind('a.mp4'), FileKind.video);205
expect(fileKind('blob', head: b([0x25, 0x50, 0x44, 0x46])), FileKind.pdf);206
expect(fileKind('nginx.conf'), FileKind.text);207
});208
});210
group('validation never changes the text', () {211
test('JSON, JSON Lines, YAML and XML report line and column', () {212
expect(validate('json', '{"a": [1, 2]}'), isNull);213
final j = validate('json', '{\n "a": 1,\n "b": }')!;214
expect(j.line, 3);215
expect(validate('jsonl', '{"a":1}\n{"b":\n')!.line, 2);216
expect(validate('yaml', 'a: 1\nb: [1, 2\n'), isNotNull);217
expect(validate('yaml', 'a: 1\nlist:\n - x\n'), isNull);218
final x = validate('xml', '<a>\n <b></a>')!;219
expect(x.line, isNotNull);220
expect(validate('xml', '<?xml version="1.0"?><a><b/></a>'), isNull);221
expect(validate('python', 'whatever'), isNull);222
});223
test('formatting is explicit and only for valid input', () {224
expect(225
formatText('json', '{"a":[1,2]}'),226
'{\n "a": [\n 1,\n 2\n ]\n}',227
);228
expect(formatText('json', '{"a":'), isNull);229
expect(formatText('xml', '<a><b/></a>', indent: 2), '<a>\n <b/>\n</a>');230
});231
});232
}SHA-256
f3eeb5dd0ad463382d282fcfe9d3998d133049d16244a95de6e3a9146942489bCH-J Proprietary Software License 1.14 · کد منبع تحت CH-J Proprietary Software License 1.14 ارائه میشود. در دسترس بودن آن شرایط مجوز را تغییر نمیدهد و حق اضافهای اعطا نمیکند.
SHA-256 بایگانی
46e427a43e87af091004f36145590bda8fe90086dfb0f631afeb5029fb0b5655