Skip to content

Commit bde0cca

Browse files
committed
chore: add an LLM agent plugin
1 parent 0bbb320 commit bde0cca

8 files changed

Lines changed: 1131 additions & 8 deletions

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "migrate-goldmark-v1-to-v2",
3+
"description": "Skills for migrating goldmark v1 to v2",
4+
"version": "1.0.0",
5+
"author": {
6+
"name": "Yusuke Inuzuka"
7+
},
8+
"license": "MIT"
9+
}

.agent-plugins/migrate-goldmark-v1-to-v2/references/breaking-changes-in-v2.md

Lines changed: 318 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Key point of CommonMark spec
2+
- In most cases, punctuation characters can be escaped with a backslash (`\`) to prevent them from being interpreted as Markdown syntax. For example, `\*` will render as `*` instead of starting an emphasis.
3+
- Spec defines sets of character categories. Use `util` package to check if a character belongs to a specific category. For example, `util.IsPunct` can be used to check if a character is a punctuation character. DO NOT use standard library functions like `unicode.IsPunct` as they may not cover all cases defined in the CommonMark spec.
4+
- Most of inline elements (like emphasis, links, etc.) can exist within multiple lines. And they can be nested. So inline elements probably have multiple divided segments:
5+
6+
```markdown
7+
> [lin
8+
> nk](https://example.com)
9+
```
10+
11+
In this case, the link element has two divided segments: `lin` and `nk`. When parsing, you should keep track of these segments and combine them when necessary. This kind of elements should have `text.MultiLineValue` instead of `text.SingleLineValue`.
12+
- Paragraph rendering can be changed by parent elements. For example, a paragraph inside a tight list item should not have `<p>` tags, while a paragraph inside a block quote should have `<p>` tags.
13+
- Tabs can be 1,2,3,4 spaces or raw tab character, depending on its position. When parsing block elements, you should aware of this and calculate the correct indentation level.
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
---
2+
name: migrate-goldmark-app-v1-to-v2
3+
context: fork
4+
description: Migrate your application from goldmark v1 to v2.
5+
allowed-tools: Bash Read
6+
---
7+
8+
# migrate-goldmark-app-v1-to-v2
9+
## Description
10+
This skill helps you migrate a goldmark (https://github.com/yuin/goldmark) extension from version 1 to version 2. It
11+
provides guidance on the changes needed to update your project to be compatible with the new version of goldmark.
12+
13+
## Knowledges
14+
15+
- [CommonMark key points](../../references/commonmark-key-points.md) : List of key points of CommonMark spec that you should be aware of when implementing a goldmark extension.
16+
- [Breaking changes in v2](../../references/breaking-changes-in-v2.md) : List of breaking changes in goldmark v2 that you should be aware of when migrating your extension from v1 to v2.
17+
18+
## Migration steps
19+
### Overview of the migration process
20+
21+
- Create a migration plan for the application.
22+
- **MUST** ask human to confirm that the migration plan is acceptable before proceeding with the migration.
23+
- **MUST** ask human to how to test the application after migration before proceeding with the migration.
24+
- e.g. : "How do you want to test the application after migration? Do you have any test cases or examples that you want to use for testing?"
25+
- Execute the migration plan to update the application code to be compatible with goldmark v2.
26+
- Update the test cases to ensure that the application works as expected with goldmark v2.
27+
- Test the application with goldmark v2 to ensure that it works as expected. If there are any issues, fix them and re-test until the application works as expected.
28+
- Update the documentation to reflect any changes made during the migration process.
29+
30+
### Create a migration plan
31+
#### Task
32+
33+
- Make sure you have read and understood the [Breaking changes in v2](../../references/breaking-changes-in-v2.md) document.
34+
- Make sure you have read and understood the [How to create an extension](./references/how-to-create-an-extension.md) document.
35+
- You create a ./features/goldmark-migration-plan.md file that contains a migration plan for the extension.
36+
37+
#### Extension
38+
39+
- If the application contains own extensions, you can use `/migrate-goldmark-extension-v1-to-v2` skill to migrate the extensions.
40+
- If the application contains third-party extensions, you need to check if the extensions provide v2 compatible version. - If not, **STOP** the migration.
41+
42+
#### Key points to consider when migrating your application
43+
##### goldmark.Markdown alternatives
44+
45+
- In v2, `goldmark.Markdown` is removed. Therefore, you need to replace it with one of the following two patterns:
46+
- Pattern 1: Use `parser.Parser` and `renderer.Renderer` to create your own `goldmark.Markdown` alternative.
47+
- Example:
48+
```go
49+
// MarkdownToStringFunc is a function type that converts markdown to HTML.
50+
type MarkdownToStringFunc func(source string) (string, error)
51+
52+
// NewMarkdownToStringFunc returns a MarkdownToStringFunc that uses the given parser and renderer.
53+
func NewMarkdownToStringFunc(p parser.Parser, r html.Renderer) MarkdownToStringFunc {
54+
return func(source string) (string, error) {
55+
var buf bytes.Buffer
56+
b := util.StringToReadOnlyBytes(source)
57+
doc := p.Parse(b)
58+
if err := r.Render(&buf, b, doc); err != nil {
59+
return "", err
60+
}
61+
return buf.String(), nil
62+
}
63+
}
64+
- Pattern 2: Use `parser.Parser` and `renderer.Renderer` separately.
65+
- Example:
66+
```go
67+
var buf bytes.Buffer
68+
p := parser.New(parser.WithAttribute(), parser.WithExtensions(extension.StrikethroughParser))
69+
r := html.New(html.WithXHTML(), html.WithUnsafe(), html.WithExtensions(extension.StrikethroughHTMLRenderer))
70+
doc := p.Parse(b)
71+
err := r.Render(&buf, b, doc)
72+
```
73+
74+
##### AST
75+
76+
- In v1, AST values are mostly 'raw' values; entities references and `\` escapes are not resolved. In v2, AST values are resolved values.
77+
- You need to check if your application relies on the 'raw' values of AST nodes.
78+
- If your application relies on the resolved values of AST nodes, you should replace `Value.Bytes` and `Value.Str` methods with `Value.Value` method.
79+
- Otherwise, you should replace `Value.Bytes` and `Value.Str` methods with `Value.Value` method.
80+
- In v2, to make the AST more semantic, some breaking changes have occurred.
81+
- Please refer to the AST-related section of [Breaking changes in v2](../../references/breaking-changes-in-v2.md).
82+
83+
##### Parsing
84+
85+
- To customize the ID generation, you need to use `parser.IDGenerator` instead of `parser.IDs`.
86+
87+
##### Rendering
88+
89+
- In v2, `renderer.Renderer` has `renderer.Context`; if the application mimics context for rendering, it should be updated to use `renderer.Context`.
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
---
2+
name: migrate-goldmark-extension-v1-to-v2
3+
context: fork
4+
description: Migrate goldmark extension from goldmark v1 to v2.
5+
allowed-tools: Bash Read
6+
---
7+
8+
# migrate-goldmark-extension-v1-to-v2
9+
## Description
10+
This skill helps you migrate a goldmark (https://github.com/yuin/goldmark) extension from version 1 to version 2. It
11+
provides guidance on the changes needed to update your project to be compatible with the new version of goldmark.
12+
13+
## Knowledges
14+
15+
- [CommonMark key points](../../references/commonmark-key-points.md) : List of key points of CommonMark spec that you should be aware of when implementing a goldmark extension.
16+
- [Breaking changes in v2](../../references/breaking-changes-in-v2.md) : List of breaking changes in goldmark v2 that you should be aware of when migrating your extension from v1 to v2.
17+
- [How to create an extension](./references/how-to-create-an-extension.md) : Guide on how to create a goldmark extension in v2, including the new extension pattern and how to implement parser and renderer extensions.
18+
19+
## Migration steps
20+
### Overview of the migration process
21+
22+
- Create a migration plan for the extension.
23+
- **MUST** ask human to confirm that the migration plan is acceptable before proceeding with the migration.
24+
- **MUST** ask human to how to test the extension after migration before proceeding with the migration.
25+
- e.g. : "How do you want to test the extension after migration? Do you have any test cases or examples that you want to use for testing?"
26+
- Execute the migration plan to update the extension code to be compatible with goldmark v2.
27+
- Update the test cases to ensure that the extension works as expected with goldmark v2.
28+
- Test the extension with goldmark v2 to ensure that it works as expected. If there are any issues, fix them and re-test until the extension works as expected.
29+
- Update the documentation to reflect any changes made during the migration process.
30+
31+
### Create a migration plan
32+
#### Task
33+
34+
- Make sure you have read and understood the [Breaking changes in v2](../../references/breaking-changes-in-v2.md) document.
35+
- Make sure you have read and understood the [How to create an extension](./references/how-to-create-an-extension.md) document.
36+
- You create a ./features/goldmark-migration-plan.md file that contains a migration plan for the extension.
37+
38+
#### Key points to consider when migrating your extension
39+
##### Extension options
40+
41+
- If the extension uses "unified" options for both parser and renderer, they should be split into separate options for each.
42+
- e.g. :
43+
- v1
44+
```go
45+
type Option interface {
46+
myOption()
47+
}
48+
49+
type ParserOption interface {
50+
Option
51+
applyParserOption(*parserConfig)
52+
}
53+
54+
type RendererOption interface {
55+
Option
56+
applyRendererOption(*rendererConfig)
57+
}
58+
59+
func New(opts ...Option) goldmark.Extender { // takes unified options
60+
// ...
61+
}
62+
```
63+
- v2
64+
```go
65+
type ParserOption interface {
66+
applyParserOption(*parserConfig)
67+
}
68+
69+
type HTMLRendererOption interface { // explicitly named for **HTML**
70+
applyRendererOption(*htmlRendererConfig) // you can access the shared renderer config like `XHTML` or `Unsafe` in the renderer config
71+
}
72+
73+
func NewParser(opts ...ParserOption) parser.Extension { // takes parser options
74+
// ...
75+
}
76+
77+
var Parser = NewParser() // Default instance of parser extension
78+
79+
func NewHTMLRenderer(opts ...HTMLRendererOption) html.Extension { // takes renderer options
80+
// ...
81+
}
82+
83+
var HTMLRenderer = NewHTMLRenderer() // Default instance of renderer extension
84+
```
85+
86+
##### AST nodes
87+
88+
- use `text.Value`(single line), `text.MultiLineValue`(multi-line) instead of `[]byte` for values that can be parsed from source text in inline AST nodes.
89+
- In your parser, you must choose `text.Decoder` implementation to decode the source value
90+
- `text.IdentityDecoder` : for raw contents like inline HTMLs, inline code, etc.
91+
- `reader.Decoder` : other contents like text, links, etc. This decoder decodes entity references, `\` escapes, etc.
92+
- In most cases, you will choose `text.Decoder`. **DO NOT** use `text.IdentityDecoder` unless you have a clear intention to do so.
93+
- use `text.Lines` instead of `[]text.Segment` for values in block AST nodes that have **raw contents** like HTML blocks, code blocks, etc.
94+
- Properties in AST Dump should be `text.Value` as possible.
95+
- e.g.
96+
- OK:
97+
```
98+
// Dump implements Node.Dump.
99+
func (n *Text) Dump(_ []byte) *NodeDump {
100+
m := map[string]any{
101+
"Value": n.Value, // text.Value
102+
}
103+
fs := textFlagsString(n.flags)
104+
if len(fs) != 0 {
105+
m["Flags"] = fs
106+
}
107+
return NewNodeDump(n, m)
108+
}
109+
```
110+
- Not OK:
111+
```
112+
// Dump implements Node.Dump.
113+
func (n *Text) Dump(source []byte) *NodeDump {
114+
m := map[string]any{
115+
"Value": n.Value.Str(source), // string
116+
}
117+
fs := textFlagsString(n.flags)
118+
if len(fs) != 0 {
119+
m["Flags"] = fs
120+
}
121+
return NewNodeDump(n, m)
122+
}
123+
```
124+
- In v2, attribute values are `text.Value` which has almost the same specification as HTML attributes.
125+
- Therefore, if the project were using non-string attributes in v1, human must decide on one of the following policies:
126+
- Use the `goldmark_v1_attribute` build tag to continue using v1 attributes as they are.
127+
- Convert attribute values to strings to comply with the v2 specification.
128+
- **MUST** ask human to decide on one of the above policies before proceeding with the migration.
129+
130+
##### Parsing
131+
132+
- In v2, all nodes have a start position. goldmark/v2 automatically sets the start position to the node. However, if you want to customize the start position, you need to call `SetPos` appropriately.
133+
134+
##### HTML Rendering
135+
136+
- `text.Value` and `text.Lines` can be rendered using the `WriteTo` method whenever possible. Also, the output destination of `WriteTo` should use `html.ContextHTMLWriter(rc)` or `html.ContextTextWriter(rc)`.
137+
- e.g. :
138+
```go
139+
tw := html.ContextTextWriter(rc)
140+
_, _ = n.Value.WriteTo(tw, source)
141+
```
142+
- `WriteTo` is fast because it does not allocate new memory. On the other hand, if you write `Value` directly like `tw.Write(n.Value.Value(source))`, it may copy the contents of `Value`, which can degrade performance.
143+
144+
##### Recommended naming convention(for public stuff)
145+
146+
- Use `myext.NewParser()` and `myext.NewHTMLRenderer()` for the extension constructors.
147+
- e.g. : `meta` extension
148+
- `meta.NewParser()`, `meta.NewHTMLRenderer()`
149+
- Use `myext.Parser` and `myext.HTMLRenderer` as the default extension values.
150+
- e.g. : `var Parser = NewParser()`, `var HTMLRenderer = NewHTMLRenderer()`
151+
- Use `myext.ParserOption` and `myext.HTMLRendererOption` for functional options.
152+
- e.g. : `type ParseOption func(*parserConfig)`, `type HTMLRendererOption func(*htmlRendererConfig)`
153+
154+
### Execute migration plan
155+
- Make sure you are on a branch that is not `main` or `master`. User must create a new branch like 'v2' to work on the migration before using this skill.
156+
- If you are on `main` or `master`, **STOP** this skill and ask human to create a new branch like 'v2' to work on the migration.
157+
- Make sure `go.mod` file is updated to use `github.com/yuin/goldmark/v2` instead of `github.com/yuin/goldmark`. User must add `goldmark/v2` before using this skill.
158+
- If `go.mod` file is not updated, **STOP** this skill and ask human to update `go.mod` file to use `github.com/yuin/goldmark/v2` instead of `github.com/yuin/goldmark`.
159+
- Update the module path in your `go.mod` file with new major version. For example, change `github.com/you/yourextension` to `github.com/you/yourextension/v2`.
160+
- **MUST** ask human to make sure that the module path is updated in `go.mod` file before proceeding with the migration.
161+
- If human confirms that the module path is updated, proceed with the migration, otherwise, **STOP** this skill and ask human to update the module path in `go.mod` file with new major version.
162+

0 commit comments

Comments
 (0)