Skip to content

Commit b0c8204

Browse files
Add support for GitLab.com (#558)
1 parent c1db3cc commit b0c8204

10 files changed

+547
-32
lines changed

src/main.ts

+50-14
Original file line numberDiff line numberDiff line change
@@ -82,29 +82,48 @@ module.exports = function (argv: string[]): void {
8282
'--githubBranch [branch]',
8383
'The GitHub branch used to infer relative links in README.md. Can be overriden by --baseContentUrl and --baseImagesUrl.'
8484
)
85+
.option(
86+
'--gitlabBranch [branch]',
87+
'The GitLab branch used to infer relative links in README.md. Can be overriden by --baseContentUrl and --baseImagesUrl.'
88+
)
8589
.option('--baseContentUrl [url]', 'Prepend all relative links in README.md with this url.')
8690
.option('--baseImagesUrl [url]', 'Prepend all relative image links in README.md with this url.')
8791
.option('--yarn', 'Use yarn instead of npm (default inferred from presence of yarn.lock or .yarnrc)')
8892
.option('--no-yarn', 'Use npm instead of yarn (default inferred from lack of yarn.lock or .yarnrc)')
8993
.option('--ignoreFile [path]', 'Indicate alternative .vscodeignore')
9094
.option('--no-gitHubIssueLinking', 'Disable automatic expansion of GitHub-style issue syntax into links')
95+
.option('--no-gitLabIssueLinking', 'Disable automatic expansion of GitLab-style issue syntax into links')
9196
.option(
9297
'--web',
9398
'Experimental flag to enable publishing web extensions. Note: This is supported only for selected extensions.'
9499
)
95-
.action(({ out, githubBranch, baseContentUrl, baseImagesUrl, yarn, ignoreFile, gitHubIssueLinking, web }) =>
96-
main(
97-
packageCommand({
98-
packagePath: out,
99-
githubBranch,
100-
baseContentUrl,
101-
baseImagesUrl,
102-
useYarn: yarn,
103-
ignoreFile,
104-
gitHubIssueLinking,
105-
web,
106-
})
107-
)
100+
.action(
101+
({
102+
out,
103+
githubBranch,
104+
gitlabBranch,
105+
baseContentUrl,
106+
baseImagesUrl,
107+
yarn,
108+
ignoreFile,
109+
gitHubIssueLinking,
110+
gitLabIssueLinking,
111+
web,
112+
}) =>
113+
main(
114+
packageCommand({
115+
packagePath: out,
116+
githubBranch,
117+
gitlabBranch,
118+
baseContentUrl,
119+
baseImagesUrl,
120+
useYarn: yarn,
121+
ignoreFile,
122+
gitHubIssueLinking,
123+
gitLabIssueLinking,
124+
web,
125+
})
126+
)
108127
);
109128

110129
program
@@ -121,6 +140,10 @@ module.exports = function (argv: string[]): void {
121140
'--githubBranch [branch]',
122141
'The GitHub branch used to infer relative links in README.md. Can be overriden by --baseContentUrl and --baseImagesUrl.'
123142
)
143+
.option(
144+
'--gitlabBranch [branch]',
145+
'The GitLab branch used to infer relative links in README.md. Can be overriden by --baseContentUrl and --baseImagesUrl.'
146+
)
124147
.option('--baseContentUrl [url]', 'Prepend all relative links in README.md with this url.')
125148
.option('--baseImagesUrl [url]', 'Prepend all relative image links in README.md with this url.')
126149
.option('--yarn', 'Use yarn instead of npm (default inferred from presence of yarn.lock or .yarnrc)')
@@ -134,7 +157,19 @@ module.exports = function (argv: string[]): void {
134157
.action(
135158
(
136159
version,
137-
{ pat, message, packagePath, githubBranch, baseContentUrl, baseImagesUrl, yarn, noVerify, ignoreFile, web }
160+
{
161+
pat,
162+
message,
163+
packagePath,
164+
githubBranch,
165+
gitlabBranch,
166+
baseContentUrl,
167+
baseImagesUrl,
168+
yarn,
169+
noVerify,
170+
ignoreFile,
171+
web,
172+
}
138173
) =>
139174
main(
140175
publish({
@@ -143,6 +178,7 @@ module.exports = function (argv: string[]): void {
143178
version,
144179
packagePath,
145180
githubBranch,
181+
gitlabBranch,
146182
baseContentUrl,
147183
baseImagesUrl,
148184
useYarn: yarn,

src/package.ts

+47-17
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,14 @@ export interface IPackageOptions {
7979
readonly cwd?: string;
8080
readonly packagePath?: string;
8181
readonly githubBranch?: string;
82+
readonly gitlabBranch?: string;
8283
readonly baseContentUrl?: string;
8384
readonly baseImagesUrl?: string;
8485
readonly useYarn?: boolean;
8586
readonly dependencyEntryPoints?: string[];
8687
readonly ignoreFile?: string;
8788
readonly gitHubIssueLinking?: boolean;
89+
readonly gitLabIssueLinking?: boolean;
8890
readonly web?: boolean;
8991
}
9092

@@ -202,6 +204,10 @@ function isGitHubRepository(repository: string): boolean {
202204
return /^https:\/\/github\.com\/|^git@github\.com:/.test(repository || '');
203205
}
204206

207+
function isGitLabRepository(repository: string): boolean {
208+
return /^https:\/\/gitlab\.com\/|^git@gitlab\.com:/.test(repository || '');
209+
}
210+
205211
function isGitHubBadge(href: string): boolean {
206212
return /^https:\/\/github\.com\/[^/]+\/[^/]+\/workflows\/.*badge\.svg/.test(href || '');
207213
}
@@ -420,8 +426,10 @@ export class MarkdownProcessor extends BaseProcessor {
420426
private baseContentUrl: string;
421427
private baseImagesUrl: string;
422428
private isGitHub: boolean;
429+
private isGitLab: boolean;
423430
private repositoryUrl: string;
424431
private gitHubIssueLinking: boolean;
432+
private gitLabIssueLinking: boolean;
425433

426434
constructor(
427435
manifest: Manifest,
@@ -432,13 +440,15 @@ export class MarkdownProcessor extends BaseProcessor {
432440
) {
433441
super(manifest);
434442

435-
const guess = this.guessBaseUrls(options.githubBranch);
443+
const guess = this.guessBaseUrls(options.githubBranch || options.gitlabBranch);
436444

437445
this.baseContentUrl = options.baseContentUrl || (guess && guess.content);
438446
this.baseImagesUrl = options.baseImagesUrl || options.baseContentUrl || (guess && guess.images);
439447
this.repositoryUrl = guess && guess.repository;
440448
this.isGitHub = isGitHubRepository(this.repositoryUrl);
449+
this.isGitLab = isGitLabRepository(this.repositoryUrl);
441450
this.gitHubIssueLinking = typeof options.gitHubIssueLinking === 'boolean' ? options.gitHubIssueLinking : true;
451+
this.gitLabIssueLinking = typeof options.gitLabIssueLinking === 'boolean' ? options.gitLabIssueLinking : true;
442452
}
443453

444454
async onFile(file: IFile): Promise<IFile> {
@@ -469,7 +479,7 @@ export class MarkdownProcessor extends BaseProcessor {
469479

470480
if (isLinkRelative) {
471481
throw new Error(
472-
`Couldn't detect the repository where this extension is published. The ${asset} '${link}' will be broken in ${this.name}. GitHub repositories will be automatically detected. Otherwise, please provide the repository URL in package.json or use the --baseContentUrl and --baseImagesUrl options.`
482+
`Couldn't detect the repository where this extension is published. The ${asset} '${link}' will be broken in ${this.name}. GitHub/GitLab repositories will be automatically detected. Otherwise, please provide the repository URL in package.json or use the --baseContentUrl and --baseImagesUrl options.`
473483
);
474484
}
475485
}
@@ -493,7 +503,7 @@ export class MarkdownProcessor extends BaseProcessor {
493503

494504
if (!this.baseImagesUrl && isLinkRelative) {
495505
throw new Error(
496-
`Couldn't detect the repository where this extension is published. The image will be broken in ${this.name}. GitHub repositories will be automatically detected. Otherwise, please provide the repository URL in package.json or use the --baseContentUrl and --baseImagesUrl options.`
506+
`Couldn't detect the repository where this extension is published. The image will be broken in ${this.name}. GitHub/GitLab repositories will be automatically detected. Otherwise, please provide the repository URL in package.json or use the --baseContentUrl and --baseImagesUrl options.`
497507
);
498508
}
499509
const prefix = this.baseImagesUrl;
@@ -505,7 +515,7 @@ export class MarkdownProcessor extends BaseProcessor {
505515
return all.replace(link, urljoin(prefix, link));
506516
});
507517

508-
if (this.gitHubIssueLinking && this.isGitHub) {
518+
if ((this.gitHubIssueLinking && this.isGitHub) || (this.gitLabIssueLinking && this.isGitLab)) {
509519
const markdownIssueRegex = /(\s|\n)([\w\d_-]+\/[\w\d_-]+)?#(\d+)\b/g;
510520
const issueReplace = (
511521
all: string,
@@ -523,11 +533,19 @@ export class MarkdownProcessor extends BaseProcessor {
523533

524534
if (owner && repositoryName && issueNumber) {
525535
// Issue in external repository
526-
const issueUrl = urljoin('https://github.com', owner, repositoryName, 'issues', issueNumber);
536+
const issueUrl = this.isGitHub
537+
? urljoin('https://github.com', owner, repositoryName, 'issues', issueNumber)
538+
: urljoin('https://gitlab.com', owner, repositoryName, '-', 'issues', issueNumber);
527539
result = prefix + `[${owner}/${repositoryName}#${issueNumber}](${issueUrl})`;
528540
} else if (!owner && !repositoryName && issueNumber) {
529541
// Issue in own repository
530-
result = prefix + `[#${issueNumber}](${urljoin(this.repositoryUrl, 'issues', issueNumber)})`;
542+
result =
543+
prefix +
544+
`[#${issueNumber}](${
545+
this.isGitHub
546+
? urljoin(this.repositoryUrl, 'issues', issueNumber)
547+
: urljoin(this.repositoryUrl, '-', 'issues', issueNumber)
548+
})`;
531549
}
532550

533551
return result;
@@ -569,7 +587,7 @@ export class MarkdownProcessor extends BaseProcessor {
569587
}
570588

571589
// GitHub heuristics
572-
private guessBaseUrls(githubBranch: string | undefined): { content: string; images: string; repository: string } {
590+
private guessBaseUrls(githostBranch: string | undefined): { content: string; images: string; repository: string } {
573591
let repository = null;
574592

575593
if (typeof this.manifest.repository === 'string') {
@@ -582,22 +600,34 @@ export class MarkdownProcessor extends BaseProcessor {
582600
return null;
583601
}
584602

585-
const regex = /github(\.com\/|:)([^/]+)\/([^/]+)(\/|$)/;
586-
const match = regex.exec(repository);
603+
const gitHubRegex = /(?<domain>github(\.com\/|:))(?<project>(?:[^/]+)\/(?:[^/]+))(\/|$)/;
604+
const gitLabRegex = /(?<domain>gitlab(\.com\/|:))(?<project>(?:[^/]+)(\/(?:[^/]+))+)(\/|$)/;
605+
const match = ((gitHubRegex.exec(repository) || gitLabRegex.exec(repository)) as unknown) as {
606+
groups: Record<string, string>;
607+
};
587608

588609
if (!match) {
589610
return null;
590611
}
591612

592-
const account = match[2];
593-
const repositoryName = match[3].replace(/\.git$/i, '');
594-
const branchName = githubBranch ? githubBranch : 'HEAD';
613+
const project = match.groups.project.replace(/\.git$/i, '');
614+
const branchName = githostBranch ? githostBranch : 'HEAD';
595615

596-
return {
597-
content: `https://github.com/${account}/${repositoryName}/blob/${branchName}`,
598-
images: `https://github.com/${account}/${repositoryName}/raw/${branchName}`,
599-
repository: `https://github.com/${account}/${repositoryName}`,
600-
};
616+
if (/^github/.test(match.groups.domain)) {
617+
return {
618+
content: `https://github.com/${project}/blob/${branchName}`,
619+
images: `https://github.com/${project}/raw/${branchName}`,
620+
repository: `https://github.com/${project}`,
621+
};
622+
} else if (/^gitlab/.test(match.groups.domain)) {
623+
return {
624+
content: `https://gitlab.com/${project}/-/blob/${branchName}`,
625+
images: `https://gitlab.com/${project}/-/raw/${branchName}`,
626+
repository: `https://gitlab.com/${project}`,
627+
};
628+
}
629+
630+
return null;
601631
}
602632
}
603633

src/publish.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export interface IPublishOptions {
119119
cwd?: string;
120120
pat?: string;
121121
githubBranch?: string;
122+
gitlabBranch?: string;
122123
baseContentUrl?: string;
123124
baseImagesUrl?: string;
124125
useYarn?: boolean;
@@ -190,6 +191,7 @@ export function publish(options: IPublishOptions = {}): Promise<any> {
190191
} else {
191192
const cwd = options.cwd;
192193
const githubBranch = options.githubBranch;
194+
const gitlabBranch = options.gitlabBranch;
193195
const baseContentUrl = options.baseContentUrl;
194196
const baseImagesUrl = options.baseImagesUrl;
195197
const useYarn = options.useYarn;
@@ -199,7 +201,7 @@ export function publish(options: IPublishOptions = {}): Promise<any> {
199201
promise = versionBump(options.cwd, options.version, options.commitMessage)
200202
.then(() => tmpName())
201203
.then(packagePath =>
202-
pack({ packagePath, cwd, githubBranch, baseContentUrl, baseImagesUrl, useYarn, ignoreFile, web })
204+
pack({ packagePath, cwd, githubBranch, gitlabBranch, baseContentUrl, baseImagesUrl, useYarn, ignoreFile, web })
203205
);
204206
}
205207

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# README
2+
3+
>**Important:** Once installed the checker will only update if you add the setting `"spellMD.enable": true` to your `.vscode\settings.json` file.
4+
5+
This README covers off:
6+
* [Functionality](#functionality)
7+
* [Install](#install)
8+
* [Run and Configure](#run-and-configure)
9+
* [Known Issues/Bugs](#known-issuesbugs)
10+
* [Backlog](#backlog)
11+
* [How to Debug](#how-to-debug)
12+
13+
# Functionality
14+
15+
Load up a Markdown file and get highlights and hovers for existing issues. Checking will occur as you type in the document.
16+
17+
![Underscores and hovers](https://gitlab.com/username/repository/-/raw/main/images/SpellMDDemo1.gif)
18+
19+
The status bar lets you quickly navigate to any issue and you can see all positions in the gutter.
20+
21+
[![Jump to issues](https://gitlab.com/username/repository/-/raw/main/images/SpellMDDemo2.gif)](http://shouldnottouchthis/)
22+
[![Jump to issues](https://gitlab.com/username/repository/-/raw/main/images/SpellMDDemo2.gif)](https://gitlab.com/username/repository/-/blob/main/monkey)
23+
![](https://gitlab.com/username/repository/-/raw/main/images/SpellMDDemo2.gif)
24+
<img src="https://gitlab.com/username/repository/-/raw/main/images/myImage.gif">
25+
26+
The `spellMD.json` config file is watched so you can add more ignores or change mappings at will.
27+
28+
![Add to dictionary](https://gitlab.com/username/repository/-/raw/main/images/SpellMDDemo3.gif)
29+
30+
![issue](https://gitlab.com/username/repository/-/raw/main/issue)
31+
32+
[mono](https://gitlab.com/username/repository/-/blob/main/monkey)
33+
[not](http://shouldnottouchthis/)
34+
[Email me](mailto:[email protected])
35+
36+
# Install
37+
This extension is published in the VS Code Gallery. So simply hit 'F1' and type 'ext inst' from there select `SpellMD` and follow instructions.
38+
39+
40+
To clone the extension and load locally...
41+
42+
```
43+
git clone https://github.com/Microsoft/vscode-SpellMD.git
44+
npm install
45+
tsc
46+
```
47+
48+
>**Note:** TypeScript 1.6 or higher is required you can check with `tsc -v` and if you need to upgrade then run `npm install -g typescript`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# README
2+
3+
>**Important:** Once installed the checker will only update if you add the setting `"spellMD.enable": true` to your `.vscode\settings.json` file.
4+
5+
This README covers off:
6+
* [Functionality](#functionality)
7+
* [Install](#install)
8+
* [Run and Configure](#run-and-configure)
9+
* [Known Issues/Bugs](#known-issuesbugs)
10+
* [Backlog](#backlog)
11+
* [How to Debug](#how-to-debug)
12+
13+
# Functionality
14+
15+
Load up a Markdown file and get highlights and hovers for existing issues. Checking will occur as you type in the document.
16+
17+
![Underscores and hovers](https://gitlab.com/base/images/SpellMDDemo1.gif)
18+
19+
The status bar lets you quickly navigate to any issue and you can see all positions in the gutter.
20+
21+
[![Jump to issues](https://gitlab.com/base/images/SpellMDDemo2.gif)](http://shouldnottouchthis/)
22+
[![Jump to issues](https://gitlab.com/base/images/SpellMDDemo2.gif)](https://gitlab.com/base/monkey)
23+
![](https://gitlab.com/base/images/SpellMDDemo2.gif)
24+
<img src="https://gitlab.com/base/images/myImage.gif">
25+
26+
The `spellMD.json` config file is watched so you can add more ignores or change mappings at will.
27+
28+
![Add to dictionary](https://gitlab.com/base/images/SpellMDDemo3.gif)
29+
30+
![issue](https://gitlab.com/base/issue)
31+
32+
[mono](https://gitlab.com/base/monkey)
33+
[not](http://shouldnottouchthis/)
34+
[Email me](mailto:[email protected])
35+
36+
# Install
37+
This extension is published in the VS Code Gallery. So simply hit 'F1' and type 'ext inst' from there select `SpellMD` and follow instructions.
38+
39+
40+
To clone the extension and load locally...
41+
42+
```
43+
git clone https://github.com/Microsoft/vscode-SpellMD.git
44+
npm install
45+
tsc
46+
```
47+
48+
>**Note:** TypeScript 1.6 or higher is required you can check with `tsc -v` and if you need to upgrade then run `npm install -g typescript`.

0 commit comments

Comments
 (0)