You've already forked StringFilr
mirror of
https://github.com/FullScreenShenanigans/StringFilr.git
synced 2026-04-28 13:00:51 -07:00
Merge pull request #3 from FullScreenShenanigans/module-exports
Module exports
This commit is contained in:
+15
-1
@@ -21,11 +21,17 @@ module.exports = function (grunt) {
|
||||
"dest": "<%= meta.paths.source %>/<%= pkg.name %>.js"
|
||||
}
|
||||
},
|
||||
"clean": ["<%= meta.paths.dist %>"],
|
||||
"copy": {
|
||||
"default": {
|
||||
"files": [{
|
||||
"src": "<%= meta.paths.source %>/<%= pkg.name %>.ts",
|
||||
"dest": "<%= meta.paths.dist %>/<%= pkg.name %>-<%= pkg.version %>.ts"
|
||||
}, {
|
||||
"src": "<%= meta.paths.source %>/References/*.ts",
|
||||
"dest": "<%= meta.paths.dist %>/",
|
||||
"expand": true,
|
||||
"flatten": true
|
||||
}, {
|
||||
"src": "README.md",
|
||||
"dest": "<%= meta.paths.dist %>/"
|
||||
@@ -51,17 +57,25 @@ module.exports = function (grunt) {
|
||||
}
|
||||
}
|
||||
},
|
||||
"preprocess": {
|
||||
"dist": {
|
||||
"src": "<%= meta.paths.dist %>/<%= pkg.name %>-<%= pkg.version %>.ts",
|
||||
"dest": "<%= meta.paths.dist %>/<%= pkg.name %>-<%= pkg.version %>.ts"
|
||||
}
|
||||
},
|
||||
"mocha_phantomjs": {
|
||||
"all": ["Tests/*.html"]
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks("grunt-contrib-clean");
|
||||
grunt.loadNpmTasks("grunt-contrib-copy");
|
||||
grunt.loadNpmTasks("grunt-contrib-uglify");
|
||||
grunt.loadNpmTasks("grunt-mocha-phantomjs");
|
||||
grunt.loadNpmTasks("grunt-preprocess");
|
||||
grunt.loadNpmTasks("grunt-tslint");
|
||||
grunt.loadNpmTasks("grunt-typescript");
|
||||
grunt.registerTask("default", [
|
||||
"tslint", "typescript", "copy", "uglify", "mocha_phantomjs"
|
||||
"tslint", "typescript", "clean", "copy", "uglify", "preprocess", "mocha_phantomjs"
|
||||
]);
|
||||
};
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
declare module StringFilr {
|
||||
export interface IStringFilrSettings {
|
||||
/**
|
||||
* An Object containing data stored as children of sub-Objects.
|
||||
*/
|
||||
library: any;
|
||||
|
||||
/**
|
||||
* A String to use as a default key to rescue on, if provided.
|
||||
*/
|
||||
normal?: string;
|
||||
|
||||
/**
|
||||
* Whether it's ok for the library to have Objects that don't contain the
|
||||
* normal key (by default, false).
|
||||
*/
|
||||
requireNormalKey?: boolean;
|
||||
}
|
||||
|
||||
export interface IStringFilr {
|
||||
getLibrary(): any;
|
||||
getNormal(): string;
|
||||
getCache(): any;
|
||||
getCached(key: string): any;
|
||||
clearCache(): void;
|
||||
clearCached(key: string): void;
|
||||
get(keyRaw: string): any;
|
||||
}
|
||||
}
|
||||
+178
-181
@@ -1,219 +1,216 @@
|
||||
interface IStringFilrSettings {
|
||||
// An Object containing data stored as children of sub-Objects.
|
||||
library: any;
|
||||
// @ifdef INCLUDE_DEFINITIONS
|
||||
/// <reference path="StringFilr.d.ts" />
|
||||
// @endif
|
||||
|
||||
// A String to use as a default key to rescue on, if provided.
|
||||
normal?: string;
|
||||
// @include ../Source/StringFilr.d.ts
|
||||
|
||||
// Whether it's ok for the library to have Objects that don't contain the
|
||||
// normal key (by default, false).
|
||||
requireNormalKey?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* A general utility for retrieving data from an Object based on nested class
|
||||
* names. You can think of the internal "library" Object as a tree structure,
|
||||
* such that you can pass in a listing (in any order) of the path to data for
|
||||
* retrieval.
|
||||
*
|
||||
* @author "Josh Goldberg" <josh@fullscreenmario.com>
|
||||
*/
|
||||
class StringFilr {
|
||||
// The library of data.
|
||||
private library: any;
|
||||
|
||||
// Listing of previously found lookups, for speed's sake.
|
||||
private cache: any;
|
||||
|
||||
// Optional default class to use when no suitable option is found.
|
||||
private normal: string;
|
||||
|
||||
// Whether to crash when a sub-object in reset has no normal child.
|
||||
private requireNormalKey: boolean;
|
||||
module StringFilr {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Resets the StringFilr.
|
||||
*
|
||||
* @constructor
|
||||
* @param {IStringFilrSettings} settings
|
||||
* A general utility for retrieving data from an Object based on nested class
|
||||
* names. You can think of the internal "library" Object as a tree structure,
|
||||
* such that you can pass in a listing (in any order) of the path to data for
|
||||
* retrieval.
|
||||
*/
|
||||
constructor(settings: IStringFilrSettings) {
|
||||
if (!settings) {
|
||||
throw new Error("No settings given to StringFilr.");
|
||||
}
|
||||
export class StringFilr implements IStringFilr {
|
||||
// The library of data.
|
||||
private library: any;
|
||||
|
||||
if (!settings.library) {
|
||||
throw new Error("No library given to StringFilr.");
|
||||
}
|
||||
this.library = settings.library;
|
||||
// Listing of previously found lookups, for speed's sake.
|
||||
private cache: any;
|
||||
|
||||
this.normal = settings.normal;
|
||||
this.requireNormalKey = settings.requireNormalKey;
|
||||
// Optional default class to use when no suitable option is found.
|
||||
private normal: string;
|
||||
|
||||
this.cache = {};
|
||||
// Whether to crash when a sub-object in reset has no normal child.
|
||||
private requireNormalKey: boolean;
|
||||
|
||||
if (this.requireNormalKey) {
|
||||
if (typeof this.normal === "undefined") {
|
||||
throw new Error("StringFilr is given requireNormalKey, but no normal class.");
|
||||
/**
|
||||
* @param {IStringFilrSettings} settings
|
||||
*/
|
||||
constructor(settings: IStringFilrSettings) {
|
||||
if (!settings) {
|
||||
throw new Error("No settings given to StringFilr.");
|
||||
}
|
||||
|
||||
this.ensureLibraryNormal();
|
||||
}
|
||||
}
|
||||
if (!settings.library) {
|
||||
throw new Error("No library given to StringFilr.");
|
||||
}
|
||||
this.library = settings.library;
|
||||
|
||||
/**
|
||||
* @return {Object} The base library of stored information.
|
||||
*/
|
||||
getLibrary(): any {
|
||||
return this.library;
|
||||
}
|
||||
this.normal = settings.normal;
|
||||
this.requireNormalKey = settings.requireNormalKey;
|
||||
|
||||
/**
|
||||
* @return {String} The optional normal class String.
|
||||
*/
|
||||
getNormal(): string {
|
||||
return this.normal;
|
||||
}
|
||||
this.cache = {};
|
||||
|
||||
/**
|
||||
* @return {Object} The complete cache of cached output.
|
||||
*/
|
||||
getCache(): any {
|
||||
return this.cache;
|
||||
}
|
||||
if (this.requireNormalKey) {
|
||||
if (typeof this.normal === "undefined") {
|
||||
throw new Error("StringFilr is given requireNormalKey, but no normal class.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Mixed} A cached value, if it exists/
|
||||
*/
|
||||
getCached(key: string): any {
|
||||
return this.cache[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely clears the cache Object.
|
||||
*/
|
||||
clearCache(): void {
|
||||
this.cache = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cached entry for a key.
|
||||
*
|
||||
* @param {String} key
|
||||
*/
|
||||
clearCached(key: string): void {
|
||||
if (this.normal) {
|
||||
key = key.replace(this.normal, "");
|
||||
this.ensureLibraryNormal();
|
||||
}
|
||||
}
|
||||
|
||||
delete this.cache[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the deepest matching data in the library for a key.
|
||||
*
|
||||
* @param {String} keyRaw
|
||||
* @return {Mixed}
|
||||
*/
|
||||
get(keyRaw: string): any {
|
||||
var key: string,
|
||||
result: any;
|
||||
|
||||
if (this.normal) {
|
||||
key = keyRaw.replace(this.normal, "");
|
||||
} else {
|
||||
key = keyRaw;
|
||||
/**
|
||||
* @return {Object} The base library of stored information.
|
||||
*/
|
||||
getLibrary(): any {
|
||||
return this.library;
|
||||
}
|
||||
|
||||
// Quickly return a cached result if it exists
|
||||
if (this.cache.hasOwnProperty(key)) {
|
||||
/**
|
||||
* @return {String} The optional normal class String.
|
||||
*/
|
||||
getNormal(): string {
|
||||
return this.normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Object} The complete cache of cached output.
|
||||
*/
|
||||
getCache(): any {
|
||||
return this.cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Mixed} A cached value, if it exists/
|
||||
*/
|
||||
getCached(key: string): any {
|
||||
return this.cache[key];
|
||||
}
|
||||
|
||||
// Since no existed, it must be found deep within the library
|
||||
result = this.followClass(key.split(/\s+/g), this.library);
|
||||
|
||||
this.cache[key] = this.cache[keyRaw] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility helper to recursively check for tree branches in the library
|
||||
* that don't have a key equal to the normal. For each sub-directory that
|
||||
* is caught, the path to it is added to output.
|
||||
*
|
||||
* @param {Object} current The current location being searched within
|
||||
* the library.
|
||||
* @param {String} path The current path within the library.
|
||||
* @param {String[]} output An Array of the String paths to parts that
|
||||
* don't have a matching key.
|
||||
* @return {String[]} output
|
||||
*/
|
||||
findLackingNormal(current: any, path: string, output: string[]): string[] {
|
||||
var i: string;
|
||||
|
||||
if (!current.hasOwnProperty(this.normal)) {
|
||||
output.push(path);
|
||||
/**
|
||||
* Completely clears the cache Object.
|
||||
*/
|
||||
clearCache(): void {
|
||||
this.cache = {};
|
||||
}
|
||||
|
||||
if (typeof current[i] === "object") {
|
||||
for (i in current) {
|
||||
if (current.hasOwnProperty(i)) {
|
||||
this.findLackingNormal(current[i], path + " " + i, output);
|
||||
/**
|
||||
* Clears the cached entry for a key.
|
||||
*
|
||||
* @param {String} key
|
||||
*/
|
||||
clearCached(key: string): void {
|
||||
if (this.normal) {
|
||||
key = key.replace(this.normal, "");
|
||||
}
|
||||
|
||||
delete this.cache[key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the deepest matching data in the library for a key.
|
||||
*
|
||||
* @param {String} keyRaw
|
||||
* @return {Mixed}
|
||||
*/
|
||||
get(keyRaw: string): any {
|
||||
var key: string,
|
||||
result: any;
|
||||
|
||||
if (this.normal) {
|
||||
key = keyRaw.replace(this.normal, "");
|
||||
} else {
|
||||
key = keyRaw;
|
||||
}
|
||||
|
||||
// Quickly return a cached result if it exists
|
||||
if (this.cache.hasOwnProperty(key)) {
|
||||
return this.cache[key];
|
||||
}
|
||||
|
||||
// Since no existed, it must be found deep within the library
|
||||
result = this.followClass(key.split(/\s+/g), this.library);
|
||||
|
||||
this.cache[key] = this.cache[keyRaw] = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility helper to recursively check for tree branches in the library
|
||||
* that don't have a key equal to the normal. For each sub-directory that
|
||||
* is caught, the path to it is added to output.
|
||||
*
|
||||
* @param {Object} current The current location being searched within
|
||||
* the library.
|
||||
* @param {String} path The current path within the library.
|
||||
* @param {String[]} output An Array of the String paths to parts that
|
||||
* don't have a matching key.
|
||||
* @return {String[]} output
|
||||
*/
|
||||
private findLackingNormal(current: any, path: string, output: string[]): string[] {
|
||||
var i: string;
|
||||
|
||||
if (!current.hasOwnProperty(this.normal)) {
|
||||
output.push(path);
|
||||
}
|
||||
|
||||
if (typeof current[i] === "object") {
|
||||
for (i in current) {
|
||||
if (current.hasOwnProperty(i)) {
|
||||
this.findLackingNormal(current[i], path + " " + i, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
/**
|
||||
* Utility function to follow a path into the library (this is the driver
|
||||
* for searching into the library). For each available key, if it matches
|
||||
* a key in current, it is removed from keys and recursion happens on the
|
||||
* sub-directory in current.
|
||||
*
|
||||
* @param {String[]} keys The currently available keys to search within.
|
||||
* @param {Object} current The current location being searched within
|
||||
* the library.
|
||||
* @return {Mixed} The most deeply matched part of the library.
|
||||
*/
|
||||
private followClass(keys: string[], current: any): any {
|
||||
var key: string,
|
||||
i: number;
|
||||
|
||||
/**
|
||||
* Utility function to follow a path into the library (this is the driver
|
||||
* for searching into the library). For each available key, if it matches
|
||||
* a key in current, it is removed from keys and recursion happens on the
|
||||
* sub-directory in current.
|
||||
*
|
||||
* @param {String[]} keys The currently available keys to search within.
|
||||
* @param {Object} current The current location being searched within
|
||||
* the library.
|
||||
* @return {Mixed} The most deeply matched part of the library.
|
||||
*/
|
||||
private followClass(keys: string[], current: any): any {
|
||||
var key: string,
|
||||
i: number;
|
||||
// If keys runs out, we're done
|
||||
if (!keys || !keys.length) {
|
||||
return current;
|
||||
}
|
||||
|
||||
// If keys runs out, we're done
|
||||
if (!keys || !keys.length) {
|
||||
// For each key in the current array...
|
||||
for (i = 0; i < keys.length; i += 1) {
|
||||
key = keys[i];
|
||||
|
||||
// ...if it matches, recurse on the other keys
|
||||
if (current.hasOwnProperty(key)) {
|
||||
keys.splice(i, 1);
|
||||
return this.followClass(keys, current[key]);
|
||||
}
|
||||
}
|
||||
|
||||
// If no key matched, try the normal (default)
|
||||
if (this.normal && current.hasOwnProperty(this.normal)) {
|
||||
return this.followClass(keys, current[this.normal]);
|
||||
}
|
||||
|
||||
// Nothing matches anything; we're done.
|
||||
return current;
|
||||
}
|
||||
|
||||
// For each key in the current array...
|
||||
for (i = 0; i < keys.length; i += 1) {
|
||||
key = keys[i];
|
||||
/**
|
||||
* Driver for this.findLackingNormal. If library directories are found to
|
||||
* not have a normal, it throws an error.
|
||||
*/
|
||||
private ensureLibraryNormal(): void {
|
||||
var caught: string[] = this.findLackingNormal(this.library, "base", []);
|
||||
|
||||
// ...if it matches, recurse on the other keys
|
||||
if (current.hasOwnProperty(key)) {
|
||||
keys.splice(i, 1);
|
||||
return this.followClass(keys, current[key]);
|
||||
if (caught.length) {
|
||||
throw new Error("Found " + caught.length + " library "
|
||||
+ "sub-directories missing the normal: "
|
||||
+ "\r\n " + caught.join("\r\n "));
|
||||
}
|
||||
}
|
||||
|
||||
// If no key matched, try the normal (default)
|
||||
if (this.normal && current.hasOwnProperty(this.normal)) {
|
||||
return this.followClass(keys, current[this.normal]);
|
||||
}
|
||||
|
||||
// Nothing matches anything; we're done.
|
||||
return current;
|
||||
}
|
||||
|
||||
private ensureLibraryNormal(): void {
|
||||
var caught: string[] = this.findLackingNormal(this.library, "base", []);
|
||||
|
||||
if (caught.length) {
|
||||
throw new Error("Found " + caught.length + " library "
|
||||
+ "sub-directories missing the normal: "
|
||||
+ "\r\n " + caught.join("\r\n "));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -27,18 +27,18 @@ var normal = "color",
|
||||
describe("constructor", function () {
|
||||
it("throws an error if not given settings", function () {
|
||||
chai.expect(function () {
|
||||
new StringFilr();
|
||||
new StringFilr.StringFilr();
|
||||
}).to.throw("No settings given to StringFilr.");
|
||||
});
|
||||
|
||||
it("throws an error if not given library", function () {
|
||||
chai.expect(function () {
|
||||
new StringFilr({});
|
||||
new StringFilr.StringFilr({});
|
||||
}).to.throw("No library given to StringFilr.");
|
||||
});
|
||||
|
||||
it("runs", function () {
|
||||
StringFiler = new StringFilr({
|
||||
StringFiler = new StringFilr.StringFilr({
|
||||
"normal": normal,
|
||||
"library": library
|
||||
});
|
||||
@@ -90,4 +90,4 @@ describe("cache", function () {
|
||||
StringFiler.clearCached("my major");
|
||||
chai.expect(StringFiler.getCached("my major")).to.be.undefined;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+12
-13
@@ -13,21 +13,20 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/FullScreenShenanigans/StringFilr/issues"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/FullScreenShenanigans/StringFilr/blob/master/LICENSE.txt"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chai": "2.2.X",
|
||||
"grunt": "0.4.X",
|
||||
"grunt-cli": "0.1.X",
|
||||
"grunt-contrib-copy": "0.8.X",
|
||||
"grunt-contrib-uglify": "0.8.X",
|
||||
"grunt-mocha-phantomjs": "0.6.X",
|
||||
"chai": "~2.2.X",
|
||||
"grunt-contrib-clean": "~0.6.0",
|
||||
"grunt": "~0.4.X",
|
||||
"grunt-cli": "~0.1.X",
|
||||
"grunt-contrib-copy": "~0.8.X",
|
||||
"grunt-contrib-uglify": "~0.8.X",
|
||||
"grunt-mocha-phantomjs": "~0.6.X",
|
||||
"grunt-tslint": "2.0.X",
|
||||
"grunt-typescript": "0.6.X",
|
||||
"mocha": "~2.2.X"
|
||||
"mocha": "~2.2.X",
|
||||
"grunt-preprocess": "~4.1.X",
|
||||
"tslint": "~2.0.X",
|
||||
"typescript": "~1.4.X"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user