Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

vscode-html-languageservice

Package Overview
Dependencies
Maintainers
6
Versions
140
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vscode-html-languageservice - npm Package Compare versions

Comparing version 1.0.0-next.4 to 1.0.0-next.5

5

lib/htmlLanguageService.d.ts

@@ -19,2 +19,5 @@ import { TextDocument, Position, CompletionItem, CompletionList, Hover, Range, SymbolInformation, Diagnostic, TextEdit, DocumentHighlight, FormattingOptions, MarkedString, DocumentLink } from 'vscode-languageserver-types';

export declare type HTMLDocument = {};
export interface DocumentContext {
resolveReference(ref: string): string;
}
export interface LanguageService {

@@ -25,4 +28,4 @@ parseHTMLDocument(document: TextDocument): HTMLDocument;

format(document: TextDocument, range: Range, options: HTMLFormatConfiguration): TextEdit[];
findDocumentLinks(document: TextDocument, workspacePath: string): DocumentLink[];
findDocumentLinks(document: TextDocument, documentContext: DocumentContext): DocumentLink[];
}
export declare function getLanguageService(): LanguageService;

51

lib/services/htmlLinks.js

@@ -6,3 +6,3 @@ (function (factory) {

else if (typeof define === 'function' && define.amd) {
define(["require", "exports", '../parser/htmlScanner', 'vscode-languageserver-types', '../utils/paths', '../utils/strings', 'vscode-uri'], factory);
define(["require", "exports", '../parser/htmlScanner', 'vscode-languageserver-types', 'vscode-uri'], factory);
}

@@ -17,4 +17,2 @@ })(function (require, exports) {

var vscode_languageserver_types_1 = require('vscode-languageserver-types');
var paths = require('../utils/paths');
var strings = require('../utils/strings');
var vscode_uri_1 = require('vscode-uri');

@@ -26,11 +24,12 @@ function stripQuotes(url) {

}
function getWorkspaceUrl(modelAbsoluteUri, rootAbsoluteUrl, tokenContent) {
function getWorkspaceUrl(modelAbsoluteUri, tokenContent, documentContext) {
if (/^\s*javascript\:/i.test(tokenContent) || /^\s*\#/i.test(tokenContent)) {
return null;
}
if (/^\s*https?:\/\//i.test(tokenContent) || /^\s*file:\/\//i.test(tokenContent)) {
tokenContent = tokenContent.replace(/^\s*/g, '');
if (/^https?:\/\//i.test(tokenContent) || /^file:\/\//i.test(tokenContent)) {
// Absolute link that needs no treatment
return tokenContent.replace(/^\s*/g, '');
return tokenContent;
}
if (/^\s*\/\//i.test(tokenContent)) {
if (/^\/\//i.test(tokenContent)) {
// Absolute link (that does not name the protocol)

@@ -43,25 +42,8 @@ var pickedScheme = 'http';

}
var modelPath = paths.dirname(modelAbsoluteUri.path);
var alternativeResultPath = null;
if (tokenContent.length > 0 && tokenContent.charAt(0) === '/') {
alternativeResultPath = tokenContent;
if (documentContext) {
return documentContext.resolveReference(tokenContent);
}
else {
alternativeResultPath = paths.join(modelPath, tokenContent);
alternativeResultPath = alternativeResultPath.replace(/^(\/\.\.)+/, '');
}
var potentialResult = modelAbsoluteUri.with({ path: alternativeResultPath }).toString(true);
var rootAbsoluteUrlStr = rootAbsoluteUrl && rootAbsoluteUrl.toString(true);
if (rootAbsoluteUrlStr && strings.startsWith(modelAbsoluteUri.toString(true), rootAbsoluteUrlStr)) {
// The `rootAbsoluteUrl` is set and matches our current model
// We need to ensure that this `potentialResult` does not escape `rootAbsoluteUrl`
var commonPrefixLength = strings.commonPrefixLength(rootAbsoluteUrlStr, potentialResult);
if (strings.endsWith(rootAbsoluteUrlStr, '/')) {
commonPrefixLength = potentialResult.lastIndexOf('/', commonPrefixLength) + 1;
}
return rootAbsoluteUrlStr + potentialResult.substr(commonPrefixLength);
}
return potentialResult;
return tokenContent;
}
function createLink(document, rootAbsoluteUrl, attributeValue, startOffset, endOffset) {
function createLink(document, documentContext, attributeValue, startOffset, endOffset) {
var documentUri = vscode_uri_1.default.parse(document.uri);

@@ -73,3 +55,3 @@ var tokenContent = stripQuotes(attributeValue);

}
var workspaceUrl = getWorkspaceUrl(documentUri, rootAbsoluteUrl, tokenContent);
var workspaceUrl = getWorkspaceUrl(documentUri, tokenContent, documentContext);
if (!workspaceUrl) {

@@ -83,12 +65,5 @@ return null;

}
function findDocumentLinks(document, workspacePath) {
function findDocumentLinks(document, documentContext) {
var newLinks = [];
var rootAbsoluteUrl = null;
if (workspacePath) {
// The workspace can be null in the no folder opened case
if (workspacePath.charAt(workspacePath.length - 1) !== '/') {
workspacePath = workspacePath + '/';
}
rootAbsoluteUrl = vscode_uri_1.default.parse(workspacePath);
}
var scanner = htmlScanner_1.createScanner(document.getText(), 0);

@@ -106,3 +81,3 @@ var token = scanner.scan();

var attributeValue = scanner.getTokenText();
var link = createLink(document, rootAbsoluteUrl, attributeValue, scanner.getTokenOffset(), scanner.getTokenEnd());
var link = createLink(document, documentContext, attributeValue, scanner.getTokenOffset(), scanner.getTokenEnd());
if (link) {

@@ -109,0 +84,0 @@ newLinks.push(link);

@@ -6,3 +6,3 @@ (function (factory) {

else if (typeof define === 'function' && define.amd) {
define(["require", "exports", 'assert', 'vscode-languageserver-types', '../htmlLanguageService'], factory);
define(["require", "exports", 'assert', 'vscode-languageserver-types', '../htmlLanguageService', 'url'], factory);
}

@@ -18,7 +18,11 @@ })(function (require, exports) {

var htmlLanguageService = require('../htmlLanguageService');
var url = require('url');
suite('HTML Link Detection', function () {
function testLinkCreation(modelUrl, rootUrl, tokenContent, expected) {
function testLinkCreation(modelUrl, tokenContent, expected) {
var documentContext = {
resolveReference: function (ref) { return url.resolve(modelUrl, ref); }
};
var document = vscode_languageserver_types_1.TextDocument.create(modelUrl, 'html', 0, "<a href=\"" + tokenContent + "\">");
var ls = htmlLanguageService.getLanguageService();
var links = ls.findDocumentLinks(document, rootUrl);
var links = ls.findDocumentLinks(document, documentContext);
assert.equal(links[0] && links[0].target, expected);

@@ -28,49 +32,36 @@ }

var document = vscode_languageserver_types_1.TextDocument.create('test://test/test.html', 'html', 0, value);
var documentContext = {
resolveReference: function (ref) { return url.resolve(document.uri, ref); }
};
var ls = htmlLanguageService.getLanguageService();
var links = ls.findDocumentLinks(document, 'test://test');
var links = ls.findDocumentLinks(document, documentContext);
assert.deepEqual(links.map(function (l) { return l.range.start.character; }), expectedLinkLocations);
}
test('Link creation', function () {
testLinkCreation('inmemory://model/1', null, 'javascript:void;', null);
testLinkCreation('inmemory://model/1', null, ' \tjavascript:alert(7);', null);
testLinkCreation('inmemory://model/1', null, ' #relative', null);
testLinkCreation('inmemory://model/1', null, 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('inmemory://model/1', null, 'http://www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('inmemory://model/1', null, 'https://www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('inmemory://model/1', null, '//www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('inmemory://model/1', null, '../../a.js', 'inmemory://model/a.js');
testLinkCreation('inmemory://model/1', 'inmemory://model/', 'javascript:void;', null);
testLinkCreation('inmemory://model/1', 'inmemory://model/', ' \tjavascript:alert(7);', null);
testLinkCreation('inmemory://model/1', 'inmemory://model/', ' #relative', null);
testLinkCreation('inmemory://model/1', 'inmemory://model/', 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('inmemory://model/1', 'inmemory://model/', 'http://www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('inmemory://model/1', 'inmemory://model/', 'https://www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('inmemory://model/1', 'inmemory://model/', ' //www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('inmemory://model/1', 'inmemory://model/', '../../a.js', 'inmemory://model/a.js');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, 'javascript:void;', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, ' \tjavascript:alert(7);', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, ' #relative', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, 'http://www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, 'https://www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, ' //www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, 'a.js', 'file:///c:/Alex/src/path/to/a.js');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, '/a.js', 'file:///a.js');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', 'javascript:void;', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', ' \tjavascript:alert(7);', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', ' #relative', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', null, 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', 'http://www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', 'https://www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', 'https://www.microsoft.com/?q=1#h', 'https://www.microsoft.com/?q=1#h');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', ' //www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', 'a.js', 'file:///c:/Alex/src/path/to/a.js');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:/Alex/src/', '/a.js', 'file:///c:/Alex/src/a.js');
testLinkCreation('https://www.test.com/path/to/file.txt', null, 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('https://www.test.com/path/to/file.txt', null, '//www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('https://www.test.com/path/to/file.txt', 'https://www.test.com', '//www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('http://model/1', 'javascript:void;', null);
testLinkCreation('http://model/1', ' \tjavascript:alert(7);', null);
testLinkCreation('http://model/1', ' #relative', null);
testLinkCreation('http://model/1', 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('http://model/1', 'http://www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('http://model/1', 'https://www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('http://model/1', '//www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('http://model/x/1', 'a.js', 'http://model/x/a.js');
testLinkCreation('http://model/x/1', '/b.js', 'http://model/b.js');
testLinkCreation('http://model/x/y/1', '../../c.js', 'http://model/c.js');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'javascript:void;', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', ' \tjavascript:alert(7);', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', ' #relative', null);
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'http://www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'https://www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', ' //www.microsoft.com/', 'http://www.microsoft.com/');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', 'a.js', 'file:///C:/Alex/src/path/to/a.js');
testLinkCreation('file:///C:/Alex/src/path/to/file.txt', '/a.js', 'file:///a.js');
testLinkCreation('https://www.test.com/path/to/file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt', 'file:///C:\\Alex\\src\\path\\to\\file.txt');
testLinkCreation('https://www.test.com/path/to/file.txt', '//www.microsoft.com/', 'https://www.microsoft.com/');
testLinkCreation('https://www.test.com/path/to/file.txt', '//www.microsoft.com/', 'https://www.microsoft.com/');
// invalid uris don't throw
testLinkCreation('https://www.test.com/path/to/file.txt', 'https://www.test.com', '%', 'https://www.test.com/path/to/%');
testLinkCreation('https://www.test.com/path/to/file.txt', '%', 'https://www.test.com/path/to/%');
// Bug #18314: Ctrl + Click does not open existing file if folder's name starts with 'c' character
testLinkCreation('file:///c:/Alex/working_dir/18314-link-detection/test.html', 'file:///c:/Alex/working_dir/18314-link-detection/', '/class/class.js', 'file:///c:/Alex/working_dir/18314-link-detection/class/class.js');
testLinkCreation('file:///c:/Alex/working_dir/18314-link-detection/test.html', '/class/class.js', 'file:///class/class.js');
});

@@ -77,0 +68,0 @@ test('Link detection', function () {

{
"name": "vscode-html-languageservice",
"version": "1.0.0-next.4",
"version": "1.0.0-next.5",
"description": "Language service for HTML",

@@ -5,0 +5,0 @@ "main": "./lib/htmlLanguageService.js",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc