Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
掘金者说
vscode
提交
27870487
V
vscode
项目概览
掘金者说
/
vscode
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vscode
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
27870487
编写于
3月 04, 2016
作者:
B
Benjamin Pasero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
user configured mimes get highest priority
上级
932e8637
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
121 addition
and
131 deletion
+121
-131
src/vs/base/common/mime.ts
src/vs/base/common/mime.ts
+87
-108
src/vs/base/test/common/mime.test.ts
src/vs/base/test/common/mime.test.ts
+28
-16
src/vs/base/test/node/mime/mime.test.ts
src/vs/base/test/node/mime/mime.test.ts
+1
-2
src/vs/editor/common/services/languagesRegistry.ts
src/vs/editor/common/services/languagesRegistry.ts
+4
-4
src/vs/workbench/parts/files/common/editors/fileAssociations.ts
.../workbench/parts/files/common/editors/fileAssociations.ts
+1
-1
未找到文件。
src/vs/base/common/mime.ts
浏览文件 @
27870487
...
...
@@ -13,140 +13,83 @@ export let MIME_TEXT = 'text/plain';
export
let
MIME_BINARY
=
'
application/octet-stream
'
;
export
let
MIME_UNKNOWN
=
'
application/unknown
'
;
export
interface
ITextMimeAssociation
{
pattern
?:
string
;
firstLineRegExp
?:
RegExp
;
userConfigured
?:
boolean
;
}
const
registeredTextMimesByFilename
:
{
[
str
:
string
]:
string
;
}
=
Object
.
create
(
null
);
const
userConfiguredTextMimesByFilename
:
{
[
str
:
string
]:
string
;
}
=
Object
.
create
(
null
);
const
registeredTextMimesByFirstLine
:
{
regexp
:
RegExp
;
mime
:
string
;
}[]
=
[];
// This is for automatic generation at native.guplfile.js#41 => darwinBundleDocumentTypes.extensions
export
function
generateKnownFilenames
(
onlyExtensions
:
boolean
=
true
):
any
{
let
filter
=
(
ext
:
string
)
=>
{
if
(
onlyExtensions
)
{
return
/^
\.
/
.
test
(
ext
);
}
return
true
;
};
let
removeLeadingDot
=
(
ext
:
string
)
=>
{
return
ext
.
replace
(
/^
\.
/
,
''
);
};
let
list
:
string
[]
=
[];
list
=
list
.
concat
(
Object
.
keys
(
registeredTextMimesByFilename
));
list
=
list
.
filter
(
filter
).
map
(
removeLeadingDot
);
list
.
sort
();
let
result
:
string
[]
=
[];
let
currentLetter
:
string
=
null
;
let
previousItem
:
string
=
null
;
let
currentRow
:
string
[]
=
[];
let
pushCurrentRow
=
()
=>
{
if
(
currentRow
.
length
>
0
)
{
result
.
push
(
'
\'
'
+
currentRow
.
join
(
'
\'
,
\'
'
)
+
'
\'
'
);
}
};
/**
* Associate a text mime to the registry
*/
export
function
registerTextMime
(
mime
:
string
,
association
:
ITextMimeAssociation
):
void
{
if
(
mime
&&
association
)
{
for
(
let
i
=
0
,
len
=
list
.
length
;
i
<
len
;
i
++
)
{
let
item
=
list
[
i
];
if
(
item
.
length
===
0
)
{
continue
;
// Firstline pattern
if
(
association
.
firstLineRegExp
)
{
registeredTextMimesByFirstLine
.
push
({
regexp
:
association
.
firstLineRegExp
,
mime
:
mime
});
}
if
(
item
===
previousItem
)
{
continue
;
}
let
letter
=
item
.
charAt
(
0
);
if
(
currentLetter
!==
letter
)
{
pushCurrentRow
();
currentLetter
=
letter
;
currentRow
=
[];
// User configured
if
(
association
.
userConfigured
&&
association
.
pattern
)
{
userConfiguredTextMimesByFilename
[
association
.
pattern
]
=
mime
;
}
currentRow
.
push
(
item
);
previousItem
=
item
;
}
pushCurrentRow
();
return
result
.
join
(
'
,
\n
'
);
}
/**
* Allow to register extra text mimes dynamically based on filename
*/
export
function
registerTextMimeByFilename
(
nameOrPatternOrPrefix
:
string
,
mime
:
string
):
void
{
if
(
nameOrPatternOrPrefix
&&
mime
)
{
if
(
registeredTextMimesByFilename
[
nameOrPatternOrPrefix
]
&&
registeredTextMimesByFilename
[
nameOrPatternOrPrefix
]
!==
mime
)
{
console
.
warn
(
'
Overwriting filename <<
'
+
nameOrPatternOrPrefix
+
'
>> to now point to mime <<
'
+
mime
+
'
>>
'
);
// Built in or via Extension
else
if
(
association
.
pattern
)
{
if
(
registeredTextMimesByFilename
[
association
.
pattern
]
&&
registeredTextMimesByFilename
[
association
.
pattern
]
!==
mime
)
{
console
.
warn
(
'
Overwriting filename <<
'
+
association
.
pattern
+
'
>> to now point to mime <<
'
+
mime
+
'
>>
'
);
}
registeredTextMimesByFilename
[
association
.
pattern
]
=
mime
;
}
registeredTextMimesByFilename
[
nameOrPatternOrPrefix
]
=
mime
;
}
}
/**
* Allow to register extra text mimes dynamically based on firstline
*/
export
function
registerTextMimeByFirstLine
(
firstLineRegexp
:
RegExp
,
mime
:
string
):
void
{
if
(
firstLineRegexp
&&
mime
)
{
registeredTextMimesByFirstLine
.
push
({
regexp
:
firstLineRegexp
,
mime
:
mime
});
}
}
/**
* Given a comma separated list of mimes in order of priority, find if the list describes a binary
* or textual resource.
*/
export
function
isBinaryMime
(
mimes
:
string
):
boolean
;
export
function
isBinaryMime
(
mimes
:
string
[]):
boolean
;
export
function
isBinaryMime
(
mimes
:
any
):
boolean
{
if
(
!
mimes
)
{
return
false
;
}
let
mimeVals
:
string
[];
if
(
types
.
isArray
(
mimes
))
{
mimeVals
=
(
<
string
[]
>
mimes
);
}
else
{
mimeVals
=
(
<
string
>
mimes
).
split
(
'
,
'
).
map
((
mime
)
=>
mime
.
trim
());
}
return
mimeVals
.
indexOf
(
MIME_BINARY
)
>=
0
;
}
/**
* New function for mime type detection supporting application/unknown as concept.
* Given a file, return the best matching mime type for it
*/
export
function
guessMimeTypes
(
path
:
string
,
firstLine
?:
string
):
string
[]
{
if
(
!
path
)
{
return
[
MIME_UNKNOWN
];
}
// 1.) Firstline gets highest priority
if
(
firstLine
)
{
if
(
strings
.
startsWithUTF8BOM
(
firstLine
))
{
firstLine
=
firstLine
.
substr
(
1
);
}
path
=
path
.
toLowerCase
();
let
filename
=
paths
.
basename
(
path
);
if
(
firstLine
.
length
>
0
)
{
for
(
let
i
=
0
;
i
<
registeredTextMimesByFirstLine
.
length
;
++
i
)
{
// 1.) Configured mappings have highest priority
let
configuredMime
=
guessMimeTypeByFilename
(
filename
,
userConfiguredTextMimesByFilename
);
if
(
configuredMime
)
{
return
[
configuredMime
,
MIME_TEXT
];
}
// Make sure the entire line matches, not just a subpart.
let
matches
=
firstLine
.
match
(
registeredTextMimesByFirstLine
[
i
].
regexp
);
if
(
matches
&&
matches
.
length
>
0
&&
matches
[
0
].
length
===
firstLine
.
length
)
{
return
[
registeredTextMimesByFirstLine
[
i
].
mime
,
MIME_TEXT
];
}
}
// 2.) Firstline has high priority over registered mappings
if
(
firstLine
)
{
let
firstlineMime
=
guessMimeTypeByFirstline
(
firstLine
);
if
(
firstlineMime
)
{
return
[
firstlineMime
,
MIME_TEXT
];
}
}
// Check with file name and extension
path
=
path
.
toLowerCase
();
let
filename
=
paths
.
basename
(
path
);
// 3.) Registered mappings have lowest priority
let
registeredMime
=
guessMimeTypeByFilename
(
filename
,
registeredTextMimesByFilename
);
if
(
registeredMime
)
{
return
[
registeredMime
,
MIME_TEXT
];
}
return
[
MIME_UNKNOWN
];
}
function
guessMimeTypeByFilename
(
filename
:
string
,
map
:
{
[
str
:
string
]:
string
;
}):
string
{
let
exactNameMatch
:
string
;
let
extensionMatch
:
string
;
let
patternNameMatch
:
string
;
// Check for dynamically registered match based on filename and extension
for
(
let
nameOrPatternOrPrefix
in
registeredTextMimesByFilename
)
{
for
(
let
nameOrPatternOrPrefix
in
map
)
{
let
nameOrPatternOrExtensionLower
:
string
=
nameOrPatternOrPrefix
.
toLowerCase
();
// First exact name match
...
...
@@ -172,20 +115,56 @@ export function guessMimeTypes(path: string, firstLine?: string): string[] {
// 2.) Exact name match has second highest prio
if
(
exactNameMatch
)
{
return
[
registeredTextMimesByFilename
[
exactNameMatch
],
MIME_TEXT
];
return
map
[
exactNameMatch
];
}
// 3.) Match on pattern
if
(
patternNameMatch
)
{
return
[
registeredTextMimesByFilename
[
patternNameMatch
],
MIME_TEXT
];
return
map
[
patternNameMatch
];
}
// 4.) Match on extension comes next
if
(
extensionMatch
)
{
return
[
registeredTextMimesByFilename
[
extensionMatch
],
MIME_TEXT
];
return
map
[
extensionMatch
];
}
return
[
MIME_UNKNOWN
];
return
null
;
}
function
guessMimeTypeByFirstline
(
firstLine
:
string
):
string
{
if
(
strings
.
startsWithUTF8BOM
(
firstLine
))
{
firstLine
=
firstLine
.
substr
(
1
);
}
if
(
firstLine
.
length
>
0
)
{
for
(
let
i
=
0
;
i
<
registeredTextMimesByFirstLine
.
length
;
++
i
)
{
// Make sure the entire line matches, not just a subpart.
let
matches
=
firstLine
.
match
(
registeredTextMimesByFirstLine
[
i
].
regexp
);
if
(
matches
&&
matches
.
length
>
0
&&
matches
[
0
].
length
===
firstLine
.
length
)
{
return
registeredTextMimesByFirstLine
[
i
].
mime
;
}
}
}
return
null
;
}
export
function
isBinaryMime
(
mimes
:
string
):
boolean
;
export
function
isBinaryMime
(
mimes
:
string
[]):
boolean
;
export
function
isBinaryMime
(
mimes
:
any
):
boolean
{
if
(
!
mimes
)
{
return
false
;
}
let
mimeVals
:
string
[];
if
(
types
.
isArray
(
mimes
))
{
mimeVals
=
(
<
string
[]
>
mimes
);
}
else
{
mimeVals
=
(
<
string
>
mimes
).
split
(
'
,
'
).
map
((
mime
)
=>
mime
.
trim
());
}
return
mimeVals
.
indexOf
(
MIME_BINARY
)
>=
0
;
}
export
function
isUnspecific
(
mime
:
string
[]
|
string
):
boolean
{
...
...
src/vs/base/test/common/mime.test.ts
浏览文件 @
27870487
...
...
@@ -5,35 +5,39 @@
'
use strict
'
;
import
*
as
assert
from
'
assert
'
;
import
{
guessMimeTypes
,
registerTextMimeByFilename
,
registerTextMimeByFirstLine
}
from
'
vs/base/common/mime
'
;
import
{
guessMimeTypes
,
registerTextMime
}
from
'
vs/base/common/mime
'
;
function
register
(
pattern
:
string
,
mime
:
string
,
user
?:
boolean
):
void
{
registerTextMime
(
mime
,
{
pattern
:
pattern
,
userConfigured
:
user
});
}
suite
(
'
Mime
'
,
()
=>
{
test
(
'
Dynamically Register Text Mime
'
,
()
=>
{
var
guess
=
guessMimeTypes
(
'
foo.monaco
'
);
assert
.
deepEqual
(
guess
,
[
'
application/unknown
'
]);
register
TextMimeByFilename
(
'
.monaco
'
,
'
text/monaco
'
);
register
(
'
.monaco
'
,
'
text/monaco
'
);
guess
=
guessMimeTypes
(
'
foo.monaco
'
);
assert
.
deepEqual
(
guess
,
[
'
text/monaco
'
,
'
text/plain
'
]);
guess
=
guessMimeTypes
(
'
.monaco
'
);
assert
.
deepEqual
(
guess
,
[
'
text/monaco
'
,
'
text/plain
'
]);
register
TextMimeByFilename
(
'
Codefile
'
,
'
text/code
'
);
register
(
'
Codefile
'
,
'
text/code
'
);
guess
=
guessMimeTypes
(
'
Codefile
'
);
assert
.
deepEqual
(
guess
,
[
'
text/code
'
,
'
text/plain
'
]);
guess
=
guessMimeTypes
(
'
foo.Codefile
'
);
assert
.
deepEqual
(
guess
,
[
'
application/unknown
'
]);
register
TextMimeByFilename
(
'
Docker*
'
,
'
text/docker
'
);
register
(
'
Docker*
'
,
'
text/docker
'
);
guess
=
guessMimeTypes
(
'
Docker-debug
'
);
assert
.
deepEqual
(
guess
,
[
'
text/docker
'
,
'
text/plain
'
]);
guess
=
guessMimeTypes
(
'
docker-PROD
'
);
assert
.
deepEqual
(
guess
,
[
'
text/docker
'
,
'
text/plain
'
]);
registerTextMime
ByFirstLine
(
/RegexesAreNice/
,
'
text/nice-regex
'
);
registerTextMime
(
'
text/nice-regex
'
,
{
firstLineRegExp
:
/RegexesAreNice/
}
);
guess
=
guessMimeTypes
(
'
Randomfile.noregistration
'
,
'
RegexesAreNice
'
);
assert
.
deepEqual
(
guess
,
[
'
text/nice-regex
'
,
'
text/plain
'
]);
...
...
@@ -45,8 +49,8 @@ suite('Mime', () => {
});
test
(
'
Mimes Priority
'
,
()
=>
{
register
TextMimeByFilename
(
'
.monaco
'
,
'
text/monaco
'
);
registerTextMime
ByFirstLine
(
/foobar/
,
'
text/foobar
'
);
register
(
'
.monaco
'
,
'
text/monaco
'
);
registerTextMime
(
'
text/foobar
'
,
{
firstLineRegExp
:
/foobar/
}
);
var
guess
=
guessMimeTypes
(
'
foo.monaco
'
);
assert
.
deepEqual
(
guess
,
[
'
text/monaco
'
,
'
text/plain
'
]);
...
...
@@ -54,32 +58,32 @@ suite('Mime', () => {
guess
=
guessMimeTypes
(
'
foo.monaco
'
,
'
foobar
'
);
assert
.
deepEqual
(
guess
,
[
'
text/foobar
'
,
'
text/plain
'
]);
register
TextMimeByFilename
(
'
dockerfile
'
,
'
text/winner
'
);
register
TextMimeByFilename
(
'
dockerfile*
'
,
'
text/looser
'
);
register
(
'
dockerfile
'
,
'
text/winner
'
);
register
(
'
dockerfile*
'
,
'
text/looser
'
);
guess
=
guessMimeTypes
(
'
dockerfile
'
);
assert
.
deepEqual
(
guess
,
[
'
text/winner
'
,
'
text/plain
'
]);
});
test
(
'
Specificity priority 1
'
,
()
=>
{
register
TextMimeByFilename
(
'
.monaco2
'
,
'
text/monaco2
'
);
register
TextMimeByFilename
(
'
specific.monaco2
'
,
'
text/specific-monaco2
'
);
register
(
'
.monaco2
'
,
'
text/monaco2
'
);
register
(
'
specific.monaco2
'
,
'
text/specific-monaco2
'
);
assert
.
deepEqual
(
guessMimeTypes
(
'
specific.monaco2
'
),
[
'
text/specific-monaco2
'
,
'
text/plain
'
]);
assert
.
deepEqual
(
guessMimeTypes
(
'
foo.monaco2
'
),
[
'
text/monaco2
'
,
'
text/plain
'
]);
});
test
(
'
Specificity priority 2
'
,
()
=>
{
register
TextMimeByFilename
(
'
specific.monaco3
'
,
'
text/specific-monaco3
'
);
register
TextMimeByFilename
(
'
.monaco3
'
,
'
text/monaco3
'
);
register
(
'
specific.monaco3
'
,
'
text/specific-monaco3
'
);
register
(
'
.monaco3
'
,
'
text/monaco3
'
);
assert
.
deepEqual
(
guessMimeTypes
(
'
specific.monaco3
'
),
[
'
text/specific-monaco3
'
,
'
text/plain
'
]);
assert
.
deepEqual
(
guessMimeTypes
(
'
foo.monaco3
'
),
[
'
text/monaco3
'
,
'
text/plain
'
]);
});
test
(
'
Mimes Priority - Longest Extension wins
'
,
()
=>
{
register
TextMimeByFilename
(
'
.monaco
'
,
'
text/monaco
'
);
register
TextMimeByFilename
(
'
.monaco.xml
'
,
'
text/monaco-xml
'
);
register
TextMimeByFilename
(
'
.monaco.xml.build
'
,
'
text/monaco-xml-build
'
);
register
(
'
.monaco
'
,
'
text/monaco
'
);
register
(
'
.monaco.xml
'
,
'
text/monaco-xml
'
);
register
(
'
.monaco.xml.build
'
,
'
text/monaco-xml-build
'
);
var
guess
=
guessMimeTypes
(
'
foo.monaco
'
);
assert
.
deepEqual
(
guess
,
[
'
text/monaco
'
,
'
text/plain
'
]);
...
...
@@ -90,4 +94,12 @@ suite('Mime', () => {
guess
=
guessMimeTypes
(
'
foo.monaco.xml.build
'
);
assert
.
deepEqual
(
guess
,
[
'
text/monaco-xml-build
'
,
'
text/plain
'
]);
});
test
(
'
Mimes Priority - User configured wins
'
,
()
=>
{
register
(
'
.monaco.xml
'
,
'
text/monaco
'
,
true
);
register
(
'
.monaco.xml
'
,
'
text/monaco-xml
'
);
var
guess
=
guessMimeTypes
(
'
foo.monaco.xml
'
);
assert
.
deepEqual
(
guess
,
[
'
text/monaco
'
,
'
text/plain
'
]);
});
});
src/vs/base/test/node/mime/mime.test.ts
浏览文件 @
27870487
...
...
@@ -6,7 +6,6 @@
'
use strict
'
;
import
assert
=
require
(
'
assert
'
);
import
path
=
require
(
'
path
'
);
import
mimeCommon
=
require
(
'
vs/base/common/mime
'
);
import
mime
=
require
(
'
vs/base/node/mime
'
);
...
...
@@ -24,7 +23,7 @@ suite('Mime', () => {
});
test
(
'
detectMimesFromFile (PNG saved as TXT)
'
,
function
(
done
:
()
=>
void
)
{
mimeCommon
.
registerTextMime
ByFilename
(
'
.txt
'
,
'
text/plain
'
);
mimeCommon
.
registerTextMime
(
'
text/plain
'
,
{
pattern
:
'
.txt
'
}
);
var
file
=
require
.
toUrl
(
'
./fixtures/some.png.txt
'
);
mime
.
detectMimesFromFile
(
file
,
(
error
,
mimes
)
=>
{
assert
.
equal
(
error
,
null
);
...
...
src/vs/editor/common/services/languagesRegistry.ts
浏览文件 @
27870487
...
...
@@ -103,19 +103,19 @@ export class LanguagesRegistry {
if
(
Array
.
isArray
(
lang
.
extensions
))
{
for
(
let
extension
of
lang
.
extensions
)
{
mime
.
registerTextMime
ByFilename
(
extension
,
primaryMime
);
mime
.
registerTextMime
(
primaryMime
,
{
pattern
:
extension
}
);
}
}
if
(
Array
.
isArray
(
lang
.
filenames
))
{
for
(
let
filename
of
lang
.
filenames
)
{
mime
.
registerTextMime
ByFilename
(
filename
,
primaryMime
);
mime
.
registerTextMime
(
primaryMime
,
{
pattern
:
filename
}
);
}
}
if
(
Array
.
isArray
(
lang
.
filenamePatterns
))
{
for
(
let
filenamePattern
of
lang
.
filenamePatterns
)
{
mime
.
registerTextMime
ByFilename
(
filenamePattern
,
primaryMime
);
mime
.
registerTextMime
(
primaryMime
,
{
pattern
:
filenamePattern
}
);
}
}
...
...
@@ -127,7 +127,7 @@ export class LanguagesRegistry {
try
{
var
firstLineRegex
=
new
RegExp
(
firstLineRegexStr
);
if
(
!
strings
.
regExpLeadsToEndlessLoop
(
firstLineRegex
))
{
mime
.
registerTextMime
ByFirstLine
(
firstLineRegex
,
primaryMime
);
mime
.
registerTextMime
(
primaryMime
,
{
firstLineRegExp
:
firstLineRegex
}
);
}
}
catch
(
err
)
{
// Most likely, the regex was bad
...
...
src/vs/workbench/parts/files/common/editors/fileAssociations.ts
浏览文件 @
27870487
...
...
@@ -41,7 +41,7 @@ export class FileAssociations implements IWorkbenchContribution {
private
onConfigurationChange
(
configuration
:
IFilesConfiguration
):
void
{
if
(
configuration
.
files
&&
configuration
.
files
.
associations
)
{
Object
.
keys
(
configuration
.
files
.
associations
).
forEach
(
pattern
=>
{
mime
.
registerTextMime
ByFilename
(
pattern
,
this
.
modeService
.
getMimeForMode
(
configuration
.
files
.
associations
[
pattern
])
);
mime
.
registerTextMime
(
this
.
modeService
.
getMimeForMode
(
configuration
.
files
.
associations
[
pattern
]),
{
pattern
:
pattern
,
userConfigured
:
true
}
);
});
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录