sdd-full 4.8.0 → 4.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +1 -1
- package/index.js +18 -12
- package/package.json +1 -1
- package/skills/VERSION.md +61 -175
- package/skills/design-planning/ai-coding-rules/SKILL.md +13 -5
- package/skills/design-planning/design-to-code/SKILL.md +14 -5
- package/skills/design-planning/enterprise-spec/SKILL.md +13 -5
- package/skills/design-planning/flutter-av/SKILL.md +16 -5
- package/skills/design-planning/flutter-map/SKILL.md +14 -5
- package/skills/design-planning/function-sdd/SKILL.md +13 -5
- package/skills/design-planning/global-overlay-stack-standard/SKILL.md +14 -4
- package/skills/design-planning/ui-motion-interaction-standard/SKILL.md +14 -4
- package/skills/design-planning/ui-sdd-specialized/SKILL.md +14 -5
- package/skills/development-execution/flutter-errors/SKILL.md +15 -5
- package/skills/quality-assurance/bdd-acceptance/SKILL.md +14 -5
- package/skills/quality-assurance/flutter-test/SKILL.md +16 -5
- package/skills/requirement-analysis/sdd/mock_sdd.md +156 -0
- package/skills/rules/project_rules.md +127 -538
- package/skills/rules/user_rules.md +263 -0
- package/skills/special-tools/env-check/SKILL.md +13 -5
- package/skills/special-tools/ios-full-auto-debug/SKILL.md +15 -5
- package/skills/flutter-skills/.github/dependabot.yaml +0 -15
- package/skills/flutter-skills/.github/workflows/dart_skills_lint_workflow.yaml +0 -68
- package/skills/flutter-skills/.github/workflows/skills_tool.yaml +0 -51
- package/skills/flutter-skills/CODE_OF_CONDUCT.md +0 -3
- package/skills/flutter-skills/CONTRIBUTING.md +0 -36
- package/skills/flutter-skills/LICENSE +0 -26
- package/skills/flutter-skills/README.md +0 -50
- package/skills/flutter-skills/pubspec.yaml +0 -9
- package/skills/flutter-skills/resources/flutter_skills.yaml +0 -434
- package/skills/flutter-skills/skills/flutter-add-integration-test/SKILL.md +0 -163
- package/skills/flutter-skills/skills/flutter-add-widget-preview/SKILL.md +0 -145
- package/skills/flutter-skills/skills/flutter-add-widget-test/SKILL.md +0 -154
- package/skills/flutter-skills/skills/flutter-apply-architecture-best-practices/SKILL.md +0 -162
- package/skills/flutter-skills/skills/flutter-build-responsive-layout/SKILL.md +0 -139
- package/skills/flutter-skills/skills/flutter-fix-layout-issues/SKILL.md +0 -130
- package/skills/flutter-skills/skills/flutter-implement-json-serialization/SKILL.md +0 -153
- package/skills/flutter-skills/skills/flutter-setup-declarative-routing/SKILL.md +0 -255
- package/skills/flutter-skills/skills/flutter-setup-localization/SKILL.md +0 -210
- package/skills/flutter-skills/skills/flutter-use-http-package/SKILL.md +0 -175
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/add-dart-lint-validation-rule/SKILL.md +0 -196
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-best-practices/SKILL.md +0 -65
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-checks-migration/SKILL.md +0 -158
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-cli-app-best-practices/SKILL.md +0 -168
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-doc-validation/SKILL.md +0 -87
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-long-lines/SKILL.md +0 -101
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-matcher-best-practices/SKILL.md +0 -136
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-modern-features/SKILL.md +0 -266
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-package-maintenance/SKILL.md +0 -92
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/SKILL.md +0 -92
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/lib/src/calculator.dart +0 -7
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/pubspec.yaml +0 -8
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/example/test/calculator_test.dart +0 -11
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/interpret_coverage.dart +0 -95
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/pubspec.yaml +0 -6
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-coverage/scripts/test/interpret_coverage_test.dart +0 -93
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/dart-test-fundamentals/SKILL.md +0 -173
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/definition-of-done/SKILL.md +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/flutter_skills_ignore.json +0 -3
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/grill-me/SKILL.md +0 -10
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/ignore.json +0 -3
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/test-driven-development/SKILL.md +0 -371
- package/skills/flutter-skills/tool/dart_skills_lint/.agents/skills/test-driven-development/testing-anti-patterns.md +0 -299
- package/skills/flutter-skills/tool/dart_skills_lint/AUTHORS +0 -7
- package/skills/flutter-skills/tool/dart_skills_lint/CHANGELOG.md +0 -12
- package/skills/flutter-skills/tool/dart_skills_lint/CONTRIBUTING.md +0 -51
- package/skills/flutter-skills/tool/dart_skills_lint/LICENSE +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/README.md +0 -203
- package/skills/flutter-skills/tool/dart_skills_lint/analysis_options.yaml +0 -296
- package/skills/flutter-skills/tool/dart_skills_lint/bench/README.md +0 -23
- package/skills/flutter-skills/tool/dart_skills_lint/bench/baseline_throughput.dart +0 -230
- package/skills/flutter-skills/tool/dart_skills_lint/bin/cli.dart +0 -10
- package/skills/flutter-skills/tool/dart_skills_lint/dart_skills_lint.yaml +0 -14
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/PRODUCTION_READYNESS.md +0 -48
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/completion_migration_plan.md +0 -99
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/legacy_patterns_report.md +0 -110
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/feature_design_docs/pub_vs_skill_report.md +0 -56
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/knowledge/SPECIFICATION.md +0 -79
- package/skills/flutter-skills/tool/dart_skills_lint/documentation/knowledge/architecture_overview.md +0 -64
- package/skills/flutter-skills/tool/dart_skills_lint/lib/dart_skills_lint.dart +0 -11
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/config_parser.dart +0 -156
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/entry_point.dart +0 -354
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/fixable_rule.dart +0 -20
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/analysis_severity.dart +0 -15
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/check_type.dart +0 -17
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/ignore_entry.dart +0 -34
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/ignore_entry.g.dart +0 -19
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skill_context.dart +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skill_rule.dart +0 -27
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skills_ignores.dart +0 -26
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/skills_ignores.g.dart +0 -24
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/models/validation_error.dart +0 -31
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rule_registry.dart +0 -79
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/absolute_paths_rule.dart +0 -74
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/description_length_rule.dart +0 -49
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/disallowed_field_rule.dart +0 -61
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/name_format_rule.dart +0 -167
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/relative_paths_rule.dart +0 -72
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/trailing_whitespace_rule.dart +0 -93
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/rules/valid_yaml_metadata_rule.dart +0 -74
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/skills_ignores_storage.dart +0 -36
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/validation_session.dart +0 -559
- package/skills/flutter-skills/tool/dart_skills_lint/lib/src/validator.dart +0 -238
- package/skills/flutter-skills/tool/dart_skills_lint/pubspec.yaml +0 -28
- package/skills/flutter-skills/tool/dart_skills_lint/skills/README.md +0 -10
- package/skills/flutter-skills/tool/dart_skills_lint/skills/dart-skills-lint-validation/SKILL.md +0 -195
- package/skills/flutter-skills/tool/dart_skills_lint/skills-lock.json +0 -75
- package/skills/flutter-skills/tool/dart_skills_lint/test/absolute_paths_test.dart +0 -167
- package/skills/flutter-skills/tool/dart_skills_lint/test/cli_integration_test.dart +0 -683
- package/skills/flutter-skills/tool/dart_skills_lint/test/config_file_test.dart +0 -292
- package/skills/flutter-skills/tool/dart_skills_lint/test/custom_rule_test.dart +0 -122
- package/skills/flutter-skills/tool/dart_skills_lint/test/directory_structure_test.dart +0 -163
- package/skills/flutter-skills/tool/dart_skills_lint/test/field_constraints_test.dart +0 -178
- package/skills/flutter-skills/tool/dart_skills_lint/test/fixer_test.dart +0 -172
- package/skills/flutter-skills/tool/dart_skills_lint/test/ignore_models_test.dart +0 -63
- package/skills/flutter-skills/tool/dart_skills_lint/test/metadata_validation_test.dart +0 -116
- package/skills/flutter-skills/tool/dart_skills_lint/test/relative_path_flag_test.dart +0 -70
- package/skills/flutter-skills/tool/dart_skills_lint/test/relative_paths_test.dart +0 -172
- package/skills/flutter-skills/tool/dart_skills_lint/test/resolve_rules_test.dart +0 -82
- package/skills/flutter-skills/tool/dart_skills_lint/test/rule_naming_test.dart +0 -29
- package/skills/flutter-skills/tool/dart_skills_lint/test/skills_ignores_storage_test.dart +0 -89
- package/skills/flutter-skills/tool/dart_skills_lint/test/test_utils.dart +0 -19
- package/skills/flutter-skills/tool/dart_skills_lint/test/trailing_whitespace_test.dart +0 -152
- package/skills/flutter-skills/tool/generator/README.md +0 -150
- package/skills/flutter-skills/tool/generator/analysis_options.yaml +0 -143
- package/skills/flutter-skills/tool/generator/bin/skills.dart +0 -73
- package/skills/flutter-skills/tool/generator/lib/src/commands/base_skill_command.dart +0 -87
- package/skills/flutter-skills/tool/generator/lib/src/commands/base_yaml_command.dart +0 -83
- package/skills/flutter-skills/tool/generator/lib/src/commands/generate_skill_command.dart +0 -92
- package/skills/flutter-skills/tool/generator/lib/src/commands/update_readme_command.dart +0 -150
- package/skills/flutter-skills/tool/generator/lib/src/commands/update_skill_command.dart +0 -97
- package/skills/flutter-skills/tool/generator/lib/src/commands/validate_skill_command.dart +0 -284
- package/skills/flutter-skills/tool/generator/lib/src/models/skill_params.dart +0 -41
- package/skills/flutter-skills/tool/generator/lib/src/services/gemini_service.dart +0 -310
- package/skills/flutter-skills/tool/generator/lib/src/services/markdown_converter.dart +0 -226
- package/skills/flutter-skills/tool/generator/lib/src/services/prompts.dart +0 -72
- package/skills/flutter-skills/tool/generator/lib/src/services/resource_fetcher_service.dart +0 -84
- package/skills/flutter-skills/tool/generator/lib/src/services/skill_instructions.dart +0 -30
- package/skills/flutter-skills/tool/generator/pubspec.yaml +0 -32
- package/skills/flutter-skills/tool/generator/test/commands/base_skill_command_test.dart +0 -131
- package/skills/flutter-skills/tool/generator/test/commands/validate_skills_input_test.dart +0 -263
- package/skills/flutter-skills/tool/generator/test/custom_skill_rules/last_modified_rule.dart +0 -32
- package/skills/flutter-skills/tool/generator/test/generate_skills_retry_test.dart +0 -105
- package/skills/flutter-skills/tool/generator/test/generate_skills_test.dart +0 -519
- package/skills/flutter-skills/tool/generator/test/lint_skills_test.dart +0 -34
- package/skills/flutter-skills/tool/generator/test/markdown_converter_test.dart +0 -103
- package/skills/flutter-skills/tool/generator/test/markdown_table_test.dart +0 -131
- package/skills/flutter-skills/tool/generator/test/models/skill_params_test.dart +0 -37
- package/skills/flutter-skills/tool/generator/test/services/gemini_service_test.dart +0 -291
- package/skills/flutter-skills/tool/generator/test/services/markdown_converter_test.dart +0 -156
- package/skills/flutter-skills/tool/generator/test/services/resource_fetcher_service_test.dart +0 -188
- package/skills/flutter-skills/tool/generator/test/update_skills_test.dart +0 -241
- package/skills/flutter-skills/tool/generator/test/validate_skills_test.dart +0 -728
- /package/skills/{.agents → flutter}/skills/flutter-add-integration-test/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-add-widget-preview/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-add-widget-test/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-apply-architecture-best-practices/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-build-responsive-layout/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-fix-layout-issues/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-implement-json-serialization/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-setup-declarative-routing/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-setup-localization/SKILL.md +0 -0
- /package/skills/{.agents → flutter}/skills/flutter-use-http-package/SKILL.md +0 -0
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
|
|
2
|
-
// for details. All rights reserved. Use of this source code is governed by a
|
|
3
|
-
// BSD-style license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
import 'dart:io';
|
|
6
|
-
|
|
7
|
-
import 'package:dart_skills_lint/src/models/analysis_severity.dart';
|
|
8
|
-
import 'package:dart_skills_lint/src/rules/absolute_paths_rule.dart';
|
|
9
|
-
import 'package:dart_skills_lint/src/rules/relative_paths_rule.dart';
|
|
10
|
-
import 'package:dart_skills_lint/src/validator.dart';
|
|
11
|
-
import 'package:test/test.dart';
|
|
12
|
-
|
|
13
|
-
import 'test_utils.dart';
|
|
14
|
-
|
|
15
|
-
void main() {
|
|
16
|
-
group('Relative Paths Validation', () {
|
|
17
|
-
late Directory tempDir;
|
|
18
|
-
|
|
19
|
-
setUp(() async {
|
|
20
|
-
tempDir = await Directory.systemTemp.createTemp('paths_test.');
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
tearDown(() async {
|
|
24
|
-
if (tempDir.existsSync()) {
|
|
25
|
-
await tempDir.delete(recursive: true);
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('passes with valid relative file path (existing file)', () async {
|
|
30
|
-
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
|
|
31
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
32
|
-
'${buildFrontmatter(name: 'test-skill')}[Link to a reference](references/DETAILS.md)\n',
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
final Directory refDir = await Directory('${skillDir.path}/references').create();
|
|
36
|
-
await File('${refDir.path}/DETAILS.md').writeAsString('Details here');
|
|
37
|
-
|
|
38
|
-
final validator = Validator(
|
|
39
|
-
ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
|
|
40
|
-
);
|
|
41
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
42
|
-
|
|
43
|
-
expect(result.isValid, isTrue);
|
|
44
|
-
expect(result.errors, isEmpty);
|
|
45
|
-
expect(result.warnings, isEmpty);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('warns with missing relative file path', () async {
|
|
49
|
-
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
|
|
50
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
51
|
-
'${buildFrontmatter(name: 'test-skill')}[Link to a references file missing](references/MISSING.md)\n',
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
final validator = Validator(
|
|
55
|
-
ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
|
|
56
|
-
);
|
|
57
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
58
|
-
|
|
59
|
-
expect(result.isValid, isTrue);
|
|
60
|
-
expect(result.warnings, contains(contains('Linked file does not exist')));
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test('fails with absolute file path', () async {
|
|
64
|
-
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
|
|
65
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
66
|
-
'${buildFrontmatter(name: 'test-skill')}[Absolute path link](/tmp/some_absolute_path/file.md)\n',
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
final validator = Validator(
|
|
70
|
-
ruleOverrides: {
|
|
71
|
-
RelativePathsRule.ruleName: AnalysisSeverity.warning,
|
|
72
|
-
AbsolutePathsRule.ruleName: AnalysisSeverity.error,
|
|
73
|
-
},
|
|
74
|
-
);
|
|
75
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
76
|
-
|
|
77
|
-
expect(result.isValid, isFalse);
|
|
78
|
-
expect(result.errors, contains(contains('Absolute filepath found in link')));
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test('ignores web URLs, emails, javascript, data URIs, and anchors', () async {
|
|
82
|
-
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
|
|
83
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
84
|
-
'${buildFrontmatter(name: 'test-skill')}- [Web link](http://example.com)\n- [Web TLS link](https://example.com)\n- [Email link](mailto:user@domain.com)\n- [JS link](javascript:alert(1))\n- [Data URI](data:image/png;base64,iVBORw)\n- [Anchor link](#section-name)\n',
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
final validator = Validator(
|
|
88
|
-
ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
|
|
89
|
-
);
|
|
90
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
91
|
-
|
|
92
|
-
expect(result.isValid, isTrue);
|
|
93
|
-
expect(result.errors, isEmpty);
|
|
94
|
-
expect(result.warnings, isEmpty); // None of these should trigger local file checks
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('passes with valid relative image path and title', () async {
|
|
98
|
-
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
|
|
99
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
100
|
-
'${buildFrontmatter(name: 'test-skill')}\n',
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
final Directory imgDir = await Directory('${skillDir.path}/images').create();
|
|
104
|
-
await File('${imgDir.path}/screenshot.png').writeAsString('image content');
|
|
105
|
-
|
|
106
|
-
final validator = Validator(
|
|
107
|
-
ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
|
|
108
|
-
);
|
|
109
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
110
|
-
|
|
111
|
-
expect(result.isValid, isTrue);
|
|
112
|
-
expect(result.errors, isEmpty);
|
|
113
|
-
expect(result.warnings, isEmpty);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test('passes with relative path containing line fragments', () async {
|
|
117
|
-
final Directory skillDir = await Directory(
|
|
118
|
-
'${tempDir.path}/a/b/c/test-skill',
|
|
119
|
-
).create(recursive: true);
|
|
120
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
121
|
-
'${buildFrontmatter(name: 'test-skill')}[Link to lines](../../../CONTRIBUTING.md#L64-L80)\n',
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
await File('${tempDir.path}/a/CONTRIBUTING.md').create(recursive: true);
|
|
125
|
-
|
|
126
|
-
final validator = Validator(
|
|
127
|
-
ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
|
|
128
|
-
);
|
|
129
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
130
|
-
|
|
131
|
-
expect(result.isValid, isTrue);
|
|
132
|
-
expect(result.errors, isEmpty);
|
|
133
|
-
expect(result.warnings, isEmpty);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('passes with relative path containing anchor fragments', () async {
|
|
137
|
-
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
|
|
138
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
139
|
-
'${buildFrontmatter(name: 'test-skill')}[Link to section](styleguide.md#miscellaneous-languages)\n',
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
await File('${skillDir.path}/styleguide.md').writeAsString('Styleguide content');
|
|
143
|
-
|
|
144
|
-
final validator = Validator(
|
|
145
|
-
ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
|
|
146
|
-
);
|
|
147
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
148
|
-
|
|
149
|
-
expect(result.isValid, isTrue);
|
|
150
|
-
expect(result.errors, isEmpty);
|
|
151
|
-
expect(result.warnings, isEmpty);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test('passes with leading and trailing whitespace in link', () async {
|
|
155
|
-
final Directory skillDir = await Directory('${tempDir.path}/test-skill').create();
|
|
156
|
-
await File('${skillDir.path}/SKILL.md').writeAsString(
|
|
157
|
-
'${buildFrontmatter(name: 'test-skill')}[Link with whitespace]( styleguide.md )\n',
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
await File('${skillDir.path}/styleguide.md').writeAsString('Styleguide content');
|
|
161
|
-
|
|
162
|
-
final validator = Validator(
|
|
163
|
-
ruleOverrides: {RelativePathsRule.ruleName: AnalysisSeverity.warning},
|
|
164
|
-
);
|
|
165
|
-
final ValidationResult result = await validator.validate(skillDir);
|
|
166
|
-
|
|
167
|
-
expect(result.isValid, isTrue);
|
|
168
|
-
expect(result.errors, isEmpty);
|
|
169
|
-
expect(result.warnings, isEmpty);
|
|
170
|
-
});
|
|
171
|
-
});
|
|
172
|
-
}
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
|
|
2
|
-
// for details. All rights reserved. Use of this source code is governed by a
|
|
3
|
-
// BSD-style license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
import 'package:args/args.dart';
|
|
6
|
-
import 'package:dart_skills_lint/src/config_parser.dart';
|
|
7
|
-
import 'package:dart_skills_lint/src/entry_point.dart';
|
|
8
|
-
import 'package:dart_skills_lint/src/models/analysis_severity.dart';
|
|
9
|
-
import 'package:dart_skills_lint/src/models/check_type.dart';
|
|
10
|
-
import 'package:dart_skills_lint/src/rule_registry.dart';
|
|
11
|
-
import 'package:dart_skills_lint/src/rules/absolute_paths_rule.dart';
|
|
12
|
-
import 'package:dart_skills_lint/src/rules/description_length_rule.dart';
|
|
13
|
-
import 'package:dart_skills_lint/src/rules/disallowed_field_rule.dart';
|
|
14
|
-
import 'package:dart_skills_lint/src/rules/name_format_rule.dart';
|
|
15
|
-
import 'package:dart_skills_lint/src/rules/relative_paths_rule.dart';
|
|
16
|
-
import 'package:dart_skills_lint/src/rules/valid_yaml_metadata_rule.dart';
|
|
17
|
-
import 'package:test/test.dart';
|
|
18
|
-
|
|
19
|
-
void main() {
|
|
20
|
-
group('resolveRules', () {
|
|
21
|
-
ArgParser createParser() {
|
|
22
|
-
final parser = ArgParser();
|
|
23
|
-
for (final CheckType check in RuleRegistry.allChecks) {
|
|
24
|
-
parser.addFlag(check.name, defaultsTo: check.defaultSeverity != AnalysisSeverity.disabled);
|
|
25
|
-
}
|
|
26
|
-
return parser;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
test('returns defaults when no args and empty config', () {
|
|
30
|
-
final ArgResults results = createParser().parse([]);
|
|
31
|
-
final config = Configuration();
|
|
32
|
-
|
|
33
|
-
final Map<String, AnalysisSeverity> resolved = resolveRules(results, config);
|
|
34
|
-
|
|
35
|
-
expect(resolved[RelativePathsRule.ruleName], RelativePathsRule.defaultSeverity);
|
|
36
|
-
expect(resolved[AbsolutePathsRule.ruleName], AbsolutePathsRule.defaultSeverity);
|
|
37
|
-
expect(resolved[DisallowedFieldRule.ruleName], DisallowedFieldRule.defaultSeverity);
|
|
38
|
-
expect(resolved[ValidYamlMetadataRule.ruleName], ValidYamlMetadataRule.defaultSeverity);
|
|
39
|
-
expect(resolved[DescriptionLengthRule.ruleName], DescriptionLengthRule.defaultSeverity);
|
|
40
|
-
expect(resolved[NameFormatRule.ruleName], NameFormatRule.defaultSeverity);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('config overrides defaults', () {
|
|
44
|
-
final ArgResults results = createParser().parse([]);
|
|
45
|
-
final config = Configuration(
|
|
46
|
-
configuredRules: {
|
|
47
|
-
RelativePathsRule.ruleName: AnalysisSeverity.error,
|
|
48
|
-
AbsolutePathsRule.ruleName: AnalysisSeverity.warning,
|
|
49
|
-
},
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
final Map<String, AnalysisSeverity> resolved = resolveRules(results, config);
|
|
53
|
-
|
|
54
|
-
expect(resolved[RelativePathsRule.ruleName], AnalysisSeverity.error);
|
|
55
|
-
expect(resolved[AbsolutePathsRule.ruleName], AnalysisSeverity.warning);
|
|
56
|
-
// Others should remain default
|
|
57
|
-
expect(resolved[DisallowedFieldRule.ruleName], DisallowedFieldRule.defaultSeverity);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('CLI flags override config and defaults', () {
|
|
61
|
-
final ArgResults results = createParser().parse(['--${RelativePathsRule.ruleName}']);
|
|
62
|
-
final config = Configuration(
|
|
63
|
-
configuredRules: {RelativePathsRule.ruleName: AnalysisSeverity.error},
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
final Map<String, AnalysisSeverity> resolved = resolveRules(results, config);
|
|
67
|
-
|
|
68
|
-
expect(resolved[RelativePathsRule.ruleName], AnalysisSeverity.error);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test('CLI flag disabled overrides config', () {
|
|
72
|
-
final ArgResults results = createParser().parse(['--no-${ValidYamlMetadataRule.ruleName}']);
|
|
73
|
-
final config = Configuration(
|
|
74
|
-
configuredRules: {ValidYamlMetadataRule.ruleName: AnalysisSeverity.warning},
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
final Map<String, AnalysisSeverity> resolved = resolveRules(results, config);
|
|
78
|
-
|
|
79
|
-
expect(resolved[ValidYamlMetadataRule.ruleName], AnalysisSeverity.disabled);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import 'package:dart_skills_lint/dart_skills_lint.dart';
|
|
2
|
-
import 'package:dart_skills_lint/src/rules/absolute_paths_rule.dart';
|
|
3
|
-
import 'package:dart_skills_lint/src/rules/description_length_rule.dart';
|
|
4
|
-
import 'package:dart_skills_lint/src/rules/disallowed_field_rule.dart';
|
|
5
|
-
import 'package:dart_skills_lint/src/rules/name_format_rule.dart';
|
|
6
|
-
import 'package:dart_skills_lint/src/rules/relative_paths_rule.dart';
|
|
7
|
-
import 'package:dart_skills_lint/src/rules/valid_yaml_metadata_rule.dart';
|
|
8
|
-
import 'package:test/test.dart';
|
|
9
|
-
|
|
10
|
-
void main() {
|
|
11
|
-
group('Rule Naming Conventions', () {
|
|
12
|
-
final List<SkillRule> rules = [
|
|
13
|
-
AbsolutePathsRule(),
|
|
14
|
-
DescriptionLengthRule(),
|
|
15
|
-
DisallowedFieldRule(),
|
|
16
|
-
NameFormatRule(),
|
|
17
|
-
RelativePathsRule(),
|
|
18
|
-
ValidYamlMetadataRule(),
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
final kebabCaseRegex = RegExp(r'^[a-z0-9]+(-[a-z0-9]+)*$');
|
|
22
|
-
|
|
23
|
-
for (final rule in rules) {
|
|
24
|
-
test('Rule "${rule.runtimeType}" has valid kebab-case name', () {
|
|
25
|
-
expect(rule.name, matches(kebabCaseRegex));
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
|
|
2
|
-
// for details. All rights reserved. Use of this source code is governed by a
|
|
3
|
-
// BSD-style license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
import 'dart:io';
|
|
6
|
-
|
|
7
|
-
import 'package:dart_skills_lint/src/models/skills_ignores.dart';
|
|
8
|
-
import 'package:dart_skills_lint/src/skills_ignores_storage.dart';
|
|
9
|
-
import 'package:test/test.dart';
|
|
10
|
-
|
|
11
|
-
void main() {
|
|
12
|
-
late Directory tempDir;
|
|
13
|
-
late SkillsIgnoresStorage storage;
|
|
14
|
-
|
|
15
|
-
setUp(() async {
|
|
16
|
-
tempDir = Directory.systemTemp.createTempSync('storage_test.');
|
|
17
|
-
storage = SkillsIgnoresStorage();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
tearDown(() async {
|
|
21
|
-
await tempDir.delete(recursive: true);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
group('SkillsIgnoresStorage.load Integration', () {
|
|
25
|
-
test('inflates empty JSON into empty skills map', () async {
|
|
26
|
-
final file = File('${tempDir.path}/empty.json');
|
|
27
|
-
await file.writeAsString('{}');
|
|
28
|
-
|
|
29
|
-
final SkillsIgnores ignores = await storage.load(file.path);
|
|
30
|
-
expect(ignores.skills.isEmpty, isTrue);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('inflates single skill with 1 ignore', () async {
|
|
34
|
-
final file = File('${tempDir.path}/one_ignore.json');
|
|
35
|
-
await file.writeAsString('''
|
|
36
|
-
{
|
|
37
|
-
"skills": {
|
|
38
|
-
"skill-a": [
|
|
39
|
-
{"rule_id": "rule1", "file_name": "file1.md"}
|
|
40
|
-
]
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
''');
|
|
44
|
-
|
|
45
|
-
final SkillsIgnores ignores = await storage.load(file.path);
|
|
46
|
-
expect(ignores.skills.containsKey('skill-a'), isTrue);
|
|
47
|
-
expect(ignores.skills['skill-a']!.length, equals(1));
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test('inflates single skill with 2 ignores', () async {
|
|
51
|
-
final file = File('${tempDir.path}/two_ignores.json');
|
|
52
|
-
await file.writeAsString('''
|
|
53
|
-
{
|
|
54
|
-
"skills": {
|
|
55
|
-
"skill-a": [
|
|
56
|
-
{"rule_id": "rule1", "file_name": "file1.md"},
|
|
57
|
-
{"rule_id": "rule2", "file_name": "file1.md"}
|
|
58
|
-
]
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
''');
|
|
62
|
-
|
|
63
|
-
final SkillsIgnores ignores = await storage.load(file.path);
|
|
64
|
-
expect(ignores.skills.containsKey('skill-a'), isTrue);
|
|
65
|
-
expect(ignores.skills['skill-a']!.length, equals(2));
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test('inflates three skills with varied ignores', () async {
|
|
69
|
-
final file = File('${tempDir.path}/three_skills.json');
|
|
70
|
-
await file.writeAsString('''
|
|
71
|
-
{
|
|
72
|
-
"skills": {
|
|
73
|
-
"skill-a": [{"rule_id": "rule1", "file_name": "file1.md"}],
|
|
74
|
-
"skill-b": [{"rule_id": "rule1", "file_name": "file1.md"}, {"rule_id": "rule2", "file_name": "file1.md"}],
|
|
75
|
-
"skill-c": [{"rule_id": "rule1", "file_name": "file1.md"}, {"rule_id": "rule2", "file_name": "file1.md"}, {"rule_id": "rule3", "file_name": "file1.md"}]
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
''');
|
|
79
|
-
|
|
80
|
-
final SkillsIgnores ignores = await storage.load(file.path);
|
|
81
|
-
expect(ignores.skills.containsKey('skill-a'), isTrue);
|
|
82
|
-
expect(ignores.skills.containsKey('skill-b'), isTrue);
|
|
83
|
-
expect(ignores.skills.containsKey('skill-c'), isTrue);
|
|
84
|
-
expect(ignores.skills['skill-a']!.length, equals(1));
|
|
85
|
-
expect(ignores.skills['skill-b']!.length, equals(2));
|
|
86
|
-
expect(ignores.skills['skill-c']!.length, equals(3));
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
|
|
2
|
-
// for details. All rights reserved. Use of this source code is governed by a
|
|
3
|
-
// BSD-style license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
String buildFrontmatter({
|
|
6
|
-
String name = 'Skill-Name',
|
|
7
|
-
String description = 'A test skill',
|
|
8
|
-
String? compatibility,
|
|
9
|
-
}) {
|
|
10
|
-
final sb = StringBuffer();
|
|
11
|
-
sb.writeln('---');
|
|
12
|
-
sb.writeln('name: $name');
|
|
13
|
-
sb.writeln('description: $description');
|
|
14
|
-
if (compatibility != null) {
|
|
15
|
-
sb.writeln('compatibility: $compatibility');
|
|
16
|
-
}
|
|
17
|
-
sb.writeln('---');
|
|
18
|
-
return sb.toString();
|
|
19
|
-
}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
|
|
2
|
-
// for details. All rights reserved. Use of this source code is governed by a
|
|
3
|
-
// BSD-style license that can be found in the LICENSE file.
|
|
4
|
-
|
|
5
|
-
import 'dart:io';
|
|
6
|
-
|
|
7
|
-
import 'package:dart_skills_lint/src/models/analysis_severity.dart';
|
|
8
|
-
import 'package:dart_skills_lint/src/models/skill_context.dart';
|
|
9
|
-
import 'package:dart_skills_lint/src/models/validation_error.dart';
|
|
10
|
-
import 'package:dart_skills_lint/src/rules/trailing_whitespace_rule.dart';
|
|
11
|
-
import 'package:test/test.dart';
|
|
12
|
-
|
|
13
|
-
import 'test_utils.dart';
|
|
14
|
-
|
|
15
|
-
void main() {
|
|
16
|
-
group('Trailing Whitespace Validation', () {
|
|
17
|
-
test('passes for line with no trailing whitespace', () async {
|
|
18
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
19
|
-
final context = SkillContext(
|
|
20
|
-
directory: Directory('dummy'),
|
|
21
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')}Line without trailing whitespace\n',
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
25
|
-
|
|
26
|
-
expect(errors, isEmpty);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('passes for line with exactly 2 trailing spaces (hard line break)', () async {
|
|
30
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
31
|
-
final context = SkillContext(
|
|
32
|
-
directory: Directory('dummy'),
|
|
33
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')}Line with 2 spaces \nNext line\n',
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
37
|
-
|
|
38
|
-
expect(errors, isEmpty);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('flags line with 1 trailing space as warning', () async {
|
|
42
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
43
|
-
final context = SkillContext(
|
|
44
|
-
directory: Directory('dummy'),
|
|
45
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')}Line with 1 space \n',
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
49
|
-
|
|
50
|
-
expect(errors.any((e) => e.message.contains('has 1 trailing space(s)')), isTrue);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('flags line with 3 trailing spaces as warning', () async {
|
|
54
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
55
|
-
final context = SkillContext(
|
|
56
|
-
directory: Directory('dummy'),
|
|
57
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')}Line with 3 spaces \n',
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
61
|
-
|
|
62
|
-
expect(errors.any((e) => e.message.contains('has 3 trailing space(s)')), isTrue);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('flags line with trailing tabs as warning', () async {
|
|
66
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
67
|
-
final context = SkillContext(
|
|
68
|
-
directory: Directory('dummy'),
|
|
69
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')}Line with tab\t\n',
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
73
|
-
|
|
74
|
-
expect(errors.any((e) => e.message.contains('trailing whitespace containing tabs')), isTrue);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('respects severity setting', () async {
|
|
78
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.error);
|
|
79
|
-
final context = SkillContext(
|
|
80
|
-
directory: Directory('dummy'),
|
|
81
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')}Line with 1 space \n',
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
85
|
-
|
|
86
|
-
expect(errors.length, 1);
|
|
87
|
-
expect(errors.first.severity, AnalysisSeverity.error);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test(
|
|
91
|
-
r'flags line with 1 trailing space before Windows line ending (\r\n) as warning',
|
|
92
|
-
() async {
|
|
93
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
94
|
-
final context = SkillContext(
|
|
95
|
-
directory: Directory('dummy'),
|
|
96
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')}Line with 1 space \r\n',
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
100
|
-
|
|
101
|
-
expect(errors.any((e) => e.message.contains('has 1 trailing space(s)')), isTrue);
|
|
102
|
-
},
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
test('flags line containing only whitespace (3 spaces) as warning', () async {
|
|
106
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
107
|
-
final context = SkillContext(
|
|
108
|
-
directory: Directory('dummy'),
|
|
109
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')} \n',
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
113
|
-
|
|
114
|
-
expect(errors.any((e) => e.message.contains('has 3 trailing space(s)')), isTrue);
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
test('passes for line containing only 2 spaces', () async {
|
|
118
|
-
final rule = TrailingWhitespaceRule(severity: AnalysisSeverity.warning);
|
|
119
|
-
final context = SkillContext(
|
|
120
|
-
directory: Directory('dummy'),
|
|
121
|
-
rawContent: '${buildFrontmatter(name: 'test-skill')} \n',
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
final List<ValidationError> errors = await rule.validate(context);
|
|
125
|
-
|
|
126
|
-
expect(errors, isEmpty);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
group('Trailing Whitespace Fix', () {
|
|
130
|
-
test('removes trailing whitespace', () {
|
|
131
|
-
final rule = TrailingWhitespaceRule();
|
|
132
|
-
|
|
133
|
-
expect(rule.fixLine('Line with 1 space '), 'Line with 1 space');
|
|
134
|
-
expect(rule.fixLine('Line with 3 spaces '), 'Line with 3 spaces');
|
|
135
|
-
expect(rule.fixLine('Line with tab\t'), 'Line with tab');
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test('keeps exactly 2 spaces', () {
|
|
139
|
-
final rule = TrailingWhitespaceRule();
|
|
140
|
-
|
|
141
|
-
expect(rule.fixLine('Line with 2 spaces '), 'Line with 2 spaces ');
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test('handles Windows line endings', () {
|
|
145
|
-
final rule = TrailingWhitespaceRule();
|
|
146
|
-
|
|
147
|
-
expect(rule.fixLine('Line with 1 space \r'), 'Line with 1 space\r');
|
|
148
|
-
expect(rule.fixLine('Line with 3 spaces \r'), 'Line with 3 spaces\r');
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
}
|