├── app
├── styles.less
├── bootstrap.config.less
├── TimedCacheFileSystem.js
├── content.jade
├── LatencyFileSystem.js
├── bootstrap.config.js
├── web_modules
│ └── jquery-caret.js
├── TestContents.js
└── app.js
├── README.md
├── .gitignore
└── package.json
/app/styles.less:
--------------------------------------------------------------------------------
1 | .completion-table td {
2 | cursor: pointer;
3 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # enhanced-resolve-completion-demo
2 |
3 | See link in description
--------------------------------------------------------------------------------
/app/bootstrap.config.less:
--------------------------------------------------------------------------------
1 | // Modify bootstrap variables here.
2 |
3 | // a example:
4 | // @bodyBackground: @grayLighter;
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # will be installed by "wpt init"
2 | /publish.bat
3 | /publish.sh
4 | /dev-server.bat
5 | /dev-server.sh
6 | /server.bat
7 | /server.sh
8 | /_template
9 |
10 | # will be installed by "npm install"
11 | /node_modules
12 |
13 | # will be created by publishing or "wpt init"
14 | # you may remove these lines if you want to publish
15 | # to a git repo. (i. e. in the gh-pages branch)
16 | /publishedStats.json
17 | /public
18 | /index.html
19 | /cache.manifest
20 | /server.js
--------------------------------------------------------------------------------
/app/TimedCacheFileSystem.js:
--------------------------------------------------------------------------------
1 | var createThrottledFunction = require("enhanced-resolve/lib/createThrottledFunction");
2 |
3 | function TimedCacheFileSystem(fs, timeout) {
4 | this.fs = fs;
5 | this.stat = createThrottledFunction(this.fs.stat.bind(this.fs), timeout, {});
6 | this.readdir = createThrottledFunction(this.fs.readdir.bind(this.fs), timeout, {});
7 | this.readFile = createThrottledFunction(this.fs.readFile.bind(this.fs), timeout, {});
8 | }
9 | module.exports = TimedCacheFileSystem;
10 |
--------------------------------------------------------------------------------
/app/content.jade:
--------------------------------------------------------------------------------
1 | - require("bootstrap");
2 | - require("./styles.less");
3 | .container-fluid
4 | .row-fluid
5 | .span6
6 | form.form
7 | fieldset
8 | legend Code completion test
9 | p Current directory: /home/user/app
10 | label Type here:
11 | input(type="text").span12.request-input
12 | table.table.table-condensed.table-hover.completion-table
13 | legend Resolve
14 | lable Resolves to:
15 | pre.result loader/index.js!moon/shine/is/cool.js
16 | .span6
17 | form.form
18 | fieldset
19 | legend Test filesystem
20 | label Choose one:
21 | select.filesystem-chooser
22 | option(value="simple") Simple
23 | option(value="depth") Depth
24 | option(value="modules") Modules
25 | label Latency: (in ms, per fs access)
26 | input(type="number", value="20").latency-input
27 | label Cache timeout: (in ms)
28 | input(type="number", value="4000").timeout-input
29 | h4 Preview
30 | pre.filesystem
31 |
--------------------------------------------------------------------------------
/app/LatencyFileSystem.js:
--------------------------------------------------------------------------------
1 | function LatencyFileSystem(fs, latency) {
2 | this.fs = fs;
3 | this.latency = latency;
4 | }
5 | module.exports = LatencyFileSystem;
6 |
7 | function asAsync(fn, callback) {
8 | try {
9 | var result = fn();
10 | setTimeout(function() {
11 | callback(null, result);
12 | }, this.latency);
13 | } catch(e) {
14 | setTimeout(function() {
15 | callback(e);
16 | }, this.latency);
17 | }
18 | }
19 |
20 | LatencyFileSystem.prototype.readdir = function(path, callback) {
21 | asAsync.call(this, function() {
22 | return this.fs.readdirSync(path);
23 | }.bind(this), callback);
24 | }
25 |
26 | LatencyFileSystem.prototype.readFile = function(path, encoding, callback) {
27 | asAsync.call(this, function() {
28 | return this.fs.readFileSync(path, encoding);
29 | }.bind(this), callback);
30 | }
31 |
32 | LatencyFileSystem.prototype.stat = function(path, callback) {
33 | asAsync.call(this, function() {
34 | return this.fs.statSync(path);
35 | }.bind(this), callback);
36 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "enhanced-resolve-completion-demo",
3 | "version": "0.1.0",
4 | "author": "Tobias Koppers @sokra",
5 | "dependencies": {
6 | "enhanced-resolve": "0.4.x"
7 | },
8 | "devDependencies": {
9 | "wpt": "0.5.x",
10 | "webpack": "0.8.x",
11 | "webpack-dev-server": "0.8.x",
12 | "enhanced-require": "0.4.x",
13 | "coffee-loader": "0.2.x",
14 | "jade-loader": "0.2.x",
15 | "json-loader": "0.2.x",
16 | "raw-loader": "0.2.x",
17 | "express": "3.0.x"
18 | },
19 | "licenses": [
20 | {
21 | "type": "MIT",
22 | "url": "http://www.opensource.org/licenses/mit-license.php"
23 | }
24 | ],
25 | "webpackTemplate": {
26 | "version": "0.5.5",
27 | "modules": {
28 | "jquery": {
29 | "templates": "https://raw.github.com/webpack/jquery-wpt-module/master",
30 | "template": "https://raw.github.com/webpack/jquery-wpt-module/v1.8.1",
31 | "version": "1.8.1"
32 | },
33 | "bootstrap": {
34 | "templates": "https://raw.github.com/webpack/bootstrap-wpt-module/master",
35 | "template": "https://raw.github.com/webpack/bootstrap-wpt-module/v2.2.1",
36 | "version": "2.2.1"
37 | }
38 | },
39 | "options": {
40 | "appName": "enhanced-resolve-completion-demo",
41 | "author": "Tobias Koppers @sokra",
42 | "nodeServer": false,
43 | "cacheManifest": false
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/app/bootstrap.config.js:
--------------------------------------------------------------------------------
1 | // executed while compiling by the bootstrap wpt-module
2 | // to get the (by-default) required bootstrap scripts and styles
3 | // you can ever require("bootstrap/xxx"), i.e. require("bootstrap/affix")
4 | // to include more scripts, that are not included by default
5 |
6 | // modify to your wishes
7 | module.exports = {
8 | scripts: {
9 | affix: true,
10 | alert: true,
11 | button: true,
12 | carousel: true,
13 | collapse: true,
14 | dropdown: true,
15 | modal: true,
16 | popover: true,
17 | scrollspy: true,
18 | tab: true,
19 | tooltip: true,
20 | transition: true,
21 | typeahead: true
22 | },
23 | styles: {
24 | accordion: true,
25 | alerts: true,
26 | breadcrumbs: true,
27 | "button-groups": true,
28 | buttons: true,
29 | carousel: true,
30 | close: true,
31 | code: true,
32 | "component-animations": true,
33 | dropdowns: true,
34 | forms: true,
35 | grid: true,
36 | "hero-unit": true,
37 | "labels-badges": true,
38 | layouts: true,
39 | mixins: true,
40 | media: true,
41 | modals: true,
42 | navbar: true,
43 | navs: true,
44 | pager: true,
45 | pagination: true,
46 | popovers: true,
47 | "progress-bars": true,
48 | "responsive-1200px-min": true,
49 | "responsive-767px-max": true,
50 | "responsive-768px-979px": true,
51 | "responsive-navbar": true,
52 | "responsive-utilities": true,
53 | scaffolding: true,
54 | sprites: true,
55 | tables: true,
56 | thumbnails: true,
57 | tooltip: true,
58 | type: true,
59 | utilities: true,
60 | wells: true
61 | }
62 | }
--------------------------------------------------------------------------------
/app/web_modules/jquery-caret.js:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright (c) 2010 C. F., Wong (Cloudgen Examplet Store)
4 | * Licensed under the MIT License:
5 | * http://www.opensource.org/licenses/mit-license.php
6 | *
7 | */
8 | (function($,len,createRange,duplicate){
9 | $.fn.caret=function(options,opt2){
10 | var start,end,t=this[0],browser=$.browser.msie;
11 | if(typeof options==="object" && typeof options.start==="number" && typeof options.end==="number") {
12 | start=options.start;
13 | end=options.end;
14 | } else if(typeof options==="number" && typeof opt2==="number"){
15 | start=options;
16 | end=opt2;
17 | } else if(typeof options==="string"){
18 | if((start=t.value.indexOf(options))>-1) end=start+options[len];
19 | else start=null;
20 | } else if(Object.prototype.toString.call(options)==="[object RegExp]"){
21 | var re=options.exec(t.value);
22 | if(re != null) {
23 | start=re.index;
24 | end=start+re[0][len];
25 | }
26 | }
27 | if(typeof start!="undefined"){
28 | if(browser){
29 | var selRange = this[0].createTextRange();
30 | selRange.collapse(true);
31 | selRange.moveStart('character', start);
32 | selRange.moveEnd('character', end-start);
33 | selRange.select();
34 | } else {
35 | this[0].selectionStart=start;
36 | this[0].selectionEnd=end;
37 | }
38 | this[0].focus();
39 | return this
40 | } else {
41 | if(browser){
42 | var selection=document.selection;
43 | if (this[0].tagName.toLowerCase() != "textarea") {
44 | var val = this.val(),
45 | range = selection[createRange]()[duplicate]();
46 | range.moveEnd("character", val[len]);
47 | var s = (range.text == "" ? val[len]:val.lastIndexOf(range.text));
48 | range = selection[createRange]()[duplicate]();
49 | range.moveStart("character", -val[len]);
50 | var e = range.text[len];
51 | } else {
52 | var range = selection[createRange](),
53 | stored_range = range[duplicate]();
54 | stored_range.moveToElementText(this[0]);
55 | stored_range.setEndPoint('EndToEnd', range);
56 | var s = stored_range.text[len] - range.text[len],
57 | e = s + range.text[len]
58 | }
59 | } else {
60 | var s=t.selectionStart,
61 | e=t.selectionEnd;
62 | }
63 | var te=t.value.substring(s,e);
64 | return {start:s,end:e,text:te,replace:function(st){
65 | return t.value.substring(0,s)+st+t.value.substring(e,t.value[len])
66 | }}
67 | }
68 | }
69 | })(jQuery,"length","createRange","duplicate");
--------------------------------------------------------------------------------
/app/TestContents.js:
--------------------------------------------------------------------------------
1 | exports.simple = {
2 | home: {
3 | user: {
4 | node_modules: {
5 | usermodule1: {
6 | "index.js": ""
7 | },
8 | usermodule2: {
9 | "package.json": JSON.stringify({
10 | main: "main"
11 | }),
12 | "main.js": ""
13 | },
14 | "usermodule3.js": ""
15 | },
16 | app: {
17 | lib: {
18 | "file.js": ""
19 | }
20 | }
21 | }
22 | }
23 | };
24 |
25 | exports.depth = {
26 | home: {
27 | user: {
28 | node_modules: {
29 | usermodule1: {
30 | "index.js": ""
31 | },
32 | usermodule2: {
33 | "package.json": JSON.stringify({
34 | main: "main"
35 | }),
36 | "main.js": ""
37 | },
38 | "usermodule3.js": ""
39 | },
40 | app: {
41 | node_modules: {
42 |
43 | },
44 | lib: {
45 | node_modules: {
46 | },
47 | web_modules: {
48 | },
49 | directory: {
50 | node_modules: {
51 | },
52 | "file.js": ""
53 | }
54 | }
55 | }
56 | }
57 | }
58 | };
59 |
60 | exports.modules = {
61 | home: {
62 | user: {
63 | node_modules: {
64 | usermodule1: {
65 | "index.js": ""
66 | },
67 | usermodule2: {
68 | "package.json": JSON.stringify({
69 | main: "main"
70 | }),
71 | "main.js": ""
72 | },
73 | "usermodule3.js": "",
74 | "raw-loader": {
75 | "package.json": JSON.stringify({
76 | loader: "loader",
77 | main: "main"
78 | }),
79 | "index.loader.js": "",
80 | "index.js": "",
81 | "main.js": "",
82 | "loader.js": ""
83 | }
84 | },
85 | app: {
86 | node_modules: {
87 | "enhanced-resolve": {
88 | "package.json": JSON.stringify({
89 | main: "lib/cachedFsResolve.js"
90 | }),
91 | lib: {
92 | "cachedFsResolve.js": "",
93 | "createThrottledFunction.js": "",
94 | "matchRegExpObject.js": "",
95 | "parse.js": "",
96 | "resolve.js": "",
97 | "stringify.js": ""
98 | },
99 | test: {
100 | "complete.js": "",
101 | "errors.js": "",
102 | fixtures: {
103 | "a.js": "",
104 | "abc.txt": "",
105 | "b.js": "",
106 | "c.js": "",
107 | "complex.js": "",
108 | "dirOrFile.js": "",
109 | "file.load1": "",
110 | "file.load2": "",
111 | "main1.js": "",
112 | "main2.js": "",
113 | "main3.js": "",
114 | "shortcutdir.js": ""
115 | },
116 | lib: {
117 | "AsyncFileSystem.js": "",
118 | "benchmark.js": "",
119 | "CachedFileSystem.js": "",
120 | "ConstFileSystem.js": "",
121 | "customResolveFactory.js": "",
122 | "DebugFileSystem.js": "",
123 | "LoggedFileSystem.js": "",
124 | "TestContents.js": "",
125 | },
126 | "parse.js": "",
127 | "resolve.js": "",
128 | "simple.js": "",
129 | "stringify.js": ""
130 | }
131 | },
132 | },
133 | lib: {
134 | node_modules: {
135 | },
136 | web_modules: {
137 | },
138 | directory: {
139 | node_modules: {
140 | },
141 | "file.js": ""
142 | }
143 | }
144 | }
145 | }
146 | }
147 | };
--------------------------------------------------------------------------------
/app/app.js:
--------------------------------------------------------------------------------
1 | function prefix(str, prefix) {
2 | return prefix + str.split("\n").join(prefix);
3 | }
4 |
5 | var customResolveFactory = require("enhanced-resolve/test/lib/customResolveFactory");
6 | var ConstFileSystem = require("enhanced-resolve/test/lib/ConstFileSystem");
7 | var LatencyFileSystem = require("./LatencyFileSystem");
8 | var TimedCacheFileSystem = require("./TimedCacheFileSystem");
9 | var TestContents = require("./TestContents");
10 |
11 | function syncFsToString(fs, path) {
12 | var stat = fs.statSync(path);
13 | if(stat.isFile()) {
14 | return path.split("/").pop();
15 | } else {
16 | var dir = fs.readdirSync(path);
17 | if(dir.length == 0) {
18 | return path.split("/").pop() + " (empty)";
19 | } else {
20 | dir = dir.map(function(d) {
21 | return syncFsToString(fs, path + "/" + d);
22 | });
23 | var last = dir.pop();
24 | dir = dir.map(function(d) {
25 | return "+--" + d.split("\n").join("\n| ");
26 | });
27 | dir.push("+--" + last.split("\n").join("\n "));
28 | return path.split("/").pop() + "\n" + dir.join("\n");
29 | }
30 | }
31 | }
32 |
33 | var resolve = null;
34 | function initFilesystem(name, latency, timeout) {
35 | var syncFs = new ConstFileSystem(TestContents[name]);
36 | resolve = customResolveFactory(new TimedCacheFileSystem(new LatencyFileSystem(syncFs, latency), timeout));
37 | $(".filesystem").text(syncFsToString(syncFs, "/home"));
38 | }
39 |
40 | var jquery = require("jquery");
41 | require("jquery-caret");
42 | jquery(function($) {
43 | $("body").html(require("./content.jade")());
44 |
45 | function updateFilesystem() {
46 | initFilesystem($(".filesystem-chooser").val(), parseInt($(".latency-input").val(), 10), parseInt($(".timeout-input").val(), 10));
47 | oldText = "";
48 | checkUpdate();
49 | }
50 | updateFilesystem();
51 |
52 | $(".filesystem-chooser, .latency-input, .timeout-input").change(function() {
53 | updateFilesystem();
54 | });
55 |
56 | $(".request-input").bind("focus keyup click mouseup mousedown", function() {
57 | checkUpdate();
58 | });
59 |
60 | var currentCompletions = null;
61 | var currentCompletionPos = 0;
62 | $(".request-input").bind("keydown keypress", function(event) {
63 | if(event.which == 13) {
64 | if(currentCompletions) {
65 | applyCompletion(currentCompletions[currentCompletionPos], $(".request-input").caret().start);
66 | }
67 | event.preventDefault();
68 | return false;
69 | }
70 | if(event.which == 38) {
71 | if(currentCompletions && currentCompletionPos > 0) {
72 | currentCompletionPos--;
73 | $($(".completion-table tr").removeClass("success")[currentCompletionPos]).addClass("success");
74 | }
75 | event.preventDefault();
76 | return false;
77 | }
78 | if(event.which == 40) {
79 | if(currentCompletions && currentCompletionPos < currentCompletions.length-1) {
80 | currentCompletionPos++;
81 | $($(".completion-table tr").removeClass("success")[currentCompletionPos]).addClass("success");
82 | }
83 | event.preventDefault();
84 | return false;
85 | }
86 |
87 | checkUpdate();
88 | });
89 |
90 | var oldText = "";
91 | function getCompletionText() {
92 | var input = $(".request-input");
93 | var caret = input.caret();
94 | var text = input.val();
95 | var rawText = text;
96 | return text.substr(0, caret.start) + "*" + text.substr(caret.end);
97 | }
98 | function checkUpdate() {
99 | var input = $(".request-input");
100 | var caret = input.caret();
101 | var rawText = input.val();
102 | var text = getCompletionText();;
103 | if(oldText == text) return;
104 | oldText = text;
105 | resolve("/home/user/app", rawText, function(err, result) {
106 | if(err) return $(".result").text(err + "");
107 | $(".result").text(result.replace(/!/g, "!\n "));
108 | });
109 | var table = $(".completion-table");
110 | resolve.complete("/home/user/app", text, function(err, completions) {
111 | table.html("");
112 | if(err) return;
113 | currentCompletions = completions;
114 | currentCompletionPos = 0;
115 | var body = $("
").text(completion.insert)).appendTo(row);
119 | $("").append($("").text(completion.seqment)).appendTo(row);
120 | $("").append($("").text(completion.result)).appendTo(row);
121 | row.click(function() {
122 | applyCompletion(completion, caret.start);
123 | });
124 | if(idx == 0)
125 | row.addClass("success");
126 | row.appendTo(body);
127 | });
128 | body.appendTo(table);
129 | });
130 | }
131 | function applyCompletion(completion, caret) {
132 | var input = $(".request-input");
133 | input.val(completion.result);
134 | input.focus();
135 | var pos = caret + completion.insert.length;
136 | input.caret({start: pos, end: pos});
137 | }
138 | });
139 |
140 |
141 |
--------------------------------------------------------------------------------