mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-04-13 19:55:12 +08:00
158 lines
2.9 KiB
Dart
158 lines
2.9 KiB
Dart
class CSS {
|
|
/// 格式化 CSS 字符串
|
|
static String pretty(String input) {
|
|
if (input.trim().isEmpty || !input.contains('{')) return input;
|
|
try {
|
|
final result = _CssFormatter(input).format();
|
|
return result.isEmpty ? input : result;
|
|
} catch (_) {
|
|
return input;
|
|
}
|
|
}
|
|
}
|
|
|
|
class _CssFormatter {
|
|
final String _src;
|
|
int _i = 0;
|
|
int _depth = 0;
|
|
final StringBuffer _buf = StringBuffer();
|
|
static const String _ind = ' ';
|
|
|
|
_CssFormatter(this._src);
|
|
|
|
String format() {
|
|
while (_i < _src.length) {
|
|
_step();
|
|
}
|
|
return _buf.toString().trim();
|
|
}
|
|
|
|
void _step() {
|
|
final c = _src[_i];
|
|
|
|
// Block comment
|
|
if (c == '/' && _peek(1) == '*') {
|
|
_readComment();
|
|
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('}\n');
|
|
_i++;
|
|
_skipWs();
|
|
if (_depth > 0 && _i < _src.length) {
|
|
_buf.writeln();
|
|
_writeIndent();
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Semicolon
|
|
if (c == ';') {
|
|
_buf.write(';\n');
|
|
_i++;
|
|
_skipWs();
|
|
_writeIndent();
|
|
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 _readComment() {
|
|
_buf.write('/*');
|
|
_i += 2;
|
|
while (_i < _src.length) {
|
|
if (_src[_i] == '*' && _peek(1) == '/') {
|
|
_buf.write('*/');
|
|
_i += 2;
|
|
break;
|
|
}
|
|
_buf.write(_src[_i]);
|
|
_i++;
|
|
}
|
|
_buf.writeln();
|
|
_skipWs();
|
|
_writeIndent();
|
|
}
|
|
|
|
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 _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;
|
|
}
|
|
}
|
|
|