optimize mime.guessMimeTypes()

This commit is contained in:
Benjamin Pasero 2016-08-16 11:02:52 +02:00
parent a61944bc39
commit d699c077a6

View file

@ -22,9 +22,16 @@ export interface ITextMimeAssociation {
userConfigured?: boolean;
}
let registeredAssociations: ITextMimeAssociation[] = [];
let nonUserRegisteredAssociations: ITextMimeAssociation[] = [];
let userRegisteredAssociations: ITextMimeAssociation[] = [];
interface ITextMimeAssociationItem extends ITextMimeAssociation {
filenameLowercase?: string;
extensionLowercase?: string;
filepatternLowercase?: string;
filepatternOnPath?: boolean;
}
let registeredAssociations: ITextMimeAssociationItem[] = [];
let nonUserRegisteredAssociations: ITextMimeAssociationItem[] = [];
let userRegisteredAssociations: ITextMimeAssociationItem[] = [];
/**
* Associate a text mime to the registry.
@ -32,39 +39,55 @@ let userRegisteredAssociations: ITextMimeAssociation[] = [];
export function registerTextMime(association: ITextMimeAssociation): void {
// Register
registeredAssociations.push(association);
if (!association.userConfigured) {
nonUserRegisteredAssociations.push(association);
const associationItem = toTextMimeAssociationItem(association);
registeredAssociations.push(associationItem);
if (!associationItem.userConfigured) {
nonUserRegisteredAssociations.push(associationItem);
} else {
userRegisteredAssociations.push(association);
userRegisteredAssociations.push(associationItem);
}
// Check for conflicts unless this is a user configured association
if (!association.userConfigured) {
if (!associationItem.userConfigured) {
registeredAssociations.forEach(a => {
if (a.mime === association.mime || a.userConfigured) {
if (a.mime === associationItem.mime || a.userConfigured) {
return; // same mime or userConfigured is ok
}
if (association.extension && a.extension === association.extension) {
console.warn(`Overwriting extension <<${association.extension}>> to now point to mime <<${association.mime}>>`);
if (associationItem.extension && a.extension === associationItem.extension) {
console.warn(`Overwriting extension <<${associationItem.extension}>> to now point to mime <<${associationItem.mime}>>`);
}
if (association.filename && a.filename === association.filename) {
console.warn(`Overwriting filename <<${association.filename}>> to now point to mime <<${association.mime}>>`);
if (associationItem.filename && a.filename === associationItem.filename) {
console.warn(`Overwriting filename <<${associationItem.filename}>> to now point to mime <<${associationItem.mime}>>`);
}
if (association.filepattern && a.filepattern === association.filepattern) {
console.warn(`Overwriting filepattern <<${association.filepattern}>> to now point to mime <<${association.mime}>>`);
if (associationItem.filepattern && a.filepattern === associationItem.filepattern) {
console.warn(`Overwriting filepattern <<${associationItem.filepattern}>> to now point to mime <<${associationItem.mime}>>`);
}
if (association.firstline && a.firstline === association.firstline) {
console.warn(`Overwriting firstline <<${association.firstline}>> to now point to mime <<${association.mime}>>`);
if (associationItem.firstline && a.firstline === associationItem.firstline) {
console.warn(`Overwriting firstline <<${associationItem.firstline}>> to now point to mime <<${associationItem.mime}>>`);
}
});
}
}
function toTextMimeAssociationItem(association: ITextMimeAssociation): ITextMimeAssociationItem {
return {
mime: association.mime,
filename: association.filename,
extension: association.extension,
filepattern: association.filepattern,
firstline: association.firstline,
userConfigured: association.userConfigured,
filenameLowercase: association.filename ? association.filename.toLowerCase() : void 0,
extensionLowercase: association.extension ? association.extension.toLowerCase() : void 0,
filepatternLowercase: association.filepattern ? association.filepattern.toLowerCase() : void 0,
filepatternOnPath: association.filepattern ? association.filepattern.indexOf(paths.sep) >= 0 : false
};
}
/**
* Clear text mimes from the registry.
*/
@ -88,15 +111,16 @@ export function guessMimeTypes(path: string, firstLine?: string): string[] {
}
path = path.toLowerCase();
let filename = paths.basename(path);
// 1.) User configured mappings have highest priority
let configuredMime = guessMimeTypeByPath(path, userRegisteredAssociations);
let configuredMime = guessMimeTypeByPath(path, filename, userRegisteredAssociations);
if (configuredMime) {
return [configuredMime, MIME_TEXT];
}
// 2.) Registered mappings have middle priority
let registeredMime = guessMimeTypeByPath(path, nonUserRegisteredAssociations);
let registeredMime = guessMimeTypeByPath(path, filename, nonUserRegisteredAssociations);
if (registeredMime) {
return [registeredMime, MIME_TEXT];
}
@ -112,27 +136,25 @@ export function guessMimeTypes(path: string, firstLine?: string): string[] {
return [MIME_UNKNOWN];
}
function guessMimeTypeByPath(path: string, associations: ITextMimeAssociation[]): string {
let filename = paths.basename(path);
let filenameMatch: ITextMimeAssociation;
let patternMatch: ITextMimeAssociation;
let extensionMatch: ITextMimeAssociation;
function guessMimeTypeByPath(path: string, filename: string, associations: ITextMimeAssociationItem[]): string {
let filenameMatch: ITextMimeAssociationItem;
let patternMatch: ITextMimeAssociationItem;
let extensionMatch: ITextMimeAssociationItem;
for (var i = 0; i < associations.length; i++) {
let association = associations[i];
// First exact name match
if (association.filename && filename === association.filename.toLowerCase()) {
if (filename === association.filenameLowercase) {
filenameMatch = association;
break; // take it!
}
// Longest pattern match
if (association.filepattern) {
let target = association.filepattern.indexOf(paths.sep) >= 0 ? path : filename; // match on full path if pattern contains path separator
if (match(association.filepattern.toLowerCase(), target)) {
if (!patternMatch || association.filepattern.length > patternMatch.filepattern.length) {
if (!patternMatch || association.filepattern.length > patternMatch.filepattern.length) {
let target = association.filepatternOnPath ? path : filename; // match on full path if pattern contains path separator
if (match(association.filepatternLowercase, target)) {
patternMatch = association;
}
}
@ -140,8 +162,8 @@ function guessMimeTypeByPath(path: string, associations: ITextMimeAssociation[])
// Longest extension match
if (association.extension) {
if (strings.endsWith(filename, association.extension.toLowerCase())) {
if (!extensionMatch || association.extension.length > extensionMatch.extension.length) {
if (!extensionMatch || association.extension.length > extensionMatch.extension.length) {
if (strings.endsWith(filename, association.extensionLowercase)) {
extensionMatch = association;
}
}