jsduck 3.8.2 → 3.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|