Files
proxypin/lib/utils/js_formatter.dart

212 lines
4.0 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class JS {
/// 格式化 JavaScript 字符串(适合还原压缩后的 JS
static String pretty(String input) {
if (input.trim().isEmpty) return input;
try {
final result = _JsFormatter(input).format();
return result.isEmpty ? input : result;
} catch (_) {
return input;
}
}
}
class _JsFormatter {
final String _src;
int _i = 0;
int _depth = 0;
final StringBuffer _buf = StringBuffer();
static const String _ind = ' ';
_JsFormatter(this._src);
String format() {
while (_i < _src.length) {
_step();
}
return _buf.toString().trim();
}
void _step() {
final c = _src[_i];
// Line comment
if (c == '/' && _peek(1) == '/') {
_readLineComment();
return;
}
// Block comment
if (c == '/' && _peek(1) == '*') {
_readBlockComment();
return;
}
// Template literal
if (c == '`') {
_readTemplateLiteral();
return;
}
// String literal
if (c == '"' || c == "'") {
_readString(c);
return;
}
// Open brace
if (c == '{') {
_trimTrailingSpace();
_buf.write(' {\n');
_depth++;
_writeIndent();
_i++;
_skipWs();
return;
}
// Close brace
if (c == '}') {
_trimTrailingSpace();
_depth = (_depth - 1).clamp(0, 100);
_buf.write('\n');
_writeIndent();
_buf.write('}');
_i++;
_skipWs();
// Don't add newline if followed by ; , )
if (_i < _src.length && _src[_i] != ';' && _src[_i] != ',' && _src[_i] != ')') {
_buf.writeln();
if (_depth > 0 && _i < _src.length) _writeIndent();
}
return;
}
// Semicolon
if (c == ';') {
_buf.write(';');
_i++;
_skipWs();
if (_i < _src.length && _src[_i] != '}') {
_buf.writeln();
_writeIndent();
}
return;
}
// Comma — keep on same line but normalize space after
if (c == ',') {
_buf.write(', ');
_i++;
_skipWs();
return;
}
// Whitespace normalization
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
final s = _buf.toString();
if (s.isNotEmpty) {
final last = s[s.length - 1];
if (last != ' ' && last != '\n') {
_buf.write(' ');
}
}
_i++;
return;
}
_buf.write(c);
_i++;
}
void _readLineComment() {
while (_i < _src.length && _src[_i] != '\n') {
_buf.write(_src[_i]);
_i++;
}
_buf.writeln();
_writeIndent();
}
void _readBlockComment() {
_buf.write('/*');
_i += 2;
while (_i < _src.length) {
if (_src[_i] == '*' && _peek(1) == '/') {
_buf.write('*/');
_i += 2;
break;
}
_buf.write(_src[_i]);
_i++;
}
}
void _readString(String quote) {
_buf.write(quote);
_i++;
while (_i < _src.length) {
final c = _src[_i];
if (c == '\\') {
_buf.write(c);
_i++;
if (_i < _src.length) {
_buf.write(_src[_i]);
_i++;
}
continue;
}
_buf.write(c);
_i++;
if (c == quote) break;
}
}
void _readTemplateLiteral() {
_buf.write('`');
_i++;
while (_i < _src.length) {
final c = _src[_i];
if (c == '\\') {
_buf.write(c);
_i++;
if (_i < _src.length) {
_buf.write(_src[_i]);
_i++;
}
continue;
}
if (c == '`') {
_buf.write(c);
_i++;
break;
}
_buf.write(c);
_i++;
}
}
void _trimTrailingSpace() {
final s = _buf.toString().trimRight();
_buf.clear();
_buf.write(s);
}
void _skipWs() {
while (_i < _src.length &&
(_src[_i] == ' ' || _src[_i] == '\t' || _src[_i] == '\n' || _src[_i] == '\r')) {
_i++;
}
}
void _writeIndent() {
_buf.write(_ind * _depth);
}
String? _peek(int offset) {
final idx = _i + offset;
return idx < _src.length ? _src[idx] : null;
}
}