@ethima/semantic-release-configuration 3.3.5 → 4.0.0
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/README.md +29 -18
- package/package.json +1 -1
- package/src/versioned-templates.js +218 -31
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ configuration supporting a range of languages and platforms supported by the
|
|
|
13
13
|
Commits specification][conventionalcommits-url].
|
|
14
14
|
- Generates release notes using
|
|
15
15
|
[`@semantic-release/release-notes-generator`][semantic-release-notes-generator-plugin-url].
|
|
16
|
-
- Updates templated content in a project's root-level `README.md
|
|
16
|
+
- Updates templated content in files, e.g. a project's root-level `README.md`,
|
|
17
17
|
with updated version information using
|
|
18
18
|
[`@google/semantic-release-replace-plugin`][semantic-release-replace-plugin-url]
|
|
19
19
|
and [`@semantic-release/git`][semantic-release-git-plugin-url].
|
|
@@ -106,39 +106,50 @@ The configuration is not able to automatically register releases with the
|
|
|
106
106
|
General registry. Newly created releases should be registered using [JuliaHub's
|
|
107
107
|
_Register Packages_ interface][juliahub-register-package-url].
|
|
108
108
|
|
|
109
|
-
### Templated Content in
|
|
109
|
+
### Templated Content in Files
|
|
110
110
|
|
|
111
111
|
The configuration will look for `__NEXT_SEMANTIC_RELEASE_VERSION__` tokens in
|
|
112
|
-
templates in
|
|
113
|
-
version that is being released. This
|
|
114
|
-
keeping installation instructions
|
|
112
|
+
templates in files specified in the `files_with_versioned_templates`
|
|
113
|
+
configuration and replace them with the version that is being released. This
|
|
114
|
+
is, for instance, useful for automatically keeping installation instructions
|
|
115
|
+
up-to-date. The configuration defaults to a project's root-level `README.md`.
|
|
115
116
|
|
|
116
|
-
Templated content
|
|
117
|
-
structure:
|
|
117
|
+
Templated content has the following token-based structure:
|
|
118
118
|
|
|
119
|
-
- A
|
|
119
|
+
- A `BEGIN_VERSIONED_TEMPLATE` token,
|
|
120
120
|
- the template itself with one or more
|
|
121
121
|
`__NEXT_SEMANTIC_RELEASE_VERSION__` tokens,
|
|
122
|
-
-
|
|
123
|
-
- (optionally) content that was previously templated
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
- an `END_VERSIONED_TEMPLATE` token,
|
|
123
|
+
- (optionally) content that was previously templated and which will be
|
|
124
|
+
discarded,
|
|
125
|
+
- an `END_VERSIONED_TEMPLATE_REPLACEMENT` token.
|
|
126
|
+
|
|
127
|
+
The `BEGIN_VERSIONED_TEMPLATE`, `END_VERSIONED_TEMPLATE` and
|
|
128
|
+
`END_VERSIONED_TEMPLATE_REPLACEMENT` tokens must each be on their own line.
|
|
129
|
+
These lines may be indented and contain other content that is exempt from
|
|
130
|
+
replacements, e.g. comment markers to ensure the templates do not affect
|
|
131
|
+
surrounding code or documentation. The exact tokens may differ per file-type,
|
|
132
|
+
[see the source code for available
|
|
133
|
+
configurations](./src/versioned-templates.js). For instance, Markdown files can
|
|
134
|
+
use HTML block comments and may replace the literal `END_VERSIONED_TEMPLATE`
|
|
135
|
+
token with an "end comment" token.
|
|
136
|
+
|
|
137
|
+
More concretely a section in a `README.md` that looks like
|
|
127
138
|
|
|
128
139
|
```markdown
|
|
129
|
-
<!--
|
|
140
|
+
<!-- BEGIN_VERSIONED_TEMPLATE
|
|
130
141
|
|
|
131
142
|
The next semantically released version will be v__NEXT_SEMANTIC_RELEASE_VERSION__!
|
|
132
143
|
|
|
133
144
|
-->
|
|
134
|
-
<!--
|
|
145
|
+
<!-- END_VERSIONED_TEMPLATE_REPLACEMENT -->
|
|
135
146
|
```
|
|
136
147
|
|
|
137
148
|
would, after a v1.2.3 release using the configuration has been triggered,
|
|
138
149
|
become
|
|
139
150
|
|
|
140
151
|
```markdown
|
|
141
|
-
<!--
|
|
152
|
+
<!-- BEGIN_VERSIONED_TEMPLATE
|
|
142
153
|
|
|
143
154
|
The next semantically released version will be v__NEXT_SEMANTIC_RELEASE_VERSION__!
|
|
144
155
|
|
|
@@ -146,7 +157,7 @@ The next semantically released version will be v__NEXT_SEMANTIC_RELEASE_VERSION_
|
|
|
146
157
|
|
|
147
158
|
The next semantically released version will be v1.2.3!
|
|
148
159
|
|
|
149
|
-
<!--
|
|
160
|
+
<!-- END_VERSIONED_TEMPLATE_REPLACEMENT -->
|
|
150
161
|
```
|
|
151
162
|
|
|
152
163
|
Note that the `v` is in the template! The version as derived by the semantic
|
|
@@ -182,7 +193,7 @@ including a non-visible whitespace character, e.g. [a _Zero Width Non-Joiner
|
|
|
182
193
|
(ZWNJ)_ character](https://unicode-table.com/en/200C/). A sufficient approach
|
|
183
194
|
is to modify the starting token, so that the template is no longer recognized
|
|
184
195
|
as one. Using the suggested ZWNJ character the starting token becomes
|
|
185
|
-
`<!--
|
|
196
|
+
`<!-- BEGIN_VERSIONED_TEMPLATE`.
|
|
186
197
|
|
|
187
198
|
Note that when using this approach, although the templates/tokens _visually_
|
|
188
199
|
look like versions that should be replaced, they cannot be copied and pasted as
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ethima/semantic-release-configuration",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A shareable semantic release configuration supporting a range of languages and platforms supported by the Ethima organization.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"repository": {
|
|
@@ -1,42 +1,229 @@
|
|
|
1
|
-
const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
const { extname } = require("node:path");
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The default configuration for tokens used by the {@link buildReplacement}
|
|
5
|
+
* and {@link buildTemplateMatcher} functions to parse templates and perform
|
|
6
|
+
* replacements.
|
|
7
|
+
*
|
|
8
|
+
* The tokens serve the following purposes:
|
|
9
|
+
* - `next_version_placeholder_token` represents locations in a template that
|
|
10
|
+
* need to be replaced by the version of the next semantic release.
|
|
11
|
+
* - `replacement_end_token` represents the end of content that was previously
|
|
12
|
+
* filled in. Should be on a separate line. This line may contain additional
|
|
13
|
+
* content which will be maintained along with the token in the replaced
|
|
14
|
+
* content, e.g. indentation, comment markers, etc..
|
|
15
|
+
* - `template_begin_token` indicates the start of the template in which
|
|
16
|
+
* `next_version_placeholder_token`s should be replaced. Should be on a
|
|
17
|
+
* separate line. This line may contain additional content which will be
|
|
18
|
+
* maintained along with the token in the replaced content, e.g. indentation,
|
|
19
|
+
* comment markers, etc..
|
|
20
|
+
* - `template_continuation_token` represents indented markers that are
|
|
21
|
+
* necessary to indicate continuation of the template, but which should not
|
|
22
|
+
* be present in the replaced content, e.g. comment indicators for line-based
|
|
23
|
+
* comments, etc. Indented whitespace does not have to be configured in the
|
|
24
|
+
* token.
|
|
25
|
+
* - `template_end_token` indicates the end of the template. Should be on a
|
|
26
|
+
* separate line. This line may contain additional content which will be
|
|
27
|
+
* maintained along with the token in the replaced content, e.g. indentation,
|
|
28
|
+
* comment markers, etc..
|
|
29
|
+
*/
|
|
30
|
+
const DEFAULT_TEMPLATE_TOKEN_CONFIGURATION = {
|
|
31
|
+
next_version_placeholder_token: "__NEXT_SEMANTIC_RELEASE_VERSION__",
|
|
32
|
+
replacement_end_token: "END_VERSIONED_TEMPLATE_REPLACEMENT",
|
|
33
|
+
template_begin_token: "BEGIN_VERSIONED_TEMPLATE",
|
|
34
|
+
template_continuation_token: "",
|
|
35
|
+
template_end_token: "END_VERSIONED_TEMPLATE",
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Template token configuration for files that can be commented using "C-style
|
|
40
|
+
* comments", e.g. C, CSS, JavaScript, TypeScript, etc.
|
|
41
|
+
*/
|
|
42
|
+
const C_BLOCK_TEMPLATE_TOKEN_CONFIGURATION = {
|
|
43
|
+
template_continuation_token: "\\s\\*+",
|
|
44
|
+
template_end_token: "\\*+/",
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Template token configuration for files that can be commented using "hash
|
|
49
|
+
* signs", e.g. Python, TOML, YAML, etc.
|
|
50
|
+
*/
|
|
51
|
+
const HASH_TEMPLATE_TOKEN_CONFIGURATION = {
|
|
52
|
+
template_continuation_token: "#",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Template token configuration for files that can be commented using XML
|
|
57
|
+
* comments, e.g. HTML, Markdown, etc.
|
|
58
|
+
*/
|
|
59
|
+
const XML_TEMPLATE_TOKEN_CONFIGURATION = {
|
|
60
|
+
template_end_token: "-->",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Maps file extensions to token configurations for templates that can be
|
|
65
|
+
* included in the specified file formats.
|
|
66
|
+
*/
|
|
67
|
+
const FILE_EXTENSION_TO_TEMPLATE_CONFIGURATION = {
|
|
68
|
+
c: C_BLOCK_TEMPLATE_TOKEN_CONFIGURATION,
|
|
69
|
+
css: C_BLOCK_TEMPLATE_TOKEN_CONFIGURATION,
|
|
70
|
+
html: XML_TEMPLATE_TOKEN_CONFIGURATION,
|
|
71
|
+
jl: HASH_TEMPLATE_TOKEN_CONFIGURATION,
|
|
72
|
+
js: C_BLOCK_TEMPLATE_TOKEN_CONFIGURATION,
|
|
73
|
+
md: XML_TEMPLATE_TOKEN_CONFIGURATION,
|
|
74
|
+
py: HASH_TEMPLATE_TOKEN_CONFIGURATION,
|
|
75
|
+
toml: HASH_TEMPLATE_TOKEN_CONFIGURATION,
|
|
76
|
+
ts: C_BLOCK_TEMPLATE_TOKEN_CONFIGURATION,
|
|
77
|
+
xml: XML_TEMPLATE_TOKEN_CONFIGURATION,
|
|
78
|
+
yaml: HASH_TEMPLATE_TOKEN_CONFIGURATION,
|
|
79
|
+
yml: HASH_TEMPLATE_TOKEN_CONFIGURATION,
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Builds a replacement string from the components matched by a matcher created
|
|
84
|
+
* by {@link buildTemplateMatcher}. Any `next_version_placeholder_token`s, as
|
|
85
|
+
* identified by the {@link DEFAULT_TEMPLATE_TOKEN_CONFIGURATION}, are replaced
|
|
86
|
+
* by the next semantic release version. Any "template continuation tokens" are
|
|
87
|
+
* removed from the template using {@link stripTemplateContinuationTokens}.
|
|
88
|
+
*/
|
|
89
|
+
function buildReplacement(
|
|
90
|
+
// Only grab the tokens of interest that should be included in the
|
|
91
|
+
// replacement string. These are obtained from the match instead of the
|
|
92
|
+
// configuration to ensure additional information in the templated area is
|
|
93
|
+
// preserved, e.g. whitespace, etc.
|
|
94
|
+
_, // Full match
|
|
95
|
+
template_begin,
|
|
19
96
|
template,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
97
|
+
template_end,
|
|
98
|
+
replacement_end,
|
|
99
|
+
_, // Index of match start
|
|
100
|
+
_, // Searched text
|
|
101
|
+
filename,
|
|
102
|
+
context
|
|
23
103
|
) {
|
|
24
|
-
const
|
|
104
|
+
const { next_version_placeholder_token, template_continuation_token } =
|
|
105
|
+
getTemplateTokenConfiguration(filename);
|
|
106
|
+
|
|
107
|
+
const normalized_template = stripTemplateContinuationTokens(
|
|
108
|
+
template_continuation_token,
|
|
109
|
+
template
|
|
110
|
+
);
|
|
25
111
|
|
|
26
112
|
return [
|
|
27
|
-
|
|
113
|
+
template_begin,
|
|
28
114
|
template,
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
TEMPLATE_VERSION_PLACEHOLDER,
|
|
115
|
+
template_end,
|
|
116
|
+
normalized_template.replaceAll(
|
|
117
|
+
next_version_placeholder_token,
|
|
33
118
|
context.nextRelease.version
|
|
34
119
|
),
|
|
35
|
-
|
|
36
|
-
templateCloseMarker,
|
|
120
|
+
replacement_end,
|
|
37
121
|
].join("");
|
|
38
122
|
}
|
|
39
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Builds a regular expression to find templated regions in a file. Templated
|
|
126
|
+
* regions are defined by a token configuration based on the {@param filename}'s
|
|
127
|
+
* extension.
|
|
128
|
+
*
|
|
129
|
+
* The resulting regular expression is set up to capture:
|
|
130
|
+
* - The line starting the template,
|
|
131
|
+
* - One or more lines defining the template in which
|
|
132
|
+
* `next_version_placeholder_token` should be replaced by the next semantic
|
|
133
|
+
* release version,
|
|
134
|
+
* - The line indicating the end of the template.
|
|
135
|
+
* - The line indicating the end of the replacement.
|
|
136
|
+
*
|
|
137
|
+
* Any content between the end of the template and the end of the replacement
|
|
138
|
+
* is dropped.
|
|
139
|
+
*/
|
|
140
|
+
function buildTemplateMatcher(filename) {
|
|
141
|
+
const { replacement_end_token, template_begin_token, template_end_token } =
|
|
142
|
+
getTemplateTokenConfiguration(filename);
|
|
143
|
+
|
|
144
|
+
return new RegExp(
|
|
145
|
+
[
|
|
146
|
+
`(\n[^\n]*${template_begin_token}[^\n]*)`,
|
|
147
|
+
// The template to insert the version into. Needs to lazily match to
|
|
148
|
+
// ensure only content up until the first `template_end_token` is matched
|
|
149
|
+
// to prevent issues when multiple templates are present in a single file
|
|
150
|
+
"((?:\n[^\n]*?)+?)",
|
|
151
|
+
`(\n[^\n]*${template_end_token}[^\n]*)`,
|
|
152
|
+
// The templated content, will be discarded. Needs to lazily match to
|
|
153
|
+
// ensure only content up until the first `replacement_end_token` is
|
|
154
|
+
// grabbed
|
|
155
|
+
".*?",
|
|
156
|
+
`(\n[^\n]*${replacement_end_token}[^\n]*?)`,
|
|
157
|
+
].join(""),
|
|
158
|
+
"gs"
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Returns the template token configuration corresponding to the specified
|
|
164
|
+
* {@param filename} based on its extension. Extension specific configuration
|
|
165
|
+
* is merged with the {@link DEFAULT_TEMPLATE_TOKEN_CONFIGURATION}
|
|
166
|
+
*/
|
|
167
|
+
function getTemplateTokenConfiguration(filename) {
|
|
168
|
+
// `extname` returns the extension with a dot-prefix
|
|
169
|
+
return {
|
|
170
|
+
...DEFAULT_TEMPLATE_TOKEN_CONFIGURATION,
|
|
171
|
+
...FILE_EXTENSION_TO_TEMPLATE_CONFIGURATION[extname(filename).slice(1)],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Strips the {@param template_continuation_token} and the largest common
|
|
177
|
+
* length of whitespace after those tokens from the {@param template}.
|
|
178
|
+
*
|
|
179
|
+
* For instance, assuming the {@param template_continuation_token} is `#`, this
|
|
180
|
+
* will turn
|
|
181
|
+
* ```
|
|
182
|
+
* # Foo bar
|
|
183
|
+
* # Quuz Quux
|
|
184
|
+
* ```
|
|
185
|
+
* into
|
|
186
|
+
* ```
|
|
187
|
+
* Foo bar
|
|
188
|
+
* Quuz Quux
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
function stripTemplateContinuationTokens(
|
|
192
|
+
template_continuation_token,
|
|
193
|
+
template
|
|
194
|
+
) {
|
|
195
|
+
// The capture group is only necessary when using this matcher in the context
|
|
196
|
+
// of replacement, i.e. where all the matched content should be replaced by
|
|
197
|
+
// the indentation. It is used in that context and for determining the
|
|
198
|
+
// largest common whitespace prefix for each line in the template
|
|
199
|
+
const indented_continuation_token_matcher = `^(\\s*)${template_continuation_token}`;
|
|
200
|
+
const continuation_prefix_matcher = new RegExp(
|
|
201
|
+
`${indented_continuation_token_matcher}(?<prefix>\\s*)`
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
const prefix_lengths = template
|
|
205
|
+
.split("\n")
|
|
206
|
+
// The first line in the template will be empty when splitting on newlines,
|
|
207
|
+
// due to the way the matchers are set up to match on starting newlines
|
|
208
|
+
.slice(1)
|
|
209
|
+
.map((template_line) => {
|
|
210
|
+
const match = template_line.match(continuation_prefix_matcher);
|
|
211
|
+
return match?.groups?.prefix?.length ?? 0;
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const largest_common_prefix_matcher = new RegExp(
|
|
215
|
+
`${indented_continuation_token_matcher}\\s{${Math.min(...prefix_lengths)}}`,
|
|
216
|
+
"gm"
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
return template.replaceAll(largest_common_prefix_matcher, "$1");
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Returns the semantic release configuration for the
|
|
224
|
+
* `@google/semantic-release-replace-plugin` set up to replace specific tokens
|
|
225
|
+
* with the next semantic release version in the provided {@param files}.
|
|
226
|
+
*/
|
|
40
227
|
function VersionedTemplatesConfiguration(files) {
|
|
41
228
|
return [
|
|
42
229
|
"@google/semantic-release-replace-plugin",
|
|
@@ -45,8 +232,8 @@ function VersionedTemplatesConfiguration(files) {
|
|
|
45
232
|
{
|
|
46
233
|
countMatches: true,
|
|
47
234
|
files,
|
|
48
|
-
from:
|
|
49
|
-
to:
|
|
235
|
+
from: buildTemplateMatcher,
|
|
236
|
+
to: buildReplacement,
|
|
50
237
|
},
|
|
51
238
|
],
|
|
52
239
|
},
|