diff --git a/src/package.ts b/src/package.ts
index eeee356a..4ed19827 100644
--- a/src/package.ts
+++ b/src/package.ts
@@ -772,7 +772,7 @@ export class MarkdownProcessor extends BaseProcessor {
contents = contents.replace(markdownPathRegex, urlReplace);
// Replace links with urls
- contents = contents.replace(//g, (all, link) => {
+ contents = contents.replace(/]+src=["']([/.\w\s#-]+)['"][^>]*>/gm, (all, link) => {
const isLinkRelative = !/^\w+:\/\//.test(link) && link[0] !== '#';
if (!this.baseImagesUrl && isLinkRelative) {
@@ -840,7 +840,13 @@ export class MarkdownProcessor extends BaseProcessor {
}
const src = decodeURI(rawSrc);
- const srcUrl = new url.URL(src);
+ let srcUrl: url.URL
+
+ try {
+ srcUrl = new url.URL(src);
+ } catch (err) {
+ throw new Error(`Invalid image source in ${this.name}: ${src}`);
+ }
if (/^data:$/i.test(srcUrl.protocol) && /^image$/i.test(srcUrl.host) && /\/svg/i.test(srcUrl.pathname)) {
throw new Error(`SVG data URLs are not allowed in ${this.name}: ${src}`);
@@ -1273,7 +1279,13 @@ export function validateManifest(manifest: Manifest): Manifest {
(manifest.badges ?? []).forEach(badge => {
const decodedUrl = decodeURI(badge.url);
- const srcUrl = new url.URL(decodedUrl);
+ let srcUrl: url.URL;
+
+ try {
+ srcUrl = new url.URL(decodedUrl);
+ } catch (err) {
+ throw new Error(`Badge URL is invalid: ${badge.url}`);
+ }
if (!/^https:$/i.test(srcUrl.protocol)) {
throw new Error(`Badge URLs must come from an HTTPS source: ${badge.url}`);
diff --git a/src/test/package.test.ts b/src/test/package.test.ts
index 2dfddce2..e4c599b6 100644
--- a/src/test/package.test.ts
+++ b/src/test/package.test.ts
@@ -2896,6 +2896,22 @@ describe('MarkdownProcessor', () => {
await throws(() => processor.onFile(readme));
});
+ it('should allow img tags spanning across lines, issue #904', async () => {
+ const manifest = {
+ name: 'test',
+ publisher: 'mocha',
+ version: '0.0.1',
+ engines: Object.create(null),
+ repository: 'https://github.com/username/repository',
+ };
+ const contents = ``;
+ const processor = new ReadmeProcessor(manifest, {});
+ const readme = { path: 'extension/readme.md', contents };
+
+ const file = await processor.onFile(readme);
+ assert.ok(file);
+ });
+
it('should catch an unchanged README.md', async () => {
const manifest = {
name: 'test',