cc-vscode-shebang-markdown 0.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0
4
+
5
+ Initial public release.
6
+
7
+ ### Added
8
+
9
+ - Custom shebang detection on the first line.
10
+ - Automatic language mode switch to Markdown.
11
+ - Configurable detection pattern.
12
+ - Configurable target language id.
13
+ - Local VSIX packaging scripts.
14
+ - npm package metadata and documentation.
15
+
16
+ ## 0.1.1
17
+
18
+ ### Added
19
+
20
+ - POSIX shell shebang fallback for `bash`, `zsh` and `sh`.
21
+ - Support for `/bin/*`, `/usr/bin/*`, `/usr/local/bin/*` and `/usr/bin/env` shebang variants.
22
+ - Support for `/usr/bin/env -S bash ...` style shebangs.
23
+ - Fallback detection for `nginx.conf` and `conf.d/*.conf`.
24
+ - Content-based nginx fallback for common nginx blocks.
25
+
26
+ ### Fixed
27
+
28
+ - Removed `.vscodeignore` because VSCE does not support using `.vscodeignore` together with the `files` property in `package.json`.
@@ -0,0 +1,27 @@
1
+ # Contributing
2
+
3
+ Contributions are welcome.
4
+
5
+ ## Development
6
+
7
+ ```bash
8
+ npm install
9
+ npm run pack:vsix
10
+ npm run reinstall
11
+ ```
12
+
13
+ ## Before opening a pull request
14
+
15
+ Please check:
16
+
17
+ ```bash
18
+ npm run pack:npm
19
+ npm run pack:vsix
20
+ ```
21
+
22
+ ## Guidelines
23
+
24
+ - Keep the extension small.
25
+ - Avoid project-specific hardcoding.
26
+ - Preserve the configurable shebang pattern.
27
+ - Document behavior changes in `CHANGELOG.md`.
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CodeCorn
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files, to deal in the Software
7
+ without restriction, including without limitation the rights to use, copy,
8
+ modify, merge, publish, distribute, sublicense, and/or sell copies of the
9
+ Software, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,337 @@
1
+ # CodeCorn Shebang Markdown
2
+
3
+ [![npm version](https://img.shields.io/npm/v/cc-vscode-shebang-markdown.svg)](https://www.npmjs.com/package/cc-vscode-shebang-markdown)
4
+ [![npm downloads](https://img.shields.io/npm/dm/cc-vscode-shebang-markdown.svg)](https://www.npmjs.com/package/cc-vscode-shebang-markdown)
5
+ [![license](https://img.shields.io/npm/l/cc-vscode-shebang-markdown.svg)](LICENSE)
6
+ [![VS Code](https://img.shields.io/badge/VS%20Code-%5E1.80.0-blue.svg)](https://code.visualstudio.com/)
7
+
8
+ **CodeCorn Shebang Markdown** is a tiny Visual Studio Code extension that detects a custom shebang on the first line of a file and switches the editor language mode to Markdown.
9
+
10
+ It is designed for workflows where Markdown-like operational files, scripts, notes or generated artifacts do not use the `.md` extension, but still need to be handled as Markdown by VS Code, markdownlint, formatters and language-aware tooling.
11
+
12
+ Italian documentation: [README_IT.md](README_IT.md)
13
+
14
+ ---
15
+
16
+ ## Why
17
+
18
+ VS Code file associations are path/name based. They are great when a file extension or filename is predictable, but they do not inspect the first line of a document.
19
+
20
+ This extension fills that gap with a small content-based rule:
21
+
22
+ ```text
23
+ first line contains a CodeCorn Markdown shebang
24
+ → switch document language mode to markdown
25
+ ```
26
+
27
+ Example:
28
+
29
+ ```text
30
+ #!/usr/bin/env cc-md
31
+
32
+ # Deployment checklist
33
+
34
+ - backup database
35
+ - dump environment
36
+ - apply patch
37
+ - verify logs
38
+ ```
39
+
40
+ Even if the file has no `.md` extension, VS Code will treat it as Markdown.
41
+
42
+ ---
43
+
44
+ ## Features
45
+
46
+ - Detects custom Markdown shebangs on the first line.
47
+ - Forces VS Code language mode to `markdown`.
48
+ - Works with untitled files, extensionless files and script-like notes.
49
+ - Configurable regex pattern.
50
+ - Configurable target VS Code language id.
51
+ - Useful with `markdownlint`, Markdown formatters and editor tooling.
52
+ - No runtime dependencies.
53
+ - Minimal extension footprint.
54
+
55
+ ---
56
+
57
+ ## Default shebangs
58
+
59
+ The default pattern is:
60
+
61
+ ```text
62
+ ^#!.*\bcc-(md|markdown)\b
63
+ ```
64
+
65
+ Supported examples:
66
+
67
+ ```text
68
+ #!/usr/bin/env cc-md
69
+ ```
70
+
71
+ ```text
72
+ #!cc-md
73
+ ```
74
+
75
+ ```text
76
+ #!/usr/bin/env cc-markdown
77
+ ```
78
+
79
+ ```text
80
+ #!cc-markdown
81
+ ```
82
+
83
+ ---
84
+
85
+ ## Installation
86
+
87
+ ### Local VSIX install
88
+
89
+ This package is primarily a VS Code extension. For local development or internal usage:
90
+
91
+ ```bash
92
+ npm install
93
+ npm run reinstall
94
+ ```
95
+
96
+ This builds the `.vsix` package and installs it in VS Code.
97
+
98
+ ### npm package
99
+
100
+ The package is also published on npm for traceability, reuse and source distribution:
101
+
102
+ ```bash
103
+ npm install cc-vscode-shebang-markdown
104
+ ```
105
+
106
+ Installing from npm does not automatically install the extension into VS Code. For actual editor installation, use a generated `.vsix` file or publish the extension to the Visual Studio Code Marketplace.
107
+
108
+ ---
109
+
110
+ ## Usage
111
+
112
+ Create or open any file whose first line matches the configured shebang pattern:
113
+
114
+ ```text
115
+ #!/usr/bin/env cc-md
116
+
117
+ # Server audit
118
+
119
+ ## Build log
120
+
121
+ - collect build output
122
+ - inspect warnings
123
+ - normalize report
124
+ ```
125
+
126
+ When the document opens, the extension switches its language mode to:
127
+
128
+ ```text
129
+ markdown
130
+ ```
131
+
132
+ You can verify this in the bottom-right language selector in VS Code.
133
+
134
+ ---
135
+
136
+ ## Configuration
137
+
138
+ ### `ccShebangMarkdown.pattern`
139
+
140
+ Regex applied to the first line of the document.
141
+
142
+ Default:
143
+
144
+ ```json
145
+ {
146
+ "ccShebangMarkdown.pattern": "^#!.*\\bcc-(md|markdown)\\b"
147
+ }
148
+ ```
149
+
150
+ ### `ccShebangMarkdown.targetLanguage`
151
+
152
+ VS Code language id to apply when the pattern matches.
153
+
154
+ Default:
155
+
156
+ ```json
157
+ {
158
+ "ccShebangMarkdown.targetLanguage": "markdown"
159
+ }
160
+ ```
161
+
162
+ Advanced example:
163
+
164
+ ```json
165
+ {
166
+ "ccShebangMarkdown.pattern": "^#!.*\\bcompany-doc\\b",
167
+ "ccShebangMarkdown.targetLanguage": "markdown"
168
+ }
169
+ ```
170
+
171
+ ---
172
+
173
+ ## markdownlint note
174
+
175
+ Some lint configurations require the first line of a Markdown document to be a heading. A shebang intentionally violates that rule.
176
+
177
+ For shebang-based Markdown files, you may want to disable `MD041`:
178
+
179
+ ```json
180
+ {
181
+ "markdownlint.config": {
182
+ "MD041": false
183
+ }
184
+ }
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Development
190
+
191
+ Clone the repository and install dependencies:
192
+
193
+ ```bash
194
+ npm install
195
+ ```
196
+
197
+ Package the VS Code extension:
198
+
199
+ ```bash
200
+ npm run pack:vsix
201
+ ```
202
+
203
+ Install it locally:
204
+
205
+ ```bash
206
+ npm run reinstall
207
+ ```
208
+
209
+ Check npm package contents before publishing:
210
+
211
+ ```bash
212
+ npm run pack:npm
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Release flow
218
+
219
+ Bump the version in `package.json`, then run:
220
+
221
+ ```bash
222
+ npm install
223
+ npm run pack:vsix
224
+ npm run pack:npm
225
+ npm publish
226
+ ```
227
+
228
+ For scoped npm packages, npm requires public scoped packages to be published with `npm publish --access public`. This package is intentionally unscoped, so plain `npm publish` is enough.
229
+
230
+ ---
231
+
232
+ ## Design principles
233
+
234
+ - Do one thing.
235
+ - Avoid filename conventions when the contract belongs in the file content.
236
+ - Keep the rule explicit and visible.
237
+ - Do not hijack unrelated files.
238
+ - Prefer configurable detection over hardcoded project paths.
239
+
240
+ ---
241
+
242
+ ## Security
243
+
244
+ This extension only reads the first line of open text documents and changes VS Code language mode through the VS Code API.
245
+
246
+ It does not:
247
+
248
+ - execute file contents;
249
+ - send telemetry;
250
+ - perform network requests;
251
+ - read secrets;
252
+ - modify files on disk.
253
+
254
+ Please report security issues privately when possible. See [SECURITY.md](SECURITY.md).
255
+
256
+ ---
257
+
258
+ ## Contributing
259
+
260
+ Issues and pull requests are welcome.
261
+
262
+ See [CONTRIBUTING.md](CONTRIBUTING.md).
263
+
264
+ ---
265
+
266
+ ## License
267
+
268
+ MIT. See [LICENSE](LICENSE).
269
+
270
+ ---
271
+
272
+ ## Maintainer
273
+
274
+ Built and maintained by **Federico Girolami** / **CodeCorn Technology**.
275
+
276
+ CodeCorn™ — We build software that Corn.
277
+
278
+ ## Language fallback rules
279
+
280
+ Besides CodeCorn Markdown shebangs, the extension also ships with defensive fallback rules for common script/config files.
281
+
282
+ ### Shell scripts
283
+
284
+ The extension reinforces VS Code detection for:
285
+
286
+ ```text
287
+ #!/bin/bash
288
+ #!/bin/zsh
289
+ #!/bin/sh
290
+ #!/usr/bin/bash
291
+ #!/usr/bin/zsh
292
+ #!/usr/bin/sh
293
+ #!/usr/local/bin/bash
294
+ #!/usr/bin/env bash
295
+ #!/usr/bin/env zsh
296
+ #!/usr/bin/env sh
297
+ #!/usr/bin/env -S bash -euo pipefail
298
+ ```
299
+
300
+ Matching files are switched to:
301
+
302
+ ```text
303
+ shellscript
304
+ ```
305
+
306
+ ### nginx
307
+
308
+ The extension includes a defensive fallback for:
309
+
310
+ ```text
311
+ nginx.conf
312
+ conf.d/*.conf
313
+ ```
314
+
315
+ and for files containing common nginx blocks near the top:
316
+
317
+ ```nginx
318
+ events {
319
+ }
320
+
321
+ http {
322
+ }
323
+
324
+ server {
325
+ }
326
+
327
+ upstream backend {
328
+ }
329
+ ```
330
+
331
+ Matching files are switched to:
332
+
333
+ ```text
334
+ nginx
335
+ ```
336
+
337
+ If the `nginx` language id is not available in the current VS Code installation, the rule falls back to `plaintext` instead of throwing.
package/README_IT.md ADDED
@@ -0,0 +1,96 @@
1
+ # CodeCorn Shebang Markdown
2
+
3
+ **CodeCorn Shebang Markdown** è una piccola estensione per Visual Studio Code che legge la prima riga di un file e, se trova uno shebang configurato, forza il language mode a Markdown.
4
+
5
+ Serve quando hai file senza estensione `.md`, oppure file operativi/script-like, che devono comunque essere trattati come Markdown da VS Code, markdownlint e formatter.
6
+
7
+ ---
8
+
9
+ ## Esempio
10
+
11
+ ```text
12
+ #!/usr/bin/env cc-md
13
+
14
+ # Checklist deploy
15
+
16
+ - backup database
17
+ - dump env
18
+ - patch
19
+ - verifica log
20
+ ```
21
+
22
+ Anche senza estensione `.md`, VS Code imposta il file come `markdown`.
23
+
24
+ ---
25
+
26
+ ## Shebang supportati
27
+
28
+ Pattern default:
29
+
30
+ ```text
31
+ ^#!.*\bcc-(md|markdown)\b
32
+ ```
33
+
34
+ Esempi:
35
+
36
+ ```text
37
+ #!/usr/bin/env cc-md
38
+ ```
39
+
40
+ ```text
41
+ #!cc-md
42
+ ```
43
+
44
+ ```text
45
+ #!/usr/bin/env cc-markdown
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Configurazione
51
+
52
+ ```json
53
+ {
54
+ "ccShebangMarkdown.pattern": "^#!.*\\bcc-(md|markdown)\\b",
55
+ "ccShebangMarkdown.targetLanguage": "markdown"
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Nota markdownlint
62
+
63
+ Se `markdownlint` segnala che la prima riga non è un heading, puoi disattivare `MD041` per questo workflow:
64
+
65
+ ```json
66
+ {
67
+ "markdownlint.config": {
68
+ "MD041": false
69
+ }
70
+ }
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Installazione locale
76
+
77
+ ```bash
78
+ npm install
79
+ npm run reinstall
80
+ ```
81
+
82
+ Questo genera il `.vsix` e lo installa in VS Code.
83
+
84
+ ---
85
+
86
+ ## Licenza
87
+
88
+ MIT.
89
+
90
+ ---
91
+
92
+ ## Maintainer
93
+
94
+ Federico Girolami / CodeCorn Technology.
95
+
96
+ CodeCorn™ — We build software that Corn.
package/SECURITY.md ADDED
@@ -0,0 +1,20 @@
1
+ # Security Policy
2
+
3
+ ## Supported versions
4
+
5
+ Security fixes are provided for the latest published version.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Please report security issues privately when possible.
10
+
11
+ Contact:
12
+
13
+ - Federico Girolami
14
+ - f.girolami@codecorn.it
15
+
16
+ ## Security model
17
+
18
+ This extension only reads the first line of open text documents and changes the VS Code language mode when the configured pattern matches.
19
+
20
+ It does not execute file contents, send telemetry, perform network requests or modify files on disk.
package/extension.js ADDED
@@ -0,0 +1,221 @@
1
+ const vscode = require('vscode');
2
+
3
+ const applying = new WeakSet();
4
+
5
+ const DEFAULT_RULES = [
6
+ {
7
+ name: 'CodeCorn Markdown shebang',
8
+ when: 'firstLine',
9
+ pattern: '^#!.*\\bcc-(md|markdown)\\b',
10
+ language: 'markdown'
11
+ },
12
+ {
13
+ name: 'POSIX shell shebang',
14
+ when: 'firstLine',
15
+ pattern: '^#!\\s*(?:/(?:usr/)?(?:local/)?bin/(?:bash|zsh|sh)\\b|/usr/bin/env\\s+(?:-[^\\s]+\\s+)*(?:bash|zsh|sh)\\b|/bin/env\\s+(?:-[^\\s]+\\s+)*(?:bash|zsh|sh)\\b)',
16
+ language: 'shellscript'
17
+ },
18
+ {
19
+ name: 'nginx.conf path',
20
+ when: 'path',
21
+ pattern: '(?:^|[/\\\\])nginx\\.conf$|(?:^|[/\\\\])conf\\.d[/\\\\].*\\.conf$',
22
+ language: 'nginx',
23
+ fallbackLanguage: 'plaintext'
24
+ },
25
+ {
26
+ name: 'nginx content fallback',
27
+ when: 'content',
28
+ pattern: '(?m)^\\s*(events|http|server|upstream)\\s*\\{|^\\s*location\\s+[^\\n]+\\{',
29
+ language: 'nginx',
30
+ fallbackLanguage: 'plaintext'
31
+ }
32
+ ];
33
+
34
+ function compileRule(rule) {
35
+ if (!rule || typeof rule !== 'object') return null;
36
+ if (!rule.pattern || !rule.language) return null;
37
+
38
+ try {
39
+ return {
40
+ name: String(rule.name || rule.language),
41
+ when: String(rule.when || 'firstLine'),
42
+ pattern: new RegExp(String(rule.pattern)),
43
+ language: String(rule.language),
44
+ fallbackLanguage: rule.fallbackLanguage ? String(rule.fallbackLanguage) : ''
45
+ };
46
+ } catch (err) {
47
+ console.warn('[cc-shebang-markdown] Invalid rule regex:', rule, err);
48
+ return null;
49
+ }
50
+ }
51
+
52
+ function readRules() {
53
+ const cfg = vscode.workspace.getConfiguration();
54
+
55
+ const legacyPattern = cfg.get(
56
+ 'ccShebangMarkdown.pattern',
57
+ '^#!.*\\bcc-(md|markdown)\\b'
58
+ );
59
+
60
+ const legacyTargetLanguage = cfg.get(
61
+ 'ccShebangMarkdown.targetLanguage',
62
+ 'markdown'
63
+ );
64
+
65
+ const configuredRules = cfg.get('ccShebangMarkdown.rules', DEFAULT_RULES);
66
+
67
+ const rules = Array.isArray(configuredRules) && configuredRules.length > 0
68
+ ? configuredRules
69
+ : DEFAULT_RULES;
70
+
71
+ const compiled = rules
72
+ .map(compileRule)
73
+ .filter(Boolean);
74
+
75
+ /*
76
+ * Backward compatibility:
77
+ * old config keys still work and remain first priority.
78
+ */
79
+ const legacyRule = compileRule({
80
+ name: 'legacy ccShebangMarkdown.pattern',
81
+ when: 'firstLine',
82
+ pattern: legacyPattern,
83
+ language: legacyTargetLanguage
84
+ });
85
+
86
+ return [
87
+ legacyRule,
88
+ ...compiled
89
+ ].filter(Boolean);
90
+ }
91
+
92
+ function getProbeText(document) {
93
+ if (!document || document.lineCount < 1) return '';
94
+
95
+ const endLine = Math.min(document.lineCount, 80);
96
+ const endCharacter = endLine > 0 ? document.lineAt(endLine - 1).text.length : 0;
97
+
98
+ return document.getText(
99
+ new vscode.Range(0, 0, Math.max(0, endLine - 1), endCharacter)
100
+ );
101
+ }
102
+
103
+ function matchesRule(document, rule) {
104
+ if (!document || !rule) return false;
105
+
106
+ if (rule.when === 'path') {
107
+ const path = document.uri && document.uri.fsPath
108
+ ? document.uri.fsPath
109
+ : document.fileName || '';
110
+
111
+ return rule.pattern.test(path);
112
+ }
113
+
114
+ if (rule.when === 'content') {
115
+ return rule.pattern.test(getProbeText(document));
116
+ }
117
+
118
+ const firstLine = document.lineCount > 0
119
+ ? document.lineAt(0).text
120
+ : '';
121
+
122
+ return rule.pattern.test(firstLine);
123
+ }
124
+
125
+ async function resolveLanguage(rule) {
126
+ const available = await vscode.languages.getLanguages();
127
+
128
+ if (available.includes(rule.language)) {
129
+ return rule.language;
130
+ }
131
+
132
+ if (rule.fallbackLanguage && available.includes(rule.fallbackLanguage)) {
133
+ console.warn(
134
+ `[cc-shebang-markdown] Language "${rule.language}" unavailable, using fallback "${rule.fallbackLanguage}" for rule "${rule.name}".`
135
+ );
136
+
137
+ return rule.fallbackLanguage;
138
+ }
139
+
140
+ console.warn(
141
+ `[cc-shebang-markdown] Language "${rule.language}" unavailable for rule "${rule.name}".`
142
+ );
143
+
144
+ return '';
145
+ }
146
+
147
+ async function maybeForceLanguage(document) {
148
+ if (!document || document.isClosed) return;
149
+ if (document.lineCount < 1) return;
150
+ if (applying.has(document)) return;
151
+
152
+ const rules = readRules();
153
+ const matchedRule = rules.find((rule) => matchesRule(document, rule));
154
+
155
+ if (!matchedRule) return;
156
+
157
+ const targetLanguage = await resolveLanguage(matchedRule);
158
+
159
+ if (!targetLanguage) return;
160
+ if (document.languageId === targetLanguage) return;
161
+
162
+ applying.add(document);
163
+
164
+ try {
165
+ await vscode.languages.setTextDocumentLanguage(document, targetLanguage);
166
+ console.info(
167
+ `[cc-shebang-markdown] Applied "${targetLanguage}" via rule "${matchedRule.name}".`
168
+ );
169
+ } catch (err) {
170
+ console.warn(
171
+ '[cc-shebang-markdown] Could not change language mode:',
172
+ err
173
+ );
174
+ } finally {
175
+ applying.delete(document);
176
+ }
177
+ }
178
+
179
+ function activate(context) {
180
+ for (const document of vscode.workspace.textDocuments) {
181
+ maybeForceLanguage(document);
182
+ }
183
+
184
+ context.subscriptions.push(
185
+ vscode.workspace.onDidOpenTextDocument((document) => {
186
+ maybeForceLanguage(document);
187
+ }),
188
+
189
+ vscode.workspace.onDidChangeTextDocument((event) => {
190
+ const touchesFirstLine = event.contentChanges.some((change) => {
191
+ return change.range.start.line === 0 || change.range.end.line === 0;
192
+ });
193
+
194
+ /*
195
+ * For content-based fallbacks, also retry on early document edits.
196
+ */
197
+ const touchesProbeArea = event.contentChanges.some((change) => {
198
+ return change.range.start.line < 80 || change.range.end.line < 80;
199
+ });
200
+
201
+ if (touchesFirstLine || touchesProbeArea) {
202
+ maybeForceLanguage(event.document);
203
+ }
204
+ }),
205
+
206
+ vscode.workspace.onDidChangeConfiguration((event) => {
207
+ if (!event.affectsConfiguration('ccShebangMarkdown')) return;
208
+
209
+ for (const document of vscode.workspace.textDocuments) {
210
+ maybeForceLanguage(document);
211
+ }
212
+ })
213
+ );
214
+ }
215
+
216
+ function deactivate() {}
217
+
218
+ module.exports = {
219
+ activate,
220
+ deactivate
221
+ };
package/package.json ADDED
@@ -0,0 +1,149 @@
1
+ {
2
+ "name": "cc-vscode-shebang-markdown",
3
+ "displayName": "CodeCorn Shebang Markdown",
4
+ "description": "VS Code extension that detects custom shebangs and file fallbacks to switch language mode for linters.",
5
+ "version": "0.1.1",
6
+ "publisher": "codecorn",
7
+ "engines": {
8
+ "vscode": "^1.80.0"
9
+ },
10
+ "categories": [
11
+ "Linters",
12
+ "Other"
13
+ ],
14
+ "activationEvents": [
15
+ "onStartupFinished",
16
+ "onLanguage:plaintext",
17
+ "onLanguage:shellscript"
18
+ ],
19
+ "main": "./extension.js",
20
+ "contributes": {
21
+ "configuration": {
22
+ "title": "CodeCorn Shebang Markdown",
23
+ "properties": {
24
+ "ccShebangMarkdown.pattern": {
25
+ "type": "string",
26
+ "default": "^#!.*\\\\bcc-(md|markdown)\\\\b",
27
+ "description": "Legacy regex applicata alla prima riga. Se matcha, viene applicato ccShebangMarkdown.targetLanguage."
28
+ },
29
+ "ccShebangMarkdown.targetLanguage": {
30
+ "type": "string",
31
+ "default": "markdown",
32
+ "description": "Legacy VS Code language id da applicare quando ccShebangMarkdown.pattern matcha."
33
+ },
34
+ "ccShebangMarkdown.rules": {
35
+ "type": "array",
36
+ "description": "Regole ordinate per forzare il language mode in base a firstLine, path o content.",
37
+ "default": [
38
+ {
39
+ "name": "CodeCorn Markdown shebang",
40
+ "when": "firstLine",
41
+ "pattern": "^#!.*\\\\bcc-(md|markdown)\\\\b",
42
+ "language": "markdown"
43
+ },
44
+ {
45
+ "name": "POSIX shell shebang",
46
+ "when": "firstLine",
47
+ "pattern": "^#!\\\\s*(?:/(?:usr/)?(?:local/)?bin/(?:bash|zsh|sh)\\\\b|/usr/bin/env\\\\s+(?:-[^\\\\s]+\\\\s+)*(?:bash|zsh|sh)\\\\b|/bin/env\\\\s+(?:-[^\\\\s]+\\\\s+)*(?:bash|zsh|sh)\\\\b)",
48
+ "language": "shellscript"
49
+ },
50
+ {
51
+ "name": "nginx.conf path",
52
+ "when": "path",
53
+ "pattern": "(?:^|[/\\\\\\\\])nginx\\\\.conf$|(?:^|[/\\\\\\\\])conf\\\\.d[/\\\\\\\\].*\\\\.conf$",
54
+ "language": "nginx",
55
+ "fallbackLanguage": "plaintext"
56
+ },
57
+ {
58
+ "name": "nginx content fallback",
59
+ "when": "content",
60
+ "pattern": "(?m)^\\\\s*(events|http|server|upstream)\\\\s*\\\\{|^\\\\s*location\\\\s+[^\\\\n]+\\\\{",
61
+ "language": "nginx",
62
+ "fallbackLanguage": "plaintext"
63
+ }
64
+ ],
65
+ "items": {
66
+ "type": "object",
67
+ "required": [
68
+ "pattern",
69
+ "language"
70
+ ],
71
+ "properties": {
72
+ "name": {
73
+ "type": "string"
74
+ },
75
+ "when": {
76
+ "type": "string",
77
+ "enum": [
78
+ "firstLine",
79
+ "path",
80
+ "content"
81
+ ],
82
+ "default": "firstLine"
83
+ },
84
+ "pattern": {
85
+ "type": "string"
86
+ },
87
+ "language": {
88
+ "type": "string"
89
+ },
90
+ "fallbackLanguage": {
91
+ "type": "string"
92
+ }
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ },
99
+ "scripts": {
100
+ "build": "npm run pack:vsix",
101
+ "package": "vsce package",
102
+ "pack:npm": "npm pack --dry-run",
103
+ "pack:vsix": "vsce package",
104
+ "install:local": "bash scripts/cc-install-local.sh",
105
+ "reinstall": "npm run pack:vsix && npm run install:local",
106
+ "bump": "bash scripts/cc-npm-bump.sh",
107
+ "publish": "bash scripts/cc-npm-publish.sh",
108
+ "prepublishOnly": "npm run pack:npm"
109
+ },
110
+ "repository": {
111
+ "type": "git",
112
+ "url": "git+https://github.com/fgirolami/cc-vscode-shebang-markdown.git"
113
+ },
114
+ "keywords": [
115
+ "vscode",
116
+ "vscode-extension",
117
+ "markdown",
118
+ "shebang",
119
+ "markdownlint",
120
+ "linter",
121
+ "language-detection",
122
+ "language-mode",
123
+ "developer-tools",
124
+ "codecorn"
125
+ ],
126
+ "author": {
127
+ "name": "Federico Girolami",
128
+ "email": "f.girolami@codecorn.it",
129
+ "url": "https://codecorn.it"
130
+ },
131
+ "license": "MIT",
132
+ "devDependencies": {
133
+ "@vscode/vsce": "^3.9.2"
134
+ },
135
+ "files": [
136
+ "extension.js",
137
+ "README.md",
138
+ "README_IT.md",
139
+ "CHANGELOG.md",
140
+ "SECURITY.md",
141
+ "CONTRIBUTING.md",
142
+ "LICENSE",
143
+ "package.json",
144
+ "scripts/cc-install-local.sh",
145
+ "scripts/cc-npm-bump.sh",
146
+ "scripts/cc-npm-publish.sh"
147
+ ],
148
+ "sideEffects": false
149
+ }
@@ -0,0 +1,19 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ PKG_NAME="$(node -p "require('./package.json').name")"
5
+ VERSION="$(node -p "require('./package.json').version")"
6
+ VSIX="${PKG_NAME}-${VERSION}.vsix"
7
+
8
+ echo "===== CC LOCAL VSIX INSTALL ====="
9
+ echo "PKG_NAME: $PKG_NAME"
10
+ echo "VERSION: $VERSION"
11
+ echo "VSIX: $VSIX"
12
+ echo
13
+
14
+ if [ ! -f "$VSIX" ]; then
15
+ echo "VSIX non trovato, genero package..."
16
+ npm run pack:vsix
17
+ fi
18
+
19
+ code --install-extension "$VSIX" --force
@@ -0,0 +1,81 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ BUMP="${1:-patch}"
5
+ NO_COMMIT="${NO_COMMIT:-0}"
6
+
7
+ if [ ! -f package.json ]; then
8
+ echo "ERRORE: package.json non trovato."
9
+ exit 1
10
+ fi
11
+
12
+ CURRENT_VERSION="$(node -p "require('./package.json').version")"
13
+ PKG_NAME="$(node -p "require('./package.json').name")"
14
+
15
+ echo "===== CC NPM BUMP ====="
16
+ echo "PKG_NAME: $PKG_NAME"
17
+ echo "CURRENT_VERSION: $CURRENT_VERSION"
18
+ echo "BUMP: $BUMP"
19
+ echo
20
+
21
+ BACKUP_DIR=".cc-backups/npm-bump-$(date +%Y%m%d-%H%M%S)"
22
+ mkdir -p "$BACKUP_DIR"
23
+ cp -p package.json "$BACKUP_DIR/package.json"
24
+ [ -f package-lock.json ] && cp -p package-lock.json "$BACKUP_DIR/package-lock.json"
25
+
26
+ echo "Backup: $BACKUP_DIR"
27
+ echo
28
+
29
+ echo "===== VERSION UPDATE ====="
30
+ npm version "$BUMP" --no-git-tag-version
31
+
32
+ NEW_VERSION="$(node -p "require('./package.json').version")"
33
+
34
+ echo
35
+ echo "===== LOCK REFRESH ====="
36
+ npm install --package-lock-only
37
+
38
+ echo
39
+ echo "===== INSTALL SCRIPT VERSION CHECK ====="
40
+ node <<'NODE'
41
+ const fs = require('fs');
42
+
43
+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
44
+ const version = pkg.version;
45
+ const name = pkg.name;
46
+
47
+ if (!pkg.scripts) pkg.scripts = {};
48
+
49
+ pkg.scripts['install:local'] = 'bash scripts/cc-install-local.sh';
50
+ pkg.scripts['reinstall'] = 'npm run pack:vsix && npm run install:local';
51
+
52
+ fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
53
+
54
+ console.log(`${name}@${version}`);
55
+ NODE
56
+
57
+ echo
58
+ echo "===== GIT DIFF ====="
59
+ git diff -- package.json package-lock.json || true
60
+
61
+ if [ "$NO_COMMIT" = "1" ]; then
62
+ echo
63
+ echo "NO_COMMIT=1: commit saltato."
64
+ else
65
+ echo
66
+ echo "===== GIT COMMIT ====="
67
+ git add package.json package-lock.json
68
+
69
+ if ! git diff --cached --quiet; then
70
+ git commit -m "chore: bump version to ${NEW_VERSION}"
71
+ else
72
+ echo "Nothing to commit."
73
+ fi
74
+ fi
75
+
76
+ echo
77
+ echo "===== DONE ====="
78
+ echo "${PKG_NAME}: ${CURRENT_VERSION} -> ${NEW_VERSION}"
79
+ echo
80
+ echo "Next:"
81
+ echo "npm run publish"
@@ -0,0 +1,134 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ PKG_NAME="${PKG_NAME:-$(node -p "require('./package.json').name")}"
5
+ VERSION="${VERSION:-$(node -p "require('./package.json').version")}"
6
+ REMOTE_NAME="${REMOTE_NAME:-origin}"
7
+
8
+ PUBLISH_NEEDED=1
9
+ PUBLISH_OK=0
10
+ NPM_AUTH_OK=0
11
+ NPM_USER=""
12
+
13
+ echo "===== PACKAGE META ====="
14
+ echo "PKG_NAME: $PKG_NAME"
15
+ echo "VERSION: $VERSION"
16
+ echo
17
+
18
+ echo "===== NPM AUTH CHECK ====="
19
+ if NPM_USER="$(npm whoami 2>/dev/null)"; then
20
+ NPM_AUTH_OK=1
21
+ echo "NPM_USER: $NPM_USER"
22
+ else
23
+ NPM_AUTH_OK=0
24
+ echo "WARN: npm non è loggato oppure la sessione è scaduta."
25
+ echo " Esegui: npm login"
26
+ echo " Publish e tag verranno saltati, ma build/commit continuano."
27
+ fi
28
+
29
+ echo
30
+ echo "===== INSTALL / LOCK REFRESH ====="
31
+ npm install
32
+
33
+ echo
34
+ echo "===== VSIX BUILD ====="
35
+ npm run pack:vsix
36
+
37
+ echo
38
+ echo "===== NPM PACK DRY RUN ====="
39
+ npm run pack:npm
40
+
41
+ echo
42
+ echo "===== NPM VERSION CHECK ====="
43
+ EXISTING_LATEST="$(npm view "$PKG_NAME" version 2>/dev/null || true)"
44
+ EXISTING_THIS_VERSION="$(npm view "${PKG_NAME}@${VERSION}" version 2>/dev/null || true)"
45
+
46
+ if [ -n "$EXISTING_LATEST" ]; then
47
+ echo "Package npm già esistente: $PKG_NAME"
48
+ echo "Latest npm version: $EXISTING_LATEST"
49
+ else
50
+ echo "Package npm non ancora esistente: $PKG_NAME"
51
+ fi
52
+
53
+ if [ -n "$EXISTING_THIS_VERSION" ]; then
54
+ echo "Versione già pubblicata su npm: ${PKG_NAME}@${VERSION}"
55
+ echo "Publish non necessario."
56
+ PUBLISH_NEEDED=0
57
+ else
58
+ echo "Versione pubblicabile: ${PKG_NAME}@${VERSION}"
59
+ PUBLISH_NEEDED=1
60
+ fi
61
+
62
+ echo
63
+ echo "===== GIT COMMIT ====="
64
+ git add package.json package-lock.json README.md README_IT.md CHANGELOG.md SECURITY.md CONTRIBUTING.md .npmignore .vscodeignore extension.js LICENSE scripts/cc-npm-publish.sh scripts/cc-npm-bump.sh scripts/cc-install-local.sh 2>/dev/null || true
65
+
66
+ if ! git diff --cached --quiet; then
67
+ git commit -m "chore: prepare npm package ${VERSION}"
68
+ else
69
+ echo "Nothing to commit."
70
+ fi
71
+
72
+ echo
73
+ echo "===== GIT PUSH MAIN ====="
74
+ if git remote get-url "$REMOTE_NAME" >/dev/null 2>&1; then
75
+ git push "$REMOTE_NAME" main
76
+ else
77
+ echo "WARN: remote '$REMOTE_NAME' non configurato. Push main saltato."
78
+ fi
79
+
80
+ echo
81
+ echo "===== NPM PUBLISH ====="
82
+ if [ "$PUBLISH_NEEDED" = "0" ]; then
83
+ echo "SKIP: ${PKG_NAME}@${VERSION} è già pubblicato."
84
+ PUBLISH_OK=1
85
+ elif [ "$NPM_AUTH_OK" != "1" ]; then
86
+ echo "SKIP: npm auth non disponibile."
87
+ echo
88
+ echo "Dopo login puoi rilanciare:"
89
+ echo "npm run publish"
90
+ PUBLISH_OK=0
91
+ else
92
+ if npm publish; then
93
+ PUBLISH_OK=1
94
+ echo "OK: pubblicato ${PKG_NAME}@${VERSION}"
95
+ else
96
+ PUBLISH_OK=0
97
+ echo "WARN: npm publish fallito."
98
+ echo " Possibili cause: sessione scaduta, 2FA/OTP, permessi package, nome già riservato."
99
+ echo " Nessun tag git verrà creato."
100
+ fi
101
+ fi
102
+
103
+ echo
104
+ echo "===== GIT TAG ====="
105
+ if [ "$PUBLISH_OK" = "1" ]; then
106
+ TAG="v${VERSION}"
107
+
108
+ if git rev-parse "$TAG" >/dev/null 2>&1; then
109
+ echo "Tag già esistente localmente: $TAG"
110
+ else
111
+ git tag "$TAG"
112
+ fi
113
+
114
+ if git remote get-url "$REMOTE_NAME" >/dev/null 2>&1; then
115
+ git push "$REMOTE_NAME" "$TAG"
116
+ else
117
+ echo "WARN: remote '$REMOTE_NAME' non configurato. Push tag saltato."
118
+ fi
119
+ else
120
+ echo "SKIP: tag saltato perché npm publish non è andato a buon fine."
121
+ fi
122
+
123
+ echo
124
+ echo "===== DONE ====="
125
+ echo "Package: ${PKG_NAME}@${VERSION}"
126
+
127
+ if npm view "$PKG_NAME" version >/dev/null 2>&1; then
128
+ echo "NPM VERSION:"
129
+ npm view "$PKG_NAME" version
130
+ echo "NPM HOMEPAGE:"
131
+ npm view "$PKG_NAME" homepage 2>/dev/null || true
132
+ else
133
+ echo "Npm package non ancora visibile/pubblicato."
134
+ fi