sdd-full 4.8.0 → 4.8.2
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 +2 -2
- package/index.js +18 -12
- package/package.json +1 -1
- package/skills/README.md +155 -47
- 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/VERSION.md +0 -310
- 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,131 +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:skills/src/services/markdown_converter.dart';
|
|
6
|
-
import 'package:test/test.dart';
|
|
7
|
-
|
|
8
|
-
void main() {
|
|
9
|
-
group('MarkdownConverter Tables', () {
|
|
10
|
-
late MarkdownConverter converter;
|
|
11
|
-
|
|
12
|
-
setUp(() {
|
|
13
|
-
converter = MarkdownConverter();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('converts simple table', () {
|
|
17
|
-
const html = '''
|
|
18
|
-
<table>
|
|
19
|
-
<thead>
|
|
20
|
-
<tr>
|
|
21
|
-
<th>Header 1</th>
|
|
22
|
-
<th>Header 2</th>
|
|
23
|
-
</tr>
|
|
24
|
-
</thead>
|
|
25
|
-
<tbody>
|
|
26
|
-
<tr>
|
|
27
|
-
<td>Cell 1</td>
|
|
28
|
-
<td>Cell 2</td>
|
|
29
|
-
</tr>
|
|
30
|
-
</tbody>
|
|
31
|
-
</table>
|
|
32
|
-
''';
|
|
33
|
-
final markdown = converter.convert(html);
|
|
34
|
-
expect(markdown, contains('| Header 1 | Header 2 |'));
|
|
35
|
-
expect(markdown, contains('|---|---|'));
|
|
36
|
-
expect(markdown, contains('| Cell 1 | Cell 2 |'));
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('converts table without thead', () {
|
|
40
|
-
const html = '''
|
|
41
|
-
<table>
|
|
42
|
-
<tr>
|
|
43
|
-
<td>Cell 1</td>
|
|
44
|
-
<td>Cell 2</td>
|
|
45
|
-
</tr>
|
|
46
|
-
</table>
|
|
47
|
-
''';
|
|
48
|
-
final markdown = converter.convert(html);
|
|
49
|
-
// Fallback: treated as table with first row as header
|
|
50
|
-
expect(markdown, contains('| Cell 1 | Cell 2 |'));
|
|
51
|
-
expect(markdown, contains('|---|---|'));
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test('converts definition lists', () {
|
|
55
|
-
const html = '''
|
|
56
|
-
<dl>
|
|
57
|
-
<dt>Term 1</dt>
|
|
58
|
-
<dd>Definition 1</dd>
|
|
59
|
-
<dt>Term 2</dt>
|
|
60
|
-
<dd>Definition 2</dd>
|
|
61
|
-
</dl>
|
|
62
|
-
''';
|
|
63
|
-
final markdown = converter.convert(html);
|
|
64
|
-
expect(markdown, contains('**Term 1**'));
|
|
65
|
-
expect(markdown, contains(': Definition 1'));
|
|
66
|
-
expect(markdown, contains('**Term 2**'));
|
|
67
|
-
expect(markdown, contains(': Definition 2'));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('converts details/summary', () {
|
|
71
|
-
const html = '''
|
|
72
|
-
<details>
|
|
73
|
-
<summary>Summary</summary>
|
|
74
|
-
Details content
|
|
75
|
-
</details>
|
|
76
|
-
''';
|
|
77
|
-
// We'll preserve HTML for details as it's often supported in markdown rendering
|
|
78
|
-
// OR we can just output the content.
|
|
79
|
-
// Preserving HTML is usually safer for details.
|
|
80
|
-
final markdown = converter.convert(html);
|
|
81
|
-
expect(markdown, contains('<details>'));
|
|
82
|
-
expect(markdown, contains('<summary>Summary</summary>'));
|
|
83
|
-
expect(markdown, contains('Details content'));
|
|
84
|
-
expect(markdown, contains('</details>'));
|
|
85
|
-
});
|
|
86
|
-
test('converts nested tables without flattening', () {
|
|
87
|
-
const html = '''
|
|
88
|
-
<table>
|
|
89
|
-
<tr>
|
|
90
|
-
<td>Outer 1</td>
|
|
91
|
-
<td>
|
|
92
|
-
<table>
|
|
93
|
-
<tr><td>Inner 1</td></tr>
|
|
94
|
-
</table>
|
|
95
|
-
</td>
|
|
96
|
-
</tr>
|
|
97
|
-
</table>
|
|
98
|
-
''';
|
|
99
|
-
final markdown = converter.convert(html);
|
|
100
|
-
// Outer row should contain both outer text and inner table result.
|
|
101
|
-
expect(markdown, contains('| Outer 1 |'));
|
|
102
|
-
expect(markdown, contains('| Inner 1 |'));
|
|
103
|
-
// The outer table should not have inner cells as separate columns of the outer structure.
|
|
104
|
-
});
|
|
105
|
-
test('handles empty table gracefully', () {
|
|
106
|
-
const html = '<table></table>';
|
|
107
|
-
final markdown = converter.convert(html);
|
|
108
|
-
expect(markdown, isEmpty);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test('converts table with multiple tbodies', () {
|
|
112
|
-
const html = '''
|
|
113
|
-
<table>
|
|
114
|
-
<thead>
|
|
115
|
-
<tr><th>Header</th></tr>
|
|
116
|
-
</thead>
|
|
117
|
-
<tbody>
|
|
118
|
-
<tr><td>Row 1</td></tr>
|
|
119
|
-
</tbody>
|
|
120
|
-
<tbody>
|
|
121
|
-
<tr><td>Row 2</td></tr>
|
|
122
|
-
</tbody>
|
|
123
|
-
</table>
|
|
124
|
-
''';
|
|
125
|
-
final markdown = converter.convert(html);
|
|
126
|
-
expect(markdown, contains('| Header |'));
|
|
127
|
-
expect(markdown, contains('| Row 1 |'));
|
|
128
|
-
expect(markdown, contains('| Row 2 |'));
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
}
|
|
@@ -1,37 +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:skills/src/models/skill_params.dart';
|
|
6
|
-
import 'package:test/test.dart';
|
|
7
|
-
|
|
8
|
-
void main() {
|
|
9
|
-
group('SkillParams', () {
|
|
10
|
-
test('fromJson parses correctly without instructions', () {
|
|
11
|
-
final json = {
|
|
12
|
-
'name': 'test-skill',
|
|
13
|
-
'description': 'Test Description',
|
|
14
|
-
'resources': ['http://example.com'],
|
|
15
|
-
};
|
|
16
|
-
final skill = SkillParams.fromJson(json);
|
|
17
|
-
expect(skill.name, 'test-skill');
|
|
18
|
-
expect(skill.description, 'Test Description');
|
|
19
|
-
expect(skill.resources, ['http://example.com']);
|
|
20
|
-
expect(skill.instructions, isNull);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test('fromJson parses correctly with instructions', () {
|
|
24
|
-
final json = {
|
|
25
|
-
'name': 'test-skill',
|
|
26
|
-
'description': 'Test Description',
|
|
27
|
-
'instructions': 'Do not hallucinate.',
|
|
28
|
-
'resources': ['http://example.com'],
|
|
29
|
-
};
|
|
30
|
-
final skill = SkillParams.fromJson(json);
|
|
31
|
-
expect(skill.name, 'test-skill');
|
|
32
|
-
expect(skill.description, 'Test Description');
|
|
33
|
-
expect(skill.resources, ['http://example.com']);
|
|
34
|
-
expect(skill.instructions, 'Do not hallucinate.');
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
}
|
|
@@ -1,291 +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:convert';
|
|
6
|
-
|
|
7
|
-
import 'package:http/http.dart' as http;
|
|
8
|
-
import 'package:http/testing.dart';
|
|
9
|
-
|
|
10
|
-
import 'package:skills/src/services/gemini_service.dart';
|
|
11
|
-
import 'package:test/test.dart';
|
|
12
|
-
|
|
13
|
-
void main() {
|
|
14
|
-
group('GeminiService', () {
|
|
15
|
-
late GeminiService service;
|
|
16
|
-
|
|
17
|
-
setUp(() {
|
|
18
|
-
service = GeminiService(
|
|
19
|
-
apiKey: 'test-api-key',
|
|
20
|
-
httpClient: http.Client(),
|
|
21
|
-
);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
group('cleanContent', () {
|
|
25
|
-
test('returns null for null content', () {
|
|
26
|
-
expect(service.cleanContent(null), isNull);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('removes markdown code blocks around content', () {
|
|
30
|
-
const content = '''
|
|
31
|
-
```markdown
|
|
32
|
-
# Title
|
|
33
|
-
Some content
|
|
34
|
-
```
|
|
35
|
-
''';
|
|
36
|
-
const expected = '''
|
|
37
|
-
# Title
|
|
38
|
-
Some content
|
|
39
|
-
''';
|
|
40
|
-
expect(service.cleanContent(content), expected);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test('removes markdown code blocks with other languages', () {
|
|
44
|
-
const content = '''
|
|
45
|
-
```text
|
|
46
|
-
# Title
|
|
47
|
-
Some content
|
|
48
|
-
```
|
|
49
|
-
''';
|
|
50
|
-
const expected = '''
|
|
51
|
-
# Title
|
|
52
|
-
Some content
|
|
53
|
-
''';
|
|
54
|
-
expect(service.cleanContent(content), expected);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('ignores trailing markdown code block if no start block', () {
|
|
58
|
-
const content = '''
|
|
59
|
-
# Title
|
|
60
|
-
Some content
|
|
61
|
-
```
|
|
62
|
-
''';
|
|
63
|
-
const expected = '''
|
|
64
|
-
# Title
|
|
65
|
-
Some content
|
|
66
|
-
```
|
|
67
|
-
''';
|
|
68
|
-
expect(service.cleanContent(content), expected);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test('strips possible frontmatter at start', () {
|
|
72
|
-
const content = '''
|
|
73
|
-
---
|
|
74
|
-
key: value
|
|
75
|
-
---
|
|
76
|
-
# Title
|
|
77
|
-
Some content
|
|
78
|
-
''';
|
|
79
|
-
const expected = '''
|
|
80
|
-
# Title
|
|
81
|
-
Some content
|
|
82
|
-
''';
|
|
83
|
-
expect(service.cleanContent(content), expected);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test('strips possible frontmatter after some noise', () {
|
|
87
|
-
const content = '''
|
|
88
|
-
Here is the content:
|
|
89
|
-
---
|
|
90
|
-
key: value
|
|
91
|
-
---
|
|
92
|
-
# Title
|
|
93
|
-
Some content
|
|
94
|
-
''';
|
|
95
|
-
const expected = '''
|
|
96
|
-
# Title
|
|
97
|
-
Some content
|
|
98
|
-
''';
|
|
99
|
-
expect(service.cleanContent(content), expected);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test('preserves internal code blocks', () {
|
|
103
|
-
const content = '''
|
|
104
|
-
# Title
|
|
105
|
-
Here is some code:
|
|
106
|
-
```dart
|
|
107
|
-
void main() {}
|
|
108
|
-
```
|
|
109
|
-
''';
|
|
110
|
-
const expected = '''
|
|
111
|
-
# Title
|
|
112
|
-
Here is some code:
|
|
113
|
-
```dart
|
|
114
|
-
void main() {}
|
|
115
|
-
```
|
|
116
|
-
''';
|
|
117
|
-
expect(service.cleanContent(content), expected);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test('ensures content ends with newline', () {
|
|
121
|
-
const content = 'Some content';
|
|
122
|
-
const expected = 'Some content\n';
|
|
123
|
-
expect(service.cleanContent(content), expected);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test('handles complex nested structure', () {
|
|
127
|
-
const content = '''
|
|
128
|
-
```markdown
|
|
129
|
-
---
|
|
130
|
-
key: value
|
|
131
|
-
---
|
|
132
|
-
# Title
|
|
133
|
-
Content with code:
|
|
134
|
-
```dart
|
|
135
|
-
print('hello');
|
|
136
|
-
```
|
|
137
|
-
```
|
|
138
|
-
''';
|
|
139
|
-
const expected = '''
|
|
140
|
-
# Title
|
|
141
|
-
Content with code:
|
|
142
|
-
```dart
|
|
143
|
-
print('hello');
|
|
144
|
-
```
|
|
145
|
-
''';
|
|
146
|
-
expect(service.cleanContent(content), expected);
|
|
147
|
-
});
|
|
148
|
-
test('removes markdown code blocks with leading whitespace', () {
|
|
149
|
-
const content = '''
|
|
150
|
-
```markdown
|
|
151
|
-
# Title
|
|
152
|
-
Some content
|
|
153
|
-
```
|
|
154
|
-
''';
|
|
155
|
-
const expected = '''
|
|
156
|
-
# Title
|
|
157
|
-
Some content
|
|
158
|
-
''';
|
|
159
|
-
expect(service.cleanContent(content), expected);
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test(
|
|
163
|
-
'removes markdown code blocks with trailing whitespace on fence',
|
|
164
|
-
() {
|
|
165
|
-
const content = '''
|
|
166
|
-
```markdown
|
|
167
|
-
# Title
|
|
168
|
-
Some content
|
|
169
|
-
```
|
|
170
|
-
''';
|
|
171
|
-
const expected = '''
|
|
172
|
-
# Title
|
|
173
|
-
Some content
|
|
174
|
-
''';
|
|
175
|
-
expect(service.cleanContent(content), expected);
|
|
176
|
-
},
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
test('removes markdown code blocks with uppercase language', () {
|
|
180
|
-
const content = '''
|
|
181
|
-
```MARKDOWN
|
|
182
|
-
# Title
|
|
183
|
-
Some content
|
|
184
|
-
```
|
|
185
|
-
''';
|
|
186
|
-
const expected = '''
|
|
187
|
-
# Title
|
|
188
|
-
Some content
|
|
189
|
-
''';
|
|
190
|
-
expect(service.cleanContent(content), expected);
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
group('generateSkillContent front matter', () {
|
|
195
|
-
test('does not wrap metadata values with quotes', () async {
|
|
196
|
-
final mockClient = MockClient((request) async {
|
|
197
|
-
return http.Response(
|
|
198
|
-
jsonEncode({
|
|
199
|
-
'candidates': [
|
|
200
|
-
{
|
|
201
|
-
'content': {
|
|
202
|
-
'parts': [
|
|
203
|
-
{'text': 'Markdown body'},
|
|
204
|
-
],
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
],
|
|
208
|
-
}),
|
|
209
|
-
200,
|
|
210
|
-
);
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
final serviceWithMock = GeminiService(
|
|
214
|
-
apiKey: 'test-api-key',
|
|
215
|
-
httpClient: mockClient,
|
|
216
|
-
model: 'models/test-model',
|
|
217
|
-
);
|
|
218
|
-
|
|
219
|
-
final result = await serviceWithMock.generateSkillContent(
|
|
220
|
-
'Raw Content',
|
|
221
|
-
'test-skill',
|
|
222
|
-
'Test description without quotes',
|
|
223
|
-
);
|
|
224
|
-
|
|
225
|
-
expect(result, isNotNull);
|
|
226
|
-
expect(result, contains('name: test-skill'));
|
|
227
|
-
expect(
|
|
228
|
-
result,
|
|
229
|
-
contains('description: Test description without quotes'),
|
|
230
|
-
);
|
|
231
|
-
expect(result, contains('model: models/test-model'));
|
|
232
|
-
// Make sure it doesn't contain double quotes for the fields
|
|
233
|
-
expect(result, isNot(contains('name: "test-skill"')));
|
|
234
|
-
expect(
|
|
235
|
-
result,
|
|
236
|
-
isNot(contains('description: "Test description without quotes"')),
|
|
237
|
-
);
|
|
238
|
-
expect(result, isNot(contains('model: "models/test-model"')));
|
|
239
|
-
});
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
group('updateSkillContent front matter', () {
|
|
243
|
-
test('does not wrap metadata values with quotes', () async {
|
|
244
|
-
final mockClient = MockClient((request) async {
|
|
245
|
-
return http.Response(
|
|
246
|
-
jsonEncode({
|
|
247
|
-
'candidates': [
|
|
248
|
-
{
|
|
249
|
-
'content': {
|
|
250
|
-
'parts': [
|
|
251
|
-
{'text': 'Markdown body'},
|
|
252
|
-
],
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
],
|
|
256
|
-
}),
|
|
257
|
-
200,
|
|
258
|
-
);
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
final serviceWithMock = GeminiService(
|
|
262
|
-
apiKey: 'test-api-key',
|
|
263
|
-
httpClient: mockClient,
|
|
264
|
-
model: 'models/test-model',
|
|
265
|
-
);
|
|
266
|
-
|
|
267
|
-
final result = await serviceWithMock.updateSkillContent(
|
|
268
|
-
'Existing Content',
|
|
269
|
-
'Raw Content',
|
|
270
|
-
'test-skill',
|
|
271
|
-
'Test description without quotes',
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
expect(result, isNotNull);
|
|
275
|
-
expect(result, contains('name: test-skill'));
|
|
276
|
-
expect(
|
|
277
|
-
result,
|
|
278
|
-
contains('description: Test description without quotes'),
|
|
279
|
-
);
|
|
280
|
-
expect(result, contains('model: models/test-model'));
|
|
281
|
-
// Make sure it doesn't contain double quotes for the fields
|
|
282
|
-
expect(result, isNot(contains('name: "test-skill"')));
|
|
283
|
-
expect(
|
|
284
|
-
result,
|
|
285
|
-
isNot(contains('description: "Test description without quotes"')),
|
|
286
|
-
);
|
|
287
|
-
expect(result, isNot(contains('model: "models/test-model"')));
|
|
288
|
-
});
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
}
|
|
@@ -1,156 +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:skills/src/services/markdown_converter.dart';
|
|
6
|
-
import 'package:test/test.dart';
|
|
7
|
-
|
|
8
|
-
void main() {
|
|
9
|
-
group('MarkdownConverter', () {
|
|
10
|
-
late MarkdownConverter converter;
|
|
11
|
-
|
|
12
|
-
setUp(() {
|
|
13
|
-
converter = MarkdownConverter();
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('converts headers', () {
|
|
17
|
-
expect(converter.convert('<h1>Title</h1>'), contains('# Title'));
|
|
18
|
-
expect(converter.convert('<h2>Subtitle</h2>'), contains('## Subtitle'));
|
|
19
|
-
expect(converter.convert('<h3>Section</h3>'), contains('### Section'));
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
test('converts paragraphs', () {
|
|
23
|
-
expect(converter.convert('<p>Hello World</p>'), contains('Hello World'));
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test('converts links', () {
|
|
27
|
-
expect(
|
|
28
|
-
converter.convert('<a href="https://example.com">Link</a>'),
|
|
29
|
-
contains('[Link](https://example.com)'),
|
|
30
|
-
);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test('converts bold and italic', () {
|
|
34
|
-
expect(converter.convert('<b>Bold</b>'), contains('**Bold**'));
|
|
35
|
-
expect(
|
|
36
|
-
converter.convert('<strong>Strong</strong>'),
|
|
37
|
-
contains('**Strong**'),
|
|
38
|
-
);
|
|
39
|
-
expect(converter.convert('<i>Italic</i>'), contains('*Italic*'));
|
|
40
|
-
expect(
|
|
41
|
-
converter.convert('<em>Emphasized</em>'),
|
|
42
|
-
contains('*Emphasized*'),
|
|
43
|
-
);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('converts code', () {
|
|
47
|
-
expect(
|
|
48
|
-
converter.convert('<code>print("hello")</code>'),
|
|
49
|
-
contains('`print("hello")`'),
|
|
50
|
-
);
|
|
51
|
-
expect(
|
|
52
|
-
converter.convert('<pre>void main() {}</pre>'),
|
|
53
|
-
allOf(contains('```'), contains('void main() {}')),
|
|
54
|
-
);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('converts lists', () {
|
|
58
|
-
const html = '''
|
|
59
|
-
<ul>
|
|
60
|
-
<li>Item 1</li>
|
|
61
|
-
<li>Item 2</li>
|
|
62
|
-
</ul>
|
|
63
|
-
''';
|
|
64
|
-
final md = converter.convert(html);
|
|
65
|
-
expect(md, contains('- Item 1'));
|
|
66
|
-
expect(md, contains('- Item 2'));
|
|
67
|
-
|
|
68
|
-
const htmlOl = '''
|
|
69
|
-
<ol>
|
|
70
|
-
<li>First</li>
|
|
71
|
-
<li>Second</li>
|
|
72
|
-
</ol>
|
|
73
|
-
''';
|
|
74
|
-
final mdOl = converter.convert(htmlOl);
|
|
75
|
-
// Currently the converter uses simplified list handling (returning - for both)
|
|
76
|
-
expect(mdOl, contains('- First'));
|
|
77
|
-
expect(mdOl, contains('- Second'));
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test('converts line breaks', () {
|
|
81
|
-
expect(converter.convert('Line 1<br>Line 2'), contains('Line 1\nLine 2'));
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('converts structural elements', () {
|
|
85
|
-
expect(
|
|
86
|
-
converter.convert('<div>Div Content</div>'),
|
|
87
|
-
contains('Div Content'),
|
|
88
|
-
);
|
|
89
|
-
expect(
|
|
90
|
-
converter.convert('<section>Section Content</section>'),
|
|
91
|
-
contains('Section Content'),
|
|
92
|
-
);
|
|
93
|
-
expect(
|
|
94
|
-
converter.convert('<main>Main Content</main>'),
|
|
95
|
-
contains('Main Content'),
|
|
96
|
-
);
|
|
97
|
-
expect(
|
|
98
|
-
converter.convert('<article>Article Content</article>'),
|
|
99
|
-
contains('Article Content'),
|
|
100
|
-
);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test('handles empty body', () {
|
|
104
|
-
expect(converter.convert(''), isEmpty);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('converts table without thead or tbody', () {
|
|
108
|
-
const html = '''
|
|
109
|
-
<table>
|
|
110
|
-
<tr><td>Data 1</td><td>Data 2</td></tr>
|
|
111
|
-
<tr><td>Data 3</td><td>Data 4</td></tr>
|
|
112
|
-
</table>
|
|
113
|
-
''';
|
|
114
|
-
expect(converter.convert(html), contains('| Data 1 | Data 2 |'));
|
|
115
|
-
expect(converter.convert(html), contains('| Data 3 | Data 4 |'));
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('converts video tag with nested source', () {
|
|
119
|
-
expect(
|
|
120
|
-
converter.convert(
|
|
121
|
-
'<video><source src="https://example.com/video.mp4"></video>',
|
|
122
|
-
),
|
|
123
|
-
contains('[Video](https://example.com/video.mp4)'),
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('converts definition lists (dl, dt, dd)', () {
|
|
128
|
-
const html = '''
|
|
129
|
-
<dl>
|
|
130
|
-
<dt>Term 1</dt>
|
|
131
|
-
<dd>Definition 1</dd>
|
|
132
|
-
</dl>
|
|
133
|
-
''';
|
|
134
|
-
final md = converter.convert(html);
|
|
135
|
-
expect(md, contains('**Term 1**'));
|
|
136
|
-
expect(md, contains('Definition 1'));
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('converts iframes', () {
|
|
140
|
-
expect(
|
|
141
|
-
converter.convert('<iframe src="https://example.com/embed"></iframe>'),
|
|
142
|
-
contains('[Iframe](https://example.com/embed)'),
|
|
143
|
-
);
|
|
144
|
-
});
|
|
145
|
-
test('retains details and summary as HTML', () {
|
|
146
|
-
const html = '''
|
|
147
|
-
<details>
|
|
148
|
-
<summary>Click to expand</summary>
|
|
149
|
-
Hidden content
|
|
150
|
-
</details>
|
|
151
|
-
''';
|
|
152
|
-
final md = converter.convert(html);
|
|
153
|
-
expect(md, contains('<details>'));
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
}
|