jsduck 3.8.2 → 3.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +34 -17
- data/jsduck.gemspec +2 -2
- data/lib/jsduck/file_categories.rb +1 -1
- data/lib/jsduck/json_duck.rb +6 -1
- data/lib/jsduck/options.rb +9 -4
- data/opt/comments-server-side/app.js +250 -246
- data/opt/comments-server-side/database.js +8 -1
- data/opt/comments-server-side/package.json +2 -3
- data/opt/comments-server-side/util.js +2 -1
- metadata +8 -16
data/Rakefile
CHANGED
@@ -17,12 +17,12 @@ def load_sdk_vars
|
|
17
17
|
else
|
18
18
|
puts "Error: sdk-vars.rb not found."
|
19
19
|
puts
|
20
|
-
puts "Please create file sdk-vars.rb and define
|
21
|
-
puts
|
22
|
-
puts "For example:"
|
20
|
+
puts "Please create file sdk-vars.rb and define in it:"
|
23
21
|
puts
|
24
22
|
puts " # path to Ext JS 4 build"
|
25
|
-
puts "
|
23
|
+
puts " EXT_BUILD='/path/to/ext-4.0.7'"
|
24
|
+
puts " # path to Touch 2 build"
|
25
|
+
puts " TOUCH_BUILD='/path/to/touch-2.0.0'"
|
26
26
|
puts " # where to output the docs"
|
27
27
|
puts " OUT_DIR='/path/to/ouput/dir'"
|
28
28
|
puts " # path to SDK (for developers at Sencha)"
|
@@ -132,7 +132,7 @@ def compress
|
|
132
132
|
system "mkdir #{dir}/extjs"
|
133
133
|
system "cp template/extjs/ext-all.js #{dir}/extjs"
|
134
134
|
system "mkdir -p #{dir}/extjs/resources/themes/images"
|
135
|
-
system "cp -r #{
|
135
|
+
system "cp -r #{EXT_BUILD}/resources/themes/images/default #{dir}/extjs/resources/themes/images"
|
136
136
|
end
|
137
137
|
|
138
138
|
|
@@ -140,10 +140,6 @@ class JsDuckRunner
|
|
140
140
|
def initialize
|
141
141
|
@options = []
|
142
142
|
load_sdk_vars
|
143
|
-
@sdk_dir = SDK_DIR
|
144
|
-
@out_dir = OUT_DIR
|
145
|
-
@ext_dir = EXT_DIR
|
146
|
-
@animator_dir = ANIMATOR_DIR
|
147
143
|
end
|
148
144
|
|
149
145
|
def add_options(options)
|
@@ -168,14 +164,14 @@ class JsDuckRunner
|
|
168
164
|
|
169
165
|
# For export of ExtJS, reference extjs from the parent dir
|
170
166
|
def make_extjs_path_relative
|
171
|
-
["#{
|
167
|
+
["#{OUT_DIR}/index.html"].each do |file|
|
172
168
|
out = []
|
173
169
|
IO.read(file).each_line do |line|
|
174
170
|
out << line.sub(/(src|href)="extjs\//, '\1="../')
|
175
171
|
end
|
176
172
|
File.open(file, 'w') {|f| f.write(out) }
|
177
173
|
end
|
178
|
-
system "rm -rf #{
|
174
|
+
system "rm -rf #{OUT_DIR}/extjs"
|
179
175
|
end
|
180
176
|
|
181
177
|
def add_ext4
|
@@ -184,10 +180,10 @@ class JsDuckRunner
|
|
184
180
|
"--footer", "Ext JS 4.0 Docs - Generated with <a href='https://github.com/senchalabs/jsduck'>JSDuck</a> VERSION. <a href='http://www.sencha.com/legal/terms-of-use/'>Terms of Use</a>",
|
185
181
|
"--ignore-global",
|
186
182
|
"--no-warnings",
|
187
|
-
"--images", "#{
|
183
|
+
"--images", "#{EXT_BUILD}/docs/doc-resources",
|
188
184
|
"--local-storage-db", "ext-4",
|
189
|
-
"--output", "#{
|
190
|
-
"#{
|
185
|
+
"--output", "#{OUT_DIR}",
|
186
|
+
"#{EXT_BUILD}/src",
|
191
187
|
]
|
192
188
|
end
|
193
189
|
|
@@ -274,6 +270,10 @@ class JsDuckRunner
|
|
274
270
|
text: 'Ext JS 3',
|
275
271
|
href: 'http://docs.sencha.com/ext-js/3-4'
|
276
272
|
},
|
273
|
+
{
|
274
|
+
text: 'Ext JS 2',
|
275
|
+
href: 'http://docs.sencha.com/ext-js/2-3'
|
276
|
+
},
|
277
277
|
{
|
278
278
|
text: 'Sencha Touch 2',
|
279
279
|
href: 'http://docs.sencha.com/touch/2-0'
|
@@ -302,12 +302,12 @@ class JsDuckRunner
|
|
302
302
|
end
|
303
303
|
|
304
304
|
def copy_extjs_build
|
305
|
-
system "cp -r #{
|
305
|
+
system "cp -r #{EXT_BUILD} #{OUT_DIR}/extjs-build"
|
306
306
|
end
|
307
307
|
|
308
308
|
# Copy over Sencha Touch
|
309
309
|
def copy_touch2_build
|
310
|
-
system "cp -r #{
|
310
|
+
system "cp -r #{TOUCH_BUILD} #{OUT_DIR}/touch"
|
311
311
|
end
|
312
312
|
|
313
313
|
def run
|
@@ -397,6 +397,23 @@ task :ext3, [:mode] => :sass do |t, args|
|
|
397
397
|
runner.run
|
398
398
|
end
|
399
399
|
|
400
|
+
desc "Run JSDuck on official Ext JS 2.3 build\n" +
|
401
|
+
"ext2 - creates debug/development version\n" +
|
402
|
+
"ext2[export] - creates export/deployable version\n"
|
403
|
+
"ext2[live] - creates live version for deployment\n"
|
404
|
+
task :ext2, [:mode] => :sass do |t, args|
|
405
|
+
mode = args[:mode] || "debug"
|
406
|
+
throw "Unknown mode #{mode}" unless ["debug", "export", "live"].include?(mode)
|
407
|
+
compress if mode == "export"
|
408
|
+
|
409
|
+
runner = JsDuckRunner.new
|
410
|
+
runner.add_options ["--output", OUT_DIR, "--config", "#{SDK_DIR}/../ext-2-source/doc-config.json"]
|
411
|
+
runner.add_debug if mode == "debug"
|
412
|
+
runner.add_seo if mode == "live"
|
413
|
+
runner.add_google_analytics if mode == "live"
|
414
|
+
runner.run
|
415
|
+
end
|
416
|
+
|
400
417
|
desc "Run JSDuck on Sencha Touch (for internal use at Sencha)\n" +
|
401
418
|
"touch - creates debug/development version\n" +
|
402
419
|
"touch[live] - create live version for deployment\n"
|
@@ -475,7 +492,7 @@ task :senchaio, [:mode] => :sass do |t, args|
|
|
475
492
|
compress if mode == "live"
|
476
493
|
|
477
494
|
runner = JsDuckRunner.new
|
478
|
-
runner.add_options ["--output", OUT_DIR, "--config", "#{SDK_DIR}/../
|
495
|
+
runner.add_options ["--output", OUT_DIR, "--config", "#{SDK_DIR}/../client-framework/docs/config.json"]
|
479
496
|
runner.add_debug if mode == "debug"
|
480
497
|
runner.add_seo if mode == "debug" || mode == "live"
|
481
498
|
runner.add_google_analytics if mode == "live"
|
data/jsduck.gemspec
CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.required_rubygems_version = ">= 1.3.5"
|
3
3
|
|
4
4
|
s.name = 'jsduck'
|
5
|
-
s.version = '3.8.
|
6
|
-
s.date = '2012-
|
5
|
+
s.version = '3.8.3'
|
6
|
+
s.date = '2012-04-05'
|
7
7
|
s.summary = "Simple JavaScript Duckumentation generator"
|
8
8
|
s.description = "Documentation generator for Sencha JS frameworks"
|
9
9
|
s.homepage = "https://github.com/senchalabs/jsduck"
|
@@ -13,7 +13,7 @@ module JsDuck
|
|
13
13
|
|
14
14
|
# Don't crash if old syntax is used.
|
15
15
|
if @categories.is_a?(Hash) && @categories["categories"]
|
16
|
-
Logger.instance.warn(
|
16
|
+
Logger.instance.warn(nil, 'Update categories file to contain just the array inside {"categories": [...]}')
|
17
17
|
@categories = @categories["categories"]
|
18
18
|
end
|
19
19
|
|
data/lib/jsduck/json_duck.rb
CHANGED
@@ -34,7 +34,12 @@ module JsDuck
|
|
34
34
|
|
35
35
|
# Reads and parses JSON from file
|
36
36
|
def self.read(filename)
|
37
|
-
|
37
|
+
begin
|
38
|
+
self.parse(JsDuck::IO.read(filename))
|
39
|
+
rescue
|
40
|
+
puts "Oh noes! #{filename} is not a valid JSON file."
|
41
|
+
exit(1)
|
42
|
+
end
|
38
43
|
end
|
39
44
|
|
40
45
|
# Parses JSON string
|
data/lib/jsduck/options.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'optparse'
|
2
2
|
require 'jsduck/meta_tag_registry'
|
3
3
|
require 'jsduck/logger'
|
4
|
-
require 'jsduck/
|
4
|
+
require 'jsduck/json_duck'
|
5
5
|
|
6
6
|
module JsDuck
|
7
7
|
|
@@ -73,7 +73,7 @@ module JsDuck
|
|
73
73
|
]
|
74
74
|
@meta_tag_paths = []
|
75
75
|
|
76
|
-
@version = "3.8.
|
76
|
+
@version = "3.8.3"
|
77
77
|
|
78
78
|
# Customizing output
|
79
79
|
@title = "Sencha Docs - Ext JS"
|
@@ -349,7 +349,12 @@ module JsDuck
|
|
349
349
|
opts.on('--config=PATH',
|
350
350
|
"Loads config options from JSON file.", " ") do |path|
|
351
351
|
path = canonical(path)
|
352
|
-
|
352
|
+
if File.exists?(path)
|
353
|
+
config = read_json_config(path)
|
354
|
+
else
|
355
|
+
puts "Oh noes! The config file #{path} doesn't exist."
|
356
|
+
exit(1)
|
357
|
+
end
|
353
358
|
# treat paths inside JSON config relative to the location of
|
354
359
|
# config file. When done, switch back to current working dir.
|
355
360
|
@working_dir = File.dirname(path)
|
@@ -447,7 +452,7 @@ module JsDuck
|
|
447
452
|
|
448
453
|
# Extracts files of first build in jsb file
|
449
454
|
def extract_jsb_files(jsb_file)
|
450
|
-
json =
|
455
|
+
json = JsonDuck::read(jsb_file)
|
451
456
|
basedir = File.dirname(jsb_file)
|
452
457
|
|
453
458
|
return json["builds"][0]["packages"].map do |package_id|
|
@@ -19,10 +19,8 @@
|
|
19
19
|
*
|
20
20
|
*/
|
21
21
|
|
22
|
-
config = require('./config');
|
23
|
-
mongoose = require('mongoose');
|
22
|
+
var config = require('./config');
|
24
23
|
require('./database');
|
25
|
-
require('express-namespace');
|
26
24
|
|
27
25
|
var mysql = require('mysql'),
|
28
26
|
client = mysql.createClient({
|
@@ -32,328 +30,334 @@ var mysql = require('mysql'),
|
|
32
30
|
database: config.db.dbName
|
33
31
|
}),
|
34
32
|
express = require('express'),
|
35
|
-
|
36
|
-
MongoStore = require('connect-session-mongo'),
|
33
|
+
MongoStore = require('connect-mongo'),
|
37
34
|
_ = require('underscore'),
|
38
35
|
ForumUser = require('./ForumUser').ForumUser,
|
39
36
|
forumUser = new ForumUser(client),
|
40
37
|
util = require('./util'),
|
41
|
-
crypto = require('crypto')
|
38
|
+
crypto = require('crypto'),
|
39
|
+
mongoose = require('mongoose');
|
42
40
|
|
41
|
+
var app = express();
|
43
42
|
|
44
|
-
|
43
|
+
app.configure(function() {
|
45
44
|
|
46
45
|
// Headers for Cross Origin Resource Sharing (CORS)
|
47
|
-
function (req, res, next) {
|
46
|
+
app.use(function (req, res, next) {
|
48
47
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
49
48
|
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS');
|
50
49
|
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
|
51
50
|
next();
|
52
|
-
}
|
51
|
+
});
|
53
52
|
|
54
|
-
express.cookieParser()
|
53
|
+
app.use(express.cookieParser(config.sessionSecret));
|
55
54
|
|
56
55
|
// Hack to set session cookie if session ID is set as a URL param.
|
57
56
|
// This is because not all browsers support sending cookies via CORS
|
58
|
-
function(req, res, next) {
|
59
|
-
if (req.query.sid) {
|
57
|
+
app.use(function(req, res, next) {
|
58
|
+
if (req.query.sid && req.query.sid != 'null') {
|
60
59
|
var sid = req.query.sid.replace(/ /g, '+');
|
61
|
-
req.
|
62
|
-
req.
|
60
|
+
req.sessionID = sid;
|
61
|
+
req.signedCookies = req.signedCookies || {};
|
62
|
+
req.signedCookies['sencha_docs'] = sid;
|
63
63
|
}
|
64
64
|
next();
|
65
|
-
}
|
65
|
+
});
|
66
66
|
|
67
67
|
// Use MongoDB for session storage
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
app.use(express.session({
|
69
|
+
secret: config.sessionSecret,
|
70
|
+
key: 'sencha_docs',
|
71
|
+
store: new MongoStore({
|
72
|
+
url: exports.mongoDb + "/sessions"
|
73
|
+
})
|
74
|
+
}));
|
75
|
+
|
76
|
+
app.use(function(req, res, next) {
|
71
77
|
// IE doesn't get content-type, so default to form encoded.
|
72
78
|
if (!req.headers['content-type']) {
|
73
79
|
req.headers['content-type'] = 'application/x-www-form-urlencoded';
|
74
80
|
}
|
75
81
|
next();
|
76
|
-
}
|
77
|
-
express.bodyParser(),
|
78
|
-
express.methodOverride()
|
79
|
-
);
|
82
|
+
});
|
80
83
|
|
81
|
-
app.
|
84
|
+
app.use(express.bodyParser());
|
85
|
+
app.use(express.methodOverride());
|
82
86
|
|
83
|
-
|
84
|
-
|
87
|
+
app.enable('jsonp callback');
|
88
|
+
});
|
85
89
|
|
86
|
-
|
87
|
-
|
88
|
-
|
90
|
+
app.configure('development', function(){
|
91
|
+
app.use(express.logger('dev'));
|
92
|
+
app.use(express.errorHandler());
|
93
|
+
});
|
89
94
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
});
|
95
|
+
/**
|
96
|
+
* Authentication
|
97
|
+
*/
|
94
98
|
|
95
|
-
|
99
|
+
app.get('/auth/session', function(req, res) {
|
100
|
+
var result = req.session && req.session.user && forumUser.clientUser(req.session.user);
|
101
|
+
res.json(result || false);
|
102
|
+
});
|
96
103
|
|
97
|
-
|
104
|
+
app.post('/auth/login', function(req, res){
|
98
105
|
|
99
|
-
|
100
|
-
res.json({ success: false, reason: err });
|
101
|
-
return;
|
102
|
-
}
|
106
|
+
forumUser.login(req.body.username, req.body.password, function(err, result) {
|
103
107
|
|
104
|
-
|
105
|
-
|
108
|
+
if (err) {
|
109
|
+
res.json({ success: false, reason: err });
|
110
|
+
return;
|
111
|
+
}
|
106
112
|
|
107
|
-
|
108
|
-
|
109
|
-
success: true
|
110
|
-
});
|
113
|
+
req.session = req.session || {};
|
114
|
+
req.session.user = result;
|
111
115
|
|
112
|
-
|
116
|
+
var response = _.extend(forumUser.clientUser(result), {
|
117
|
+
sessionID: req.sessionID,
|
118
|
+
success: true
|
113
119
|
});
|
114
|
-
});
|
115
|
-
|
116
|
-
// Remove session
|
117
|
-
app.post('/logout', function(req, res){
|
118
|
-
req.session.user = null;
|
119
|
-
res.json({ success: true });
|
120
|
-
});
|
121
120
|
|
122
|
-
|
123
|
-
* Handles comment unsubscription requests.
|
124
|
-
*/
|
125
|
-
app.get('/unsubscribe/:subscriptionId', function(req, res) {
|
126
|
-
|
127
|
-
Subscription.findOne({ _id: req.params.subscriptionId }, function(err, subscription) {
|
128
|
-
if (err) throw(err);
|
129
|
-
|
130
|
-
if (subscription) {
|
131
|
-
if (req.query.all == 'true') {
|
132
|
-
Subscription.remove({ userId: subscription.userId }, function(err) {
|
133
|
-
res.send("You have been unsubscribed from all threads.");
|
134
|
-
});
|
135
|
-
} else {
|
136
|
-
Subscription.remove({ _id: req.params.subscriptionId }, function(err) {
|
137
|
-
res.send("You have been unsubscribed from that thread.");
|
138
|
-
});
|
139
|
-
}
|
140
|
-
} else {
|
141
|
-
res.send("You are already unsubscribed.");
|
142
|
-
}
|
143
|
-
});
|
121
|
+
res.json(response);
|
144
122
|
});
|
145
|
-
|
146
123
|
});
|
147
124
|
|
125
|
+
// Remove session
|
126
|
+
app.post('/auth/logout', function(req, res){
|
127
|
+
req.session.user = null;
|
128
|
+
res.json({ success: true });
|
129
|
+
});
|
148
130
|
|
149
131
|
/**
|
150
|
-
*
|
132
|
+
* Handles comment unsubscription requests.
|
151
133
|
*/
|
152
|
-
app.
|
134
|
+
app.get('/auth/unsubscribe/:subscriptionId', function(req, res) {
|
153
135
|
|
154
|
-
|
155
|
-
|
156
|
-
*/
|
157
|
-
app.get('/comments', util.getCommentReads, function(req, res) {
|
136
|
+
Subscription.findOne({ _id: req.params.subscriptionId }, function(err, subscription) {
|
137
|
+
if (err) throw(err);
|
158
138
|
|
159
|
-
if (
|
160
|
-
|
161
|
-
|
139
|
+
if (subscription) {
|
140
|
+
if (req.query.all == 'true') {
|
141
|
+
Subscription.remove({ userId: subscription.userId }, function(err) {
|
142
|
+
res.send("You have been unsubscribed from all threads.");
|
143
|
+
});
|
144
|
+
} else {
|
145
|
+
Subscription.remove({ _id: req.params.subscriptionId }, function(err) {
|
146
|
+
res.send("You have been unsubscribed from that thread.");
|
147
|
+
});
|
148
|
+
}
|
149
|
+
} else {
|
150
|
+
res.send("You are already unsubscribed.");
|
162
151
|
}
|
163
|
-
|
164
|
-
Comment.find({
|
165
|
-
target: JSON.parse(req.query.startkey),
|
166
|
-
deleted: { '$ne': true },
|
167
|
-
sdk: req.params.sdk,
|
168
|
-
version: req.params.version
|
169
|
-
}).sort('createdAt', 1).run(function(err, comments){
|
170
|
-
res.json(util.scoreComments(comments, req));
|
171
|
-
});
|
172
152
|
});
|
153
|
+
});
|
173
154
|
|
174
|
-
/**
|
175
|
-
* Returns n most recent comments.
|
176
|
-
* Takes two parameters: offset and limit.
|
177
|
-
*
|
178
|
-
* The last comment object returned will contain `total_rows`,
|
179
|
-
* `offset` and `limit` fields. I'd say it's a hack, but at least
|
180
|
-
* it works for now.
|
181
|
-
*/
|
182
|
-
app.get('/comments_recent', util.getCommentReads, function(req, res) {
|
183
|
-
var offset = parseInt(req.query.offset, 10) || 0;
|
184
|
-
var limit = parseInt(req.query.limit, 10) || 100;
|
185
|
-
var filter = {
|
186
|
-
deleted: { '$ne': true },
|
187
|
-
sdk: req.params.sdk,
|
188
|
-
version: req.params.version
|
189
|
-
};
|
190
|
-
|
191
|
-
if (req.query.hideRead && req.commentMeta.reads.length > 0) {
|
192
|
-
filter._id = { $nin: req.commentMeta.reads };
|
193
|
-
}
|
194
155
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
Comment.count(filter).run(function(err, count) {
|
199
|
-
var last = comments[comments.length-1];
|
200
|
-
last.total_rows = count;
|
201
|
-
last.offset = offset;
|
202
|
-
last.limit = limit;
|
203
|
-
res.json(comments);
|
204
|
-
});
|
205
|
-
});
|
206
|
-
});
|
156
|
+
/**
|
157
|
+
* Commenting
|
158
|
+
*/
|
207
159
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
160
|
+
/**
|
161
|
+
* Returns a list of comments for a particular target (eg class, guide, video)
|
162
|
+
*/
|
163
|
+
app.get('/auth/:sdk/:version/comments', util.getCommentReads, function(req, res) {
|
164
|
+
|
165
|
+
if (!req.query.startkey) {
|
166
|
+
res.json({error: 'Invalid request'});
|
167
|
+
return;
|
168
|
+
}
|
169
|
+
|
170
|
+
Comment.find({
|
171
|
+
target: JSON.parse(req.query.startkey),
|
172
|
+
deleted: { '$ne': true },
|
173
|
+
sdk: req.params.sdk,
|
174
|
+
version: req.params.version
|
175
|
+
}).sort('createdAt', 1).run(function(err, comments){
|
176
|
+
res.json(util.scoreComments(comments, req));
|
214
177
|
});
|
178
|
+
});
|
215
179
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
180
|
+
/**
|
181
|
+
* Returns n most recent comments.
|
182
|
+
* Takes two parameters: offset and limit.
|
183
|
+
*
|
184
|
+
* The last comment object returned will contain `total_rows`,
|
185
|
+
* `offset` and `limit` fields. I'd say it's a hack, but at least
|
186
|
+
* it works for now.
|
187
|
+
*/
|
188
|
+
app.get('/auth/:sdk/:version/comments_recent', util.getCommentReads, function(req, res) {
|
189
|
+
var offset = parseInt(req.query.offset, 10) || 0;
|
190
|
+
var limit = parseInt(req.query.limit, 10) || 100;
|
191
|
+
var filter = {
|
192
|
+
deleted: { '$ne': true },
|
193
|
+
sdk: req.params.sdk,
|
194
|
+
version: req.params.version
|
195
|
+
};
|
196
|
+
|
197
|
+
if (req.query.hideRead && req.commentMeta.reads.length > 0) {
|
198
|
+
filter._id = { $nin: req.commentMeta.reads };
|
199
|
+
}
|
200
|
+
|
201
|
+
Comment.find(filter).sort('createdAt', -1).skip(offset).limit(limit).run(function(err, comments) {
|
202
|
+
comments = util.scoreComments(comments, req);
|
203
|
+
// Count all comments, store count to last comment
|
204
|
+
Comment.count(filter).run(function(err, count) {
|
205
|
+
var last = comments[comments.length-1];
|
206
|
+
last.total_rows = count;
|
207
|
+
last.offset = offset;
|
208
|
+
last.limit = limit;
|
209
|
+
res.json(comments);
|
210
|
+
});
|
221
211
|
});
|
212
|
+
});
|
222
213
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
if (target.length === 2) {
|
231
|
-
target.push('');
|
232
|
-
}
|
233
|
-
|
234
|
-
var comment = new Comment({
|
235
|
-
author: req.session.user.username,
|
236
|
-
userId: req.session.user.userid,
|
237
|
-
content: req.body.comment,
|
238
|
-
action: req.body.action,
|
239
|
-
rating: Number(req.body.rating),
|
240
|
-
contentHtml: util.markdown(req.body.comment),
|
241
|
-
downVotes: [],
|
242
|
-
upVotes: [],
|
243
|
-
createdAt: new Date,
|
244
|
-
target: target,
|
245
|
-
emaiHash: crypto.createHash('md5').update(req.session.user.email).digest("hex"),
|
246
|
-
sdk: req.params.sdk,
|
247
|
-
version: req.params.version,
|
248
|
-
moderator: req.session.user.moderator,
|
249
|
-
title: req.body.title,
|
250
|
-
url: req.body.url
|
251
|
-
});
|
214
|
+
/**
|
215
|
+
* Returns number of comments for each class/member,
|
216
|
+
* and a list of classes/members into which the user has subscribed.
|
217
|
+
*/
|
218
|
+
app.get('/auth/:sdk/:version/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) {
|
219
|
+
res.send({ comments: req.commentCounts, subscriptions: req.commentSubscriptions || [] });
|
220
|
+
});
|
252
221
|
|
253
|
-
|
254
|
-
|
222
|
+
/**
|
223
|
+
* Returns an individual comment (used when editing a comment)
|
224
|
+
*/
|
225
|
+
app.get('/auth/:sdk/:version/comments/:commentId', util.findComment, function(req, res) {
|
226
|
+
res.json({ success: true, content: req.comment.content });
|
227
|
+
});
|
255
228
|
|
256
|
-
|
257
|
-
|
229
|
+
/**
|
230
|
+
* Creates a new comment
|
231
|
+
*/
|
232
|
+
app.post('/auth/:sdk/:version/comments', util.requireLoggedInUser, function(req, res) {
|
233
|
+
|
234
|
+
var target = JSON.parse(req.body.target);
|
235
|
+
|
236
|
+
if (target.length === 2) {
|
237
|
+
target.push('');
|
238
|
+
}
|
239
|
+
|
240
|
+
var comment = new Comment({
|
241
|
+
author: req.session.user.username,
|
242
|
+
userId: req.session.user.userid,
|
243
|
+
content: req.body.comment,
|
244
|
+
action: req.body.action,
|
245
|
+
rating: Number(req.body.rating),
|
246
|
+
contentHtml: util.markdown(req.body.comment),
|
247
|
+
downVotes: [],
|
248
|
+
upVotes: [],
|
249
|
+
createdAt: new Date,
|
250
|
+
target: target,
|
251
|
+
emaiHash: crypto.createHash('md5').update(req.session.user.email).digest("hex"),
|
252
|
+
sdk: req.params.sdk,
|
253
|
+
version: req.params.version,
|
254
|
+
moderator: req.session.user.moderator,
|
255
|
+
title: req.body.title,
|
256
|
+
url: req.body.url
|
258
257
|
});
|
259
258
|
|
260
|
-
|
261
|
-
|
262
|
-
*/
|
263
|
-
app.post('/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) {
|
264
|
-
|
265
|
-
var voteDirection,
|
266
|
-
comment = req.comment;
|
259
|
+
comment.save(function(err, response) {
|
260
|
+
res.json({ success: true, id: response._id, action: req.body.action });
|
267
261
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
util.requireOwner(req, res, function() {
|
272
|
-
comment.content = req.body.content;
|
273
|
-
comment.contentHtml = util.markdown(req.body.content);
|
274
|
-
|
275
|
-
comment.updates = comment.updates || [];
|
276
|
-
comment.updates.push({
|
277
|
-
updatedAt: String(new Date()),
|
278
|
-
author: req.session.user.username
|
279
|
-
});
|
262
|
+
util.sendEmailUpdates(comment);
|
263
|
+
});
|
264
|
+
});
|
280
265
|
|
281
|
-
|
282
|
-
|
283
|
-
|
266
|
+
/**
|
267
|
+
* Updates an existing comment (for voting or updating contents)
|
268
|
+
*/
|
269
|
+
app.post('/auth/:sdk/:version/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) {
|
270
|
+
|
271
|
+
var voteDirection,
|
272
|
+
comment = req.comment;
|
273
|
+
|
274
|
+
if (req.body.vote) {
|
275
|
+
util.vote(req, res, comment);
|
276
|
+
} else {
|
277
|
+
util.requireOwner(req, res, function() {
|
278
|
+
comment.content = req.body.content;
|
279
|
+
comment.contentHtml = util.markdown(req.body.content);
|
280
|
+
|
281
|
+
comment.updates = comment.updates || [];
|
282
|
+
comment.updates.push({
|
283
|
+
updatedAt: String(new Date()),
|
284
|
+
author: req.session.user.username
|
284
285
|
});
|
285
|
-
}
|
286
|
-
});
|
287
286
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
app.post('/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) {
|
292
|
-
req.comment.deleted = true;
|
293
|
-
req.comment.save(function(err, response) {
|
294
|
-
res.send({ success: true });
|
287
|
+
comment.save(function(err, response) {
|
288
|
+
res.json({ success: true, content: comment.contentHtml });
|
289
|
+
});
|
295
290
|
});
|
296
|
-
}
|
291
|
+
}
|
292
|
+
});
|
297
293
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
});
|
294
|
+
/**
|
295
|
+
* Deletes a comment
|
296
|
+
*/
|
297
|
+
app.post('/auth/:sdk/:version/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) {
|
298
|
+
req.comment.deleted = true;
|
299
|
+
req.comment.save(function(err, response) {
|
300
|
+
res.send({ success: true });
|
306
301
|
});
|
302
|
+
});
|
307
303
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
});
|
304
|
+
/**
|
305
|
+
* Restores deleted comment
|
306
|
+
*/
|
307
|
+
app.post('/auth/:sdk/:version/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) {
|
308
|
+
req.comment.deleted = false;
|
309
|
+
req.comment.save(function(err, response) {
|
310
|
+
res.send({ success: true, comment: util.scoreComments([req.comment], req)[0] });
|
316
311
|
});
|
312
|
+
});
|
317
313
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
314
|
+
/**
|
315
|
+
* Marks a comment 'read'
|
316
|
+
*/
|
317
|
+
app.post('/auth/:sdk/:version/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) {
|
318
|
+
req.commentMeta.metaType = 'read';
|
319
|
+
req.commentMeta.save(function(err, response) {
|
320
|
+
res.send({ success: true });
|
323
321
|
});
|
322
|
+
});
|
323
|
+
|
324
|
+
/**
|
325
|
+
* Get email subscriptions
|
326
|
+
*/
|
327
|
+
app.get('/auth/:sdk/:version/subscriptions', util.getCommentSubscriptions, function(req, res) {
|
328
|
+
res.json({ subscriptions: req.commentMeta.subscriptions });
|
329
|
+
});
|
324
330
|
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
331
|
+
/**
|
332
|
+
* Subscibe / unsubscribe to a comment thread
|
333
|
+
*/
|
334
|
+
app.post('/auth/:sdk/:version/subscribe', util.requireLoggedInUser, function(req, res) {
|
329
335
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
+
var subscriptionBody = {
|
337
|
+
sdk: req.params.sdk,
|
338
|
+
version: req.params.version,
|
339
|
+
target: JSON.parse(req.body.target),
|
340
|
+
userId: req.session.user.userid
|
341
|
+
};
|
336
342
|
|
337
|
-
|
343
|
+
Subscription.findOne(subscriptionBody, function(err, subscription) {
|
338
344
|
|
339
|
-
|
345
|
+
if (subscription && req.body.subscribed == 'false') {
|
340
346
|
|
341
|
-
|
342
|
-
|
343
|
-
|
347
|
+
subscription.remove(function(err, ok) {
|
348
|
+
res.send({ success: true });
|
349
|
+
});
|
344
350
|
|
345
|
-
|
351
|
+
} else if (!subscription && req.body.subscribed == 'true') {
|
346
352
|
|
347
|
-
|
348
|
-
|
353
|
+
subscription = new Subscription(subscriptionBody);
|
354
|
+
subscription.email = req.session.user.email;
|
349
355
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
});
|
356
|
+
subscription.save(function(err, ok) {
|
357
|
+
res.send({ success: true });
|
358
|
+
});
|
359
|
+
}
|
355
360
|
});
|
356
|
-
|
357
361
|
});
|
358
362
|
|
359
363
|
var port = 3000;
|
@@ -1,6 +1,11 @@
|
|
1
|
+
|
1
2
|
/**
|
2
3
|
* Defines comment schema and connects to database
|
3
4
|
*/
|
5
|
+
|
6
|
+
var mongoose = require('mongoose'),
|
7
|
+
config = require('./config');
|
8
|
+
|
4
9
|
Comment = mongoose.model('Comment', new mongoose.Schema({
|
5
10
|
sdk: String,
|
6
11
|
version: String,
|
@@ -43,4 +48,6 @@ Meta = mongoose.model('Meta', new mongoose.Schema({
|
|
43
48
|
metaType: String
|
44
49
|
}));
|
45
50
|
|
46
|
-
mongoose.connect(config.mongoDb)
|
51
|
+
mongoose.connect(config.mongoDb, function(err, ok) {
|
52
|
+
console.log("Connected to DB")
|
53
|
+
});
|
@@ -4,10 +4,10 @@
|
|
4
4
|
"description": "Commenting backend for JSDuck Documentation",
|
5
5
|
"author": "Nick Poudlen <nick@sencha.com>",
|
6
6
|
"dependencies": {
|
7
|
+
"express": "git://github.com/visionmedia/express.git",
|
8
|
+
"express-namespace": "",
|
7
9
|
"connect": "",
|
8
10
|
"connect-mongo": "",
|
9
|
-
"express": "",
|
10
|
-
"express-namespace": "",
|
11
11
|
"marked": "",
|
12
12
|
"mongoose": "",
|
13
13
|
"mysql": "",
|
@@ -17,4 +17,3 @@
|
|
17
17
|
"nodemailer": ""
|
18
18
|
}
|
19
19
|
}
|
20
|
-
|
@@ -2,7 +2,8 @@
|
|
2
2
|
var marked = require('marked'),
|
3
3
|
_ = require('underscore'),
|
4
4
|
sanitizer = require('sanitizer'),
|
5
|
-
nodemailer = require("nodemailer")
|
5
|
+
nodemailer = require("nodemailer"),
|
6
|
+
mongoose = require('mongoose');
|
6
7
|
|
7
8
|
/**
|
8
9
|
* Converts Markdown-formatted comment text into HTML.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jsduck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.8.
|
4
|
+
version: 3.8.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-04-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rdiscount
|
17
|
-
requirement: &
|
17
|
+
requirement: &9318620 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *9318620
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: json
|
28
|
-
requirement: &
|
28
|
+
requirement: &9318020 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *9318020
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: parallel
|
39
|
-
requirement: &
|
39
|
+
requirement: &9317460 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
version: '0'
|
45
45
|
type: :runtime
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *9317460
|
48
48
|
description: Documentation generator for Sencha JS frameworks
|
49
49
|
email: rene.saarsoo@sencha.com
|
50
50
|
executables:
|
@@ -464,20 +464,12 @@ files:
|
|
464
464
|
- template-min/extjs/resources/themes/images/default/form/text-bg.gif
|
465
465
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-bottom-corners.gif
|
466
466
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-right-sides.gif
|
467
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-bottom-corners.gif
|
468
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-right-sides.gif
|
469
467
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-top-sides.gif
|
470
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-left-sides.gif
|
471
468
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-top-corners.gif
|
472
469
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-left-corners.gif
|
473
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-right-corners.gif
|
474
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-top-corners.gif
|
475
470
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-left-sides.gif
|
476
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-bottom-sides.gif
|
477
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-left-corners.gif
|
478
471
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-right-corners.gif
|
479
472
|
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-bottom-sides.gif
|
480
|
-
- template-min/extjs/resources/themes/images/default/window-header/window-header-default-collapsed-top-sides.gif
|
481
473
|
- template-min/extjs/resources/themes/images/default/tab-bar/scroll-left.gif
|
482
474
|
- template-min/extjs/resources/themes/images/default/tab-bar/tab-bar-default-bg.gif
|
483
475
|
- template-min/extjs/resources/themes/images/default/tab-bar/scroll-right.gif
|