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 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 constants SDK_DIR and OUT_DIR in it."
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 " EXT_DIR='/path/to/ext-4.0.7'"
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 #{EXT_DIR}/resources/themes/images/default #{dir}/extjs/resources/themes/images"
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
- ["#{@out_dir}/index.html"].each do |file|
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 #{@out_dir}/extjs"
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", "#{@ext_dir}/docs/doc-resources",
183
+ "--images", "#{EXT_BUILD}/docs/doc-resources",
188
184
  "--local-storage-db", "ext-4",
189
- "--output", "#{@out_dir}",
190
- "#{@ext_dir}/src",
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 #{@ext_dir} #{@out_dir}/extjs-build"
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 #{@sdk_dir}/touch/build #{@out_dir}/touch"
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}/../sync/docs/config.json"]
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"
@@ -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.2'
6
- s.date = '2012-03-29'
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(:old_cat_format, 'Update categories file to contain just the array inside {"categories": [...]}')
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
 
@@ -34,7 +34,12 @@ module JsDuck
34
34
 
35
35
  # Reads and parses JSON from file
36
36
  def self.read(filename)
37
- self.parse(JsDuck::IO.read(filename))
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
@@ -1,7 +1,7 @@
1
1
  require 'optparse'
2
2
  require 'jsduck/meta_tag_registry'
3
3
  require 'jsduck/logger'
4
- require 'jsduck/io'
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.2"
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
- config = read_json_config(path)
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 = JSON.parse(JsDuck::IO.read(jsb_file))
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
- connect = require('connect'),
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
- var app = express.createServer(
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.cookies = req.cookies || {};
62
- req.cookies['sencha_docs'] = sid;
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
- connect.session({ store: new MongoStore, secret: config.sessionSecret, key: 'sencha_docs' }),
69
-
70
- function(req, res, next) {
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.enable('jsonp callback');
84
+ app.use(express.bodyParser());
85
+ app.use(express.methodOverride());
82
86
 
83
- // All URLs start with /auth
84
- app.namespace('/auth', function(){
87
+ app.enable('jsonp callback');
88
+ });
85
89
 
86
- /**
87
- * Authentication
88
- */
90
+ app.configure('development', function(){
91
+ app.use(express.logger('dev'));
92
+ app.use(express.errorHandler());
93
+ });
89
94
 
90
- app.get('/session', function(req, res) {
91
- var result = req.session && req.session.user && forumUser.clientUser(req.session.user);
92
- res.json(result || false);
93
- });
95
+ /**
96
+ * Authentication
97
+ */
94
98
 
95
- app.post('/login', function(req, res){
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
- forumUser.login(req.body.username, req.body.password, function(err, result) {
104
+ app.post('/auth/login', function(req, res){
98
105
 
99
- if (err) {
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
- req.session = req.session || {};
105
- req.session.user = result;
108
+ if (err) {
109
+ res.json({ success: false, reason: err });
110
+ return;
111
+ }
106
112
 
107
- var response = _.extend(forumUser.clientUser(result), {
108
- sessionID: req.sessionID,
109
- success: true
110
- });
113
+ req.session = req.session || {};
114
+ req.session.user = result;
111
115
 
112
- res.json(response);
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
- * Commenting
132
+ * Handles comment unsubscription requests.
151
133
  */
152
- app.namespace('/auth/:sdk/:version', function(){
134
+ app.get('/auth/unsubscribe/:subscriptionId', function(req, res) {
153
135
 
154
- /**
155
- * Returns a list of comments for a particular target (eg class, guide, video)
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 (!req.query.startkey) {
160
- res.json({error: 'Invalid request'});
161
- return;
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
- Comment.find(filter).sort('createdAt', -1).skip(offset).limit(limit).run(function(err, comments) {
196
- comments = util.scoreComments(comments, req);
197
- // Count all comments, store count to last comment
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
- * Returns number of comments for each class/member,
210
- * and a list of classes/members into which the user has subscribed.
211
- */
212
- app.get('/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) {
213
- res.send({ comments: req.commentCounts, subscriptions: req.commentSubscriptions || [] });
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
- * Returns an individual comment (used when editing a comment)
218
- */
219
- app.get('/comments/:commentId', util.findComment, function(req, res) {
220
- res.json({ success: true, content: req.comment.content });
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
- * Creates a new comment
225
- */
226
- app.post('/comments', util.requireLoggedInUser, function(req, res) {
227
-
228
- var target = JSON.parse(req.body.target);
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
- comment.save(function(err, response) {
254
- res.json({ success: true, id: response._id, action: req.body.action });
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
- util.sendEmailUpdates(comment);
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
- * Updates an existing comment (for voting or updating contents)
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
- if (req.body.vote) {
269
- util.vote(req, res, comment);
270
- } else {
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
- comment.save(function(err, response) {
282
- res.json({ success: true, content: comment.contentHtml });
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
- * Deletes a comment
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
- * Restores deleted comment
300
- */
301
- app.post('/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) {
302
- req.comment.deleted = false;
303
- req.comment.save(function(err, response) {
304
- res.send({ success: true, comment: util.scoreComments([req.comment], req)[0] });
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
- * Marks a comment 'read'
310
- */
311
- app.post('/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) {
312
- req.commentMeta.metaType = 'read';
313
- req.commentMeta.save(function(err, response) {
314
- res.send({ success: true });
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
- * Get email subscriptions
320
- */
321
- app.get('/subscriptions', util.getCommentSubscriptions, function(req, res) {
322
- res.json({ subscriptions: req.commentMeta.subscriptions });
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
- * Subscibe / unsubscribe to a comment thread
327
- */
328
- app.post('/subscribe', util.requireLoggedInUser, function(req, res) {
331
+ /**
332
+ * Subscibe / unsubscribe to a comment thread
333
+ */
334
+ app.post('/auth/:sdk/:version/subscribe', util.requireLoggedInUser, function(req, res) {
329
335
 
330
- var subscriptionBody = {
331
- sdk: req.params.sdk,
332
- version: req.params.version,
333
- target: JSON.parse(req.body.target),
334
- userId: req.session.user.userid
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
- Subscription.findOne(subscriptionBody, function(err, subscription) {
343
+ Subscription.findOne(subscriptionBody, function(err, subscription) {
338
344
 
339
- if (subscription && req.body.subscribed == 'false') {
345
+ if (subscription && req.body.subscribed == 'false') {
340
346
 
341
- subscription.remove(function(err, ok) {
342
- res.send({ success: true });
343
- });
347
+ subscription.remove(function(err, ok) {
348
+ res.send({ success: true });
349
+ });
344
350
 
345
- } else if (!subscription && req.body.subscribed == 'true') {
351
+ } else if (!subscription && req.body.subscribed == 'true') {
346
352
 
347
- subscription = new Subscription(subscriptionBody);
348
- subscription.email = req.session.user.email;
353
+ subscription = new Subscription(subscriptionBody);
354
+ subscription.email = req.session.user.email;
349
355
 
350
- subscription.save(function(err, ok) {
351
- res.send({ success: true });
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.2
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-03-29 00:00:00.000000000 Z
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: &9961600 !ruby/object:Gem::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: *9961600
25
+ version_requirements: *9318620
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: json
28
- requirement: &9961020 !ruby/object:Gem::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: *9961020
36
+ version_requirements: *9318020
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: parallel
39
- requirement: &9960340 !ruby/object:Gem::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: *9960340
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