jsduck 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/COPYING +674 -0
- data/README.md +197 -0
- data/Rakefile +23 -0
- data/bin/jsduck +63 -0
- data/jsduck.gemspec +21 -0
- data/lib/jsduck/aggregator.rb +104 -0
- data/lib/jsduck/app.rb +89 -0
- data/lib/jsduck/cfg_table.rb +21 -0
- data/lib/jsduck/class.rb +116 -0
- data/lib/jsduck/doc_formatter.rb +69 -0
- data/lib/jsduck/doc_parser.rb +277 -0
- data/lib/jsduck/event_table.rb +33 -0
- data/lib/jsduck/lexer.rb +193 -0
- data/lib/jsduck/long_params.rb +31 -0
- data/lib/jsduck/merger.rb +286 -0
- data/lib/jsduck/method_table.rb +45 -0
- data/lib/jsduck/page.rb +56 -0
- data/lib/jsduck/parser.rb +195 -0
- data/lib/jsduck/property_table.rb +21 -0
- data/lib/jsduck/short_params.rb +28 -0
- data/lib/jsduck/table.rb +109 -0
- data/lib/jsduck/tree.rb +104 -0
- data/lib/jsduck/tree_icons.rb +19 -0
- data/template/index.html +45 -0
- data/template/resources/TabCloseMenu.js +150 -0
- data/template/resources/block-bottom.gif +0 -0
- data/template/resources/block-top.gif +0 -0
- data/template/resources/class.gif +0 -0
- data/template/resources/cmp.gif +0 -0
- data/template/resources/collapse-all.gif +0 -0
- data/template/resources/config.gif +0 -0
- data/template/resources/css/ext-all.css +6789 -0
- data/template/resources/css/xtheme-gray.css +1654 -0
- data/template/resources/docs.css +359 -0
- data/template/resources/docs.gif +0 -0
- data/template/resources/docs.js +672 -0
- data/template/resources/event.gif +0 -0
- data/template/resources/expand-all.gif +0 -0
- data/template/resources/expand-bg-over.gif +0 -0
- data/template/resources/expand-bg.gif +0 -0
- data/template/resources/expand-members.gif +0 -0
- data/template/resources/ext-all.js +11 -0
- data/template/resources/ext-base.js +7 -0
- data/template/resources/extanim32.gif +0 -0
- data/template/resources/fav.gif +0 -0
- data/template/resources/favicon.ico +0 -0
- data/template/resources/hd-bg.png +0 -0
- data/template/resources/hide-inherited.gif +0 -0
- data/template/resources/images/default/box/corners-blue.gif +0 -0
- data/template/resources/images/default/box/corners.gif +0 -0
- data/template/resources/images/default/box/l-blue.gif +0 -0
- data/template/resources/images/default/box/l.gif +0 -0
- data/template/resources/images/default/box/r-blue.gif +0 -0
- data/template/resources/images/default/box/r.gif +0 -0
- data/template/resources/images/default/box/tb-blue.gif +0 -0
- data/template/resources/images/default/box/tb.gif +0 -0
- data/template/resources/images/default/button/arrow.gif +0 -0
- data/template/resources/images/default/button/btn.gif +0 -0
- data/template/resources/images/default/button/group-cs.gif +0 -0
- data/template/resources/images/default/button/group-lr.gif +0 -0
- data/template/resources/images/default/button/group-tb.gif +0 -0
- data/template/resources/images/default/button/s-arrow-b-noline.gif +0 -0
- data/template/resources/images/default/button/s-arrow-b.gif +0 -0
- data/template/resources/images/default/button/s-arrow-bo.gif +0 -0
- data/template/resources/images/default/button/s-arrow-noline.gif +0 -0
- data/template/resources/images/default/button/s-arrow-o.gif +0 -0
- data/template/resources/images/default/button/s-arrow.gif +0 -0
- data/template/resources/images/default/dd/drop-add.gif +0 -0
- data/template/resources/images/default/dd/drop-no.gif +0 -0
- data/template/resources/images/default/dd/drop-yes.gif +0 -0
- data/template/resources/images/default/editor/tb-sprite.gif +0 -0
- data/template/resources/images/default/form/checkbox.gif +0 -0
- data/template/resources/images/default/form/clear-trigger.gif +0 -0
- data/template/resources/images/default/form/clear-trigger.psd +0 -0
- data/template/resources/images/default/form/date-trigger.gif +0 -0
- data/template/resources/images/default/form/date-trigger.psd +0 -0
- data/template/resources/images/default/form/error-tip-corners.gif +0 -0
- data/template/resources/images/default/form/exclamation.gif +0 -0
- data/template/resources/images/default/form/radio.gif +0 -0
- data/template/resources/images/default/form/search-trigger.gif +0 -0
- data/template/resources/images/default/form/search-trigger.psd +0 -0
- data/template/resources/images/default/form/text-bg.gif +0 -0
- data/template/resources/images/default/form/trigger-square.gif +0 -0
- data/template/resources/images/default/form/trigger-square.psd +0 -0
- data/template/resources/images/default/form/trigger-tpl.gif +0 -0
- data/template/resources/images/default/form/trigger.gif +0 -0
- data/template/resources/images/default/form/trigger.psd +0 -0
- data/template/resources/images/default/gradient-bg.gif +0 -0
- data/template/resources/images/default/grid/arrow-left-white.gif +0 -0
- data/template/resources/images/default/grid/arrow-right-white.gif +0 -0
- data/template/resources/images/default/grid/col-move-bottom.gif +0 -0
- data/template/resources/images/default/grid/col-move-top.gif +0 -0
- data/template/resources/images/default/grid/columns.gif +0 -0
- data/template/resources/images/default/grid/dirty.gif +0 -0
- data/template/resources/images/default/grid/done.gif +0 -0
- data/template/resources/images/default/grid/drop-no.gif +0 -0
- data/template/resources/images/default/grid/drop-yes.gif +0 -0
- data/template/resources/images/default/grid/footer-bg.gif +0 -0
- data/template/resources/images/default/grid/grid-blue-hd.gif +0 -0
- data/template/resources/images/default/grid/grid-blue-split.gif +0 -0
- data/template/resources/images/default/grid/grid-hrow.gif +0 -0
- data/template/resources/images/default/grid/grid-loading.gif +0 -0
- data/template/resources/images/default/grid/grid-split.gif +0 -0
- data/template/resources/images/default/grid/grid-vista-hd.gif +0 -0
- data/template/resources/images/default/grid/grid3-hd-btn.gif +0 -0
- data/template/resources/images/default/grid/grid3-hrow-over.gif +0 -0
- data/template/resources/images/default/grid/grid3-hrow.gif +0 -0
- data/template/resources/images/default/grid/grid3-special-col-bg.gif +0 -0
- data/template/resources/images/default/grid/grid3-special-col-sel-bg.gif +0 -0
- data/template/resources/images/default/grid/group-by.gif +0 -0
- data/template/resources/images/default/grid/group-collapse.gif +0 -0
- data/template/resources/images/default/grid/group-expand-sprite.gif +0 -0
- data/template/resources/images/default/grid/group-expand.gif +0 -0
- data/template/resources/images/default/grid/hd-pop.gif +0 -0
- data/template/resources/images/default/grid/hmenu-asc.gif +0 -0
- data/template/resources/images/default/grid/hmenu-desc.gif +0 -0
- data/template/resources/images/default/grid/hmenu-lock.gif +0 -0
- data/template/resources/images/default/grid/hmenu-lock.png +0 -0
- data/template/resources/images/default/grid/hmenu-unlock.gif +0 -0
- data/template/resources/images/default/grid/hmenu-unlock.png +0 -0
- data/template/resources/images/default/grid/invalid_line.gif +0 -0
- data/template/resources/images/default/grid/loading.gif +0 -0
- data/template/resources/images/default/grid/mso-hd.gif +0 -0
- data/template/resources/images/default/grid/nowait.gif +0 -0
- data/template/resources/images/default/grid/page-first-disabled.gif +0 -0
- data/template/resources/images/default/grid/page-first.gif +0 -0
- data/template/resources/images/default/grid/page-last-disabled.gif +0 -0
- data/template/resources/images/default/grid/page-last.gif +0 -0
- data/template/resources/images/default/grid/page-next-disabled.gif +0 -0
- data/template/resources/images/default/grid/page-next.gif +0 -0
- data/template/resources/images/default/grid/page-prev-disabled.gif +0 -0
- data/template/resources/images/default/grid/page-prev.gif +0 -0
- data/template/resources/images/default/grid/pick-button.gif +0 -0
- data/template/resources/images/default/grid/refresh.gif +0 -0
- data/template/resources/images/default/grid/row-check-sprite.gif +0 -0
- data/template/resources/images/default/grid/row-expand-sprite.gif +0 -0
- data/template/resources/images/default/grid/row-over.gif +0 -0
- data/template/resources/images/default/grid/row-sel.gif +0 -0
- data/template/resources/images/default/grid/sort-hd.gif +0 -0
- data/template/resources/images/default/grid/sort_asc.gif +0 -0
- data/template/resources/images/default/grid/sort_desc.gif +0 -0
- data/template/resources/images/default/grid/wait.gif +0 -0
- data/template/resources/images/default/layout/collapse.gif +0 -0
- data/template/resources/images/default/layout/expand.gif +0 -0
- data/template/resources/images/default/layout/gradient-bg.gif +0 -0
- data/template/resources/images/default/layout/mini-bottom.gif +0 -0
- data/template/resources/images/default/layout/mini-left.gif +0 -0
- data/template/resources/images/default/layout/mini-right.gif +0 -0
- data/template/resources/images/default/layout/mini-top.gif +0 -0
- data/template/resources/images/default/layout/ns-collapse.gif +0 -0
- data/template/resources/images/default/layout/ns-expand.gif +0 -0
- data/template/resources/images/default/layout/panel-close.gif +0 -0
- data/template/resources/images/default/layout/panel-title-bg.gif +0 -0
- data/template/resources/images/default/layout/panel-title-light-bg.gif +0 -0
- data/template/resources/images/default/layout/stick.gif +0 -0
- data/template/resources/images/default/layout/stuck.gif +0 -0
- data/template/resources/images/default/layout/tab-close-on.gif +0 -0
- data/template/resources/images/default/layout/tab-close.gif +0 -0
- data/template/resources/images/default/menu/checked.gif +0 -0
- data/template/resources/images/default/menu/group-checked.gif +0 -0
- data/template/resources/images/default/menu/item-over.gif +0 -0
- data/template/resources/images/default/menu/menu-parent.gif +0 -0
- data/template/resources/images/default/menu/menu.gif +0 -0
- data/template/resources/images/default/menu/unchecked.gif +0 -0
- data/template/resources/images/default/panel/corners-sprite.gif +0 -0
- data/template/resources/images/default/panel/left-right.gif +0 -0
- data/template/resources/images/default/panel/light-hd.gif +0 -0
- data/template/resources/images/default/panel/tool-sprite-tpl.gif +0 -0
- data/template/resources/images/default/panel/tool-sprites.gif +0 -0
- data/template/resources/images/default/panel/tools-sprites-trans.gif +0 -0
- data/template/resources/images/default/panel/top-bottom.gif +0 -0
- data/template/resources/images/default/panel/top-bottom.png +0 -0
- data/template/resources/images/default/panel/white-corners-sprite.gif +0 -0
- data/template/resources/images/default/panel/white-left-right.gif +0 -0
- data/template/resources/images/default/panel/white-top-bottom.gif +0 -0
- data/template/resources/images/default/progress/progress-bg.gif +0 -0
- data/template/resources/images/default/qtip/bg.gif +0 -0
- data/template/resources/images/default/qtip/close.gif +0 -0
- data/template/resources/images/default/qtip/tip-anchor-sprite.gif +0 -0
- data/template/resources/images/default/qtip/tip-sprite.gif +0 -0
- data/template/resources/images/default/s.gif +0 -0
- data/template/resources/images/default/shadow-c.png +0 -0
- data/template/resources/images/default/shadow-lr.png +0 -0
- data/template/resources/images/default/shadow.png +0 -0
- data/template/resources/images/default/shared/blue-loading.gif +0 -0
- data/template/resources/images/default/shared/calendar.gif +0 -0
- data/template/resources/images/default/shared/glass-bg.gif +0 -0
- data/template/resources/images/default/shared/hd-sprite.gif +0 -0
- data/template/resources/images/default/shared/large-loading.gif +0 -0
- data/template/resources/images/default/shared/left-btn.gif +0 -0
- data/template/resources/images/default/shared/loading-balls.gif +0 -0
- data/template/resources/images/default/shared/right-btn.gif +0 -0
- data/template/resources/images/default/shared/warning.gif +0 -0
- data/template/resources/images/default/sizer/e-handle-dark.gif +0 -0
- data/template/resources/images/default/sizer/e-handle.gif +0 -0
- data/template/resources/images/default/sizer/ne-handle-dark.gif +0 -0
- data/template/resources/images/default/sizer/ne-handle.gif +0 -0
- data/template/resources/images/default/sizer/nw-handle-dark.gif +0 -0
- data/template/resources/images/default/sizer/nw-handle.gif +0 -0
- data/template/resources/images/default/sizer/s-handle-dark.gif +0 -0
- data/template/resources/images/default/sizer/s-handle.gif +0 -0
- data/template/resources/images/default/sizer/se-handle-dark.gif +0 -0
- data/template/resources/images/default/sizer/se-handle.gif +0 -0
- data/template/resources/images/default/sizer/square.gif +0 -0
- data/template/resources/images/default/sizer/sw-handle-dark.gif +0 -0
- data/template/resources/images/default/sizer/sw-handle.gif +0 -0
- data/template/resources/images/default/slider/slider-bg.png +0 -0
- data/template/resources/images/default/slider/slider-thumb.png +0 -0
- data/template/resources/images/default/slider/slider-v-bg.png +0 -0
- data/template/resources/images/default/slider/slider-v-thumb.png +0 -0
- data/template/resources/images/default/tabs/scroll-left.gif +0 -0
- data/template/resources/images/default/tabs/scroll-right.gif +0 -0
- data/template/resources/images/default/tabs/scroller-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-btm-inactive-left-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-btm-inactive-right-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-btm-left-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-btm-over-left-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-btm-over-right-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-btm-right-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-close.gif +0 -0
- data/template/resources/images/default/tabs/tab-strip-bg.gif +0 -0
- data/template/resources/images/default/tabs/tab-strip-bg.png +0 -0
- data/template/resources/images/default/tabs/tab-strip-btm-bg.gif +0 -0
- data/template/resources/images/default/tabs/tabs-sprite.gif +0 -0
- data/template/resources/images/default/toolbar/bg.gif +0 -0
- data/template/resources/images/default/toolbar/btn-arrow-light.gif +0 -0
- data/template/resources/images/default/toolbar/btn-arrow.gif +0 -0
- data/template/resources/images/default/toolbar/btn-over-bg.gif +0 -0
- data/template/resources/images/default/toolbar/gray-bg.gif +0 -0
- data/template/resources/images/default/toolbar/more.gif +0 -0
- data/template/resources/images/default/toolbar/tb-bg.gif +0 -0
- data/template/resources/images/default/toolbar/tb-btn-sprite.gif +0 -0
- data/template/resources/images/default/toolbar/tb-xl-btn-sprite.gif +0 -0
- data/template/resources/images/default/toolbar/tb-xl-sep.gif +0 -0
- data/template/resources/images/default/tree/arrows.gif +0 -0
- data/template/resources/images/default/tree/drop-add.gif +0 -0
- data/template/resources/images/default/tree/drop-between.gif +0 -0
- data/template/resources/images/default/tree/drop-no.gif +0 -0
- data/template/resources/images/default/tree/drop-over.gif +0 -0
- data/template/resources/images/default/tree/drop-under.gif +0 -0
- data/template/resources/images/default/tree/drop-yes.gif +0 -0
- data/template/resources/images/default/tree/elbow-end-minus-nl.gif +0 -0
- data/template/resources/images/default/tree/elbow-end-minus.gif +0 -0
- data/template/resources/images/default/tree/elbow-end-plus-nl.gif +0 -0
- data/template/resources/images/default/tree/elbow-end-plus.gif +0 -0
- data/template/resources/images/default/tree/elbow-end.gif +0 -0
- data/template/resources/images/default/tree/elbow-line.gif +0 -0
- data/template/resources/images/default/tree/elbow-minus-nl.gif +0 -0
- data/template/resources/images/default/tree/elbow-minus.gif +0 -0
- data/template/resources/images/default/tree/elbow-plus-nl.gif +0 -0
- data/template/resources/images/default/tree/elbow-plus.gif +0 -0
- data/template/resources/images/default/tree/elbow.gif +0 -0
- data/template/resources/images/default/tree/folder-open.gif +0 -0
- data/template/resources/images/default/tree/folder.gif +0 -0
- data/template/resources/images/default/tree/leaf.gif +0 -0
- data/template/resources/images/default/tree/loading.gif +0 -0
- data/template/resources/images/default/tree/s.gif +0 -0
- data/template/resources/images/default/window/icon-error.gif +0 -0
- data/template/resources/images/default/window/icon-info.gif +0 -0
- data/template/resources/images/default/window/icon-question.gif +0 -0
- data/template/resources/images/default/window/icon-warning.gif +0 -0
- data/template/resources/images/default/window/left-corners.png +0 -0
- data/template/resources/images/default/window/left-corners.psd +0 -0
- data/template/resources/images/default/window/left-right.png +0 -0
- data/template/resources/images/default/window/left-right.psd +0 -0
- data/template/resources/images/default/window/right-corners.png +0 -0
- data/template/resources/images/default/window/right-corners.psd +0 -0
- data/template/resources/images/default/window/top-bottom.png +0 -0
- data/template/resources/images/default/window/top-bottom.psd +0 -0
- data/template/resources/images/gray/button/btn-arrow.gif +0 -0
- data/template/resources/images/gray/button/btn-sprite.gif +0 -0
- data/template/resources/images/gray/button/btn.gif +0 -0
- data/template/resources/images/gray/button/group-cs.gif +0 -0
- data/template/resources/images/gray/button/group-lr.gif +0 -0
- data/template/resources/images/gray/button/group-tb.gif +0 -0
- data/template/resources/images/gray/button/s-arrow-bo.gif +0 -0
- data/template/resources/images/gray/button/s-arrow-o.gif +0 -0
- data/template/resources/images/gray/form/clear-trigger.gif +0 -0
- data/template/resources/images/gray/form/date-trigger.gif +0 -0
- data/template/resources/images/gray/form/search-trigger.gif +0 -0
- data/template/resources/images/gray/form/trigger-square.gif +0 -0
- data/template/resources/images/gray/form/trigger.gif +0 -0
- data/template/resources/images/gray/gradient-bg.gif +0 -0
- data/template/resources/images/gray/grid/col-move-bottom.gif +0 -0
- data/template/resources/images/gray/grid/col-move-top.gif +0 -0
- data/template/resources/images/gray/grid/grid3-hd-btn.gif +0 -0
- data/template/resources/images/gray/grid/grid3-hrow-over.gif +0 -0
- data/template/resources/images/gray/grid/grid3-hrow-over2.gif +0 -0
- data/template/resources/images/gray/grid/grid3-hrow.gif +0 -0
- data/template/resources/images/gray/grid/grid3-hrow2.gif +0 -0
- data/template/resources/images/gray/grid/grid3-special-col-bg.gif +0 -0
- data/template/resources/images/gray/grid/grid3-special-col-bg2.gif +0 -0
- data/template/resources/images/gray/grid/grid3-special-col-sel-bg.gif +0 -0
- data/template/resources/images/gray/grid/group-collapse.gif +0 -0
- data/template/resources/images/gray/grid/group-expand-sprite.gif +0 -0
- data/template/resources/images/gray/grid/group-expand.gif +0 -0
- data/template/resources/images/gray/grid/page-first.gif +0 -0
- data/template/resources/images/gray/grid/page-last.gif +0 -0
- data/template/resources/images/gray/grid/page-next.gif +0 -0
- data/template/resources/images/gray/grid/page-prev.gif +0 -0
- data/template/resources/images/gray/grid/refresh.gif +0 -0
- data/template/resources/images/gray/grid/row-expand-sprite.gif +0 -0
- data/template/resources/images/gray/grid/sort_asc.gif +0 -0
- data/template/resources/images/gray/grid/sort_desc.gif +0 -0
- data/template/resources/images/gray/menu/group-checked.gif +0 -0
- data/template/resources/images/gray/menu/item-over-disabled.gif +0 -0
- data/template/resources/images/gray/menu/item-over.gif +0 -0
- data/template/resources/images/gray/menu/menu-parent.gif +0 -0
- data/template/resources/images/gray/panel/corners-sprite.gif +0 -0
- data/template/resources/images/gray/panel/left-right.gif +0 -0
- data/template/resources/images/gray/panel/light-hd.gif +0 -0
- data/template/resources/images/gray/panel/tool-sprite-tpl.gif +0 -0
- data/template/resources/images/gray/panel/tool-sprites.gif +0 -0
- data/template/resources/images/gray/panel/tools-sprites-trans.gif +0 -0
- data/template/resources/images/gray/panel/top-bottom.gif +0 -0
- data/template/resources/images/gray/panel/top-bottom.png +0 -0
- data/template/resources/images/gray/panel/white-corners-sprite.gif +0 -0
- data/template/resources/images/gray/panel/white-left-right.gif +0 -0
- data/template/resources/images/gray/panel/white-top-bottom.gif +0 -0
- data/template/resources/images/gray/progress/progress-bg.gif +0 -0
- data/template/resources/images/gray/qtip/bg.gif +0 -0
- data/template/resources/images/gray/qtip/close.gif +0 -0
- data/template/resources/images/gray/qtip/tip-anchor-sprite.gif +0 -0
- data/template/resources/images/gray/qtip/tip-sprite.gif +0 -0
- data/template/resources/images/gray/s.gif +0 -0
- data/template/resources/images/gray/shared/hd-sprite.gif +0 -0
- data/template/resources/images/gray/shared/left-btn.gif +0 -0
- data/template/resources/images/gray/shared/right-btn.gif +0 -0
- data/template/resources/images/gray/sizer/e-handle.gif +0 -0
- data/template/resources/images/gray/sizer/ne-handle.gif +0 -0
- data/template/resources/images/gray/sizer/nw-handle.gif +0 -0
- data/template/resources/images/gray/sizer/s-handle.gif +0 -0
- data/template/resources/images/gray/sizer/se-handle.gif +0 -0
- data/template/resources/images/gray/sizer/square.gif +0 -0
- data/template/resources/images/gray/sizer/sw-handle.gif +0 -0
- data/template/resources/images/gray/slider/slider-thumb.png +0 -0
- data/template/resources/images/gray/slider/slider-v-thumb.png +0 -0
- data/template/resources/images/gray/tabs/scroll-left.gif +0 -0
- data/template/resources/images/gray/tabs/scroll-right.gif +0 -0
- data/template/resources/images/gray/tabs/scroller-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-btm-inactive-left-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-btm-inactive-right-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-btm-left-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-btm-over-left-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-btm-over-right-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-btm-right-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-close.gif +0 -0
- data/template/resources/images/gray/tabs/tab-strip-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tab-strip-bg.png +0 -0
- data/template/resources/images/gray/tabs/tab-strip-btm-bg.gif +0 -0
- data/template/resources/images/gray/tabs/tabs-sprite.gif +0 -0
- data/template/resources/images/gray/toolbar/bg.gif +0 -0
- data/template/resources/images/gray/toolbar/btn-arrow-light.gif +0 -0
- data/template/resources/images/gray/toolbar/btn-arrow.gif +0 -0
- data/template/resources/images/gray/toolbar/btn-over-bg.gif +0 -0
- data/template/resources/images/gray/toolbar/gray-bg.gif +0 -0
- data/template/resources/images/gray/toolbar/more.gif +0 -0
- data/template/resources/images/gray/toolbar/tb-bg.gif +0 -0
- data/template/resources/images/gray/toolbar/tb-btn-sprite.gif +0 -0
- data/template/resources/images/gray/tree/arrows.gif +0 -0
- data/template/resources/images/gray/tree/elbow-end-minus-nl.gif +0 -0
- data/template/resources/images/gray/tree/elbow-end-minus.gif +0 -0
- data/template/resources/images/gray/tree/elbow-end-plus-nl.gif +0 -0
- data/template/resources/images/gray/tree/elbow-end-plus.gif +0 -0
- data/template/resources/images/gray/window/icon-error.gif +0 -0
- data/template/resources/images/gray/window/icon-info.gif +0 -0
- data/template/resources/images/gray/window/icon-question.gif +0 -0
- data/template/resources/images/gray/window/icon-warning.gif +0 -0
- data/template/resources/images/gray/window/left-corners.png +0 -0
- data/template/resources/images/gray/window/left-corners.pspimage +0 -0
- data/template/resources/images/gray/window/left-right.png +0 -0
- data/template/resources/images/gray/window/right-corners.png +0 -0
- data/template/resources/images/gray/window/top-bottom.png +0 -0
- data/template/resources/inherited.gif +0 -0
- data/template/resources/member-collapsed.gif +0 -0
- data/template/resources/member-expanded.gif +0 -0
- data/template/resources/member-hover.gif +0 -0
- data/template/resources/method.gif +0 -0
- data/template/resources/pkg-closed.gif +0 -0
- data/template/resources/pkg-open.gif +0 -0
- data/template/resources/pkg.gif +0 -0
- data/template/resources/prop.gif +0 -0
- data/template/resources/s.gif +0 -0
- data/template/resources/static.gif +0 -0
- data/template/resources/style.css +302 -0
- data/template/welcome.html +45 -0
- metadata +481 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'jsduck/table'
|
2
|
+
require 'jsduck/short_params'
|
3
|
+
require 'jsduck/long_params'
|
4
|
+
|
5
|
+
module JsDuck
|
6
|
+
|
7
|
+
class EventTable < Table
|
8
|
+
def initialize(cls)
|
9
|
+
super(cls)
|
10
|
+
@type = :event
|
11
|
+
@id = @cls.full_name + "-events"
|
12
|
+
@title = "Public Events"
|
13
|
+
@column_title = "Event"
|
14
|
+
@row_class = "method-row"
|
15
|
+
@short_params = ShortParams.new
|
16
|
+
@long_params = LongParams.new(@cls)
|
17
|
+
end
|
18
|
+
|
19
|
+
def signature_suffix(item)
|
20
|
+
" : " + @short_params.render(item[:params])
|
21
|
+
end
|
22
|
+
|
23
|
+
def extra_doc(item)
|
24
|
+
[
|
25
|
+
"<div class='mdetail-params'>",
|
26
|
+
"<strong style='font-weight: normal;'>Listeners will be called with the following arguments:</strong>",
|
27
|
+
@long_params.render(item[:params]),
|
28
|
+
"</div>"
|
29
|
+
].join("\n")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/jsduck/lexer.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
|
5
|
+
# Tokenizes JavaScript code into lexical tokens.
|
6
|
+
#
|
7
|
+
# Each token has a type and value.
|
8
|
+
# Types and possible values for them are as follows:
|
9
|
+
#
|
10
|
+
# - :number -- 25
|
11
|
+
# - :string -- "Hello world"
|
12
|
+
# - :keyword -- "typeof"
|
13
|
+
# - :ident -- "foo"
|
14
|
+
# - :regex -- "/abc/i"
|
15
|
+
# - :operator -- "+"
|
16
|
+
# - :doc_comment -- "/** My comment */"
|
17
|
+
#
|
18
|
+
# Notice that doc-comments are recognized as tokens while normal
|
19
|
+
# comments are ignored just as whitespace.
|
20
|
+
#
|
21
|
+
class Lexer
|
22
|
+
def initialize(input)
|
23
|
+
@input = StringScanner.new(input)
|
24
|
+
tokenize
|
25
|
+
end
|
26
|
+
|
27
|
+
# Tests if given pattern matches the tokens that follow at current
|
28
|
+
# position.
|
29
|
+
#
|
30
|
+
# Takes list of strings and symbols. Symbols are compared to
|
31
|
+
# token type, while strings to token value. For example:
|
32
|
+
#
|
33
|
+
# look(:ident, "=", :regex)
|
34
|
+
#
|
35
|
+
def look(*tokens)
|
36
|
+
i = 0
|
37
|
+
tokens.all? do |t|
|
38
|
+
tok = @tokens[i]
|
39
|
+
i += 1
|
40
|
+
return false if tok == nil
|
41
|
+
if t.instance_of?(Symbol) then
|
42
|
+
tok[:type] == t
|
43
|
+
else
|
44
|
+
tok[:value] == t
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the value of next token, moving the current token cursor
|
50
|
+
# also to next token.
|
51
|
+
#
|
52
|
+
# When full=true, returns full token as hash like so:
|
53
|
+
#
|
54
|
+
# {:type => :ident, :value => "foo"}
|
55
|
+
#
|
56
|
+
def next(full=false)
|
57
|
+
tok = @tokens.shift
|
58
|
+
full ? tok : tok[:value]
|
59
|
+
end
|
60
|
+
|
61
|
+
# True when no more tokens.
|
62
|
+
def empty?
|
63
|
+
@tokens.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Goes through the whole input and tokenizes it
|
67
|
+
def tokenize
|
68
|
+
@tokens = []
|
69
|
+
while !@input.eos? do
|
70
|
+
skip_white_and_comments
|
71
|
+
if @input.check(/[0-9]+/) then
|
72
|
+
@tokens << {
|
73
|
+
:type => :number,
|
74
|
+
:value => eval(@input.scan(/[0-9]+(\.[0-9]*)?/))
|
75
|
+
}
|
76
|
+
elsif @input.check(/\w+/) then
|
77
|
+
value = @input.scan(/\w+/)
|
78
|
+
@tokens << {
|
79
|
+
:type => KEYWORDS[value] ? :keyword : :ident,
|
80
|
+
:value => value
|
81
|
+
}
|
82
|
+
elsif @input.check(/\/\*\*/) then
|
83
|
+
@tokens << {
|
84
|
+
:type => :doc_comment,
|
85
|
+
:value => @input.scan_until(/\*\/|\Z/)
|
86
|
+
}
|
87
|
+
elsif @input.check(/"/) then
|
88
|
+
@tokens << {
|
89
|
+
:type => :string,
|
90
|
+
:value => eval(@input.scan(/"([^"\\]|\\.)*"/))
|
91
|
+
}
|
92
|
+
elsif @input.check(/'/) then
|
93
|
+
@tokens << {
|
94
|
+
:type => :string,
|
95
|
+
:value => eval(@input.scan(/'([^'\\]|\\.)*'/))
|
96
|
+
}
|
97
|
+
elsif @input.check(/\//) then
|
98
|
+
if regex? then
|
99
|
+
@tokens << {
|
100
|
+
:type => :regex,
|
101
|
+
:value => @input.scan(/\/([^\/\\]|\\.)*\/[gim]*/)
|
102
|
+
}
|
103
|
+
else
|
104
|
+
@tokens << {
|
105
|
+
:type => :operator,
|
106
|
+
:value => @input.scan(/\//)
|
107
|
+
}
|
108
|
+
end
|
109
|
+
elsif @input.check(/./) then
|
110
|
+
@tokens << {
|
111
|
+
:type => :operator,
|
112
|
+
:value => @input.scan(/./)
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# A slash "/" is a division operator if it follows:
|
119
|
+
# - identifier
|
120
|
+
# - the "this" keyword
|
121
|
+
# - number
|
122
|
+
# - closing bracket )
|
123
|
+
# - closing square-bracket ]
|
124
|
+
# Otherwise it's a beginning of regex
|
125
|
+
def regex?
|
126
|
+
if @tokens.last then
|
127
|
+
type = @tokens.last[:type]
|
128
|
+
value = @tokens.last[:value]
|
129
|
+
if type == :ident || type == :number
|
130
|
+
return false
|
131
|
+
elsif type == :keyword && value == "this"
|
132
|
+
return false
|
133
|
+
elsif type == :operator && (value == ")" || value == "]")
|
134
|
+
return false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
return true
|
138
|
+
end
|
139
|
+
|
140
|
+
def skip_white_and_comments
|
141
|
+
skip_white
|
142
|
+
while multiline_comment? || line_comment? do
|
143
|
+
if multiline_comment? then
|
144
|
+
@input.scan_until(/\*\/|\Z/)
|
145
|
+
elsif line_comment? then
|
146
|
+
@input.scan_until(/\n|\Z/)
|
147
|
+
end
|
148
|
+
skip_white
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def multiline_comment?
|
153
|
+
@input.check(/\/\*[^*]/)
|
154
|
+
end
|
155
|
+
|
156
|
+
def line_comment?
|
157
|
+
@input.check(/\/\//)
|
158
|
+
end
|
159
|
+
|
160
|
+
def skip_white
|
161
|
+
@input.scan(/\s+/)
|
162
|
+
end
|
163
|
+
|
164
|
+
KEYWORDS = {
|
165
|
+
"break" => true,
|
166
|
+
"case" => true,
|
167
|
+
"catch" => true,
|
168
|
+
"continue" => true,
|
169
|
+
"default" => true,
|
170
|
+
"delete" => true,
|
171
|
+
"do" => true,
|
172
|
+
"else" => true,
|
173
|
+
"finally" => true,
|
174
|
+
"for" => true,
|
175
|
+
"function" => true,
|
176
|
+
"if" => true,
|
177
|
+
"in" => true,
|
178
|
+
"instanceof" => true,
|
179
|
+
"new" => true,
|
180
|
+
"return" => true,
|
181
|
+
"switch" => true,
|
182
|
+
"this" => true,
|
183
|
+
"throw" => true,
|
184
|
+
"try" => true,
|
185
|
+
"typeof" => true,
|
186
|
+
"var" => true,
|
187
|
+
"void" => true,
|
188
|
+
"while" => true,
|
189
|
+
"with" => true,
|
190
|
+
}
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "jsduck/doc_formatter"
|
2
|
+
|
3
|
+
module JsDuck
|
4
|
+
|
5
|
+
# Renders method/event parameters list in long form
|
6
|
+
# for use in documentation body.
|
7
|
+
class LongParams
|
8
|
+
def initialize(cls)
|
9
|
+
@formatter = DocFormatter.new(cls.full_name)
|
10
|
+
end
|
11
|
+
|
12
|
+
def render(params)
|
13
|
+
if params.length > 0
|
14
|
+
"<ul>" + params.collect {|p| render_single(p) }.join("") + "</ul>"
|
15
|
+
else
|
16
|
+
"<ul><li>None.</li></ul>"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_single(param)
|
21
|
+
doc = @formatter.format(param[:doc])
|
22
|
+
return [
|
23
|
+
"<li>",
|
24
|
+
"<code>#{param[:name]}</code> : #{param[:type]}",
|
25
|
+
"<div class='sub-desc'>#{doc}</div>",
|
26
|
+
"</li>",
|
27
|
+
].join("")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,286 @@
|
|
1
|
+
module JsDuck
|
2
|
+
|
3
|
+
# Takes data from doc-comment and code that follows it and combines
|
4
|
+
# these to pieces of information into one. The code comes from
|
5
|
+
# JsDuck::Parser and doc-comment from JsDuck::DocParser.
|
6
|
+
#
|
7
|
+
# The main method merge() produces a hash as a result.
|
8
|
+
class Merger
|
9
|
+
def merge(docs, code)
|
10
|
+
case detect_doc_type(docs, code)
|
11
|
+
when :class
|
12
|
+
create_class(docs, code)
|
13
|
+
when :event
|
14
|
+
create_event(docs, code)
|
15
|
+
when :method
|
16
|
+
create_method(docs, code)
|
17
|
+
when :cfg
|
18
|
+
create_cfg(docs, code)
|
19
|
+
when :property
|
20
|
+
create_property(docs, code)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Detects whether the doc-comment is for class, cfg, event, method or property.
|
25
|
+
def detect_doc_type(docs, code)
|
26
|
+
doc_map = build_doc_map(docs)
|
27
|
+
|
28
|
+
if doc_map[:class]
|
29
|
+
:class
|
30
|
+
elsif doc_map[:event]
|
31
|
+
:event
|
32
|
+
elsif doc_map[:method]
|
33
|
+
:method
|
34
|
+
elsif doc_map[:property] || doc_map[:type]
|
35
|
+
:property
|
36
|
+
elsif code[:type] == :ext_extend
|
37
|
+
:class
|
38
|
+
elsif code[:type] == :assignment && class_name?(*code[:left])
|
39
|
+
:class
|
40
|
+
elsif code[:type] == :function && class_name?(code[:name])
|
41
|
+
:class
|
42
|
+
elsif doc_map[:cfg]
|
43
|
+
:cfg
|
44
|
+
elsif code[:type] == :function
|
45
|
+
:method
|
46
|
+
elsif code[:type] == :assignment && code[:right] && code[:right][:type] == :function
|
47
|
+
:method
|
48
|
+
else
|
49
|
+
:property
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Class name begins with upcase char
|
54
|
+
def class_name?(*name_chain)
|
55
|
+
return name_chain.last =~ /\A[A-Z]/
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_class(docs, code)
|
59
|
+
groups = group_class_docs(docs)
|
60
|
+
result = create_bare_class(groups[:class], code)
|
61
|
+
result[:cfg] = groups[:cfg].map { |tags| create_cfg(tags, {}, result[:name]) }
|
62
|
+
result[:method] = []
|
63
|
+
if groups[:constructor].length > 0
|
64
|
+
constr = create_method(groups[:constructor], {})
|
65
|
+
constr[:member] = result[:name]
|
66
|
+
result[:method] << constr
|
67
|
+
end
|
68
|
+
result[:property] = []
|
69
|
+
result[:event] = []
|
70
|
+
result
|
71
|
+
end
|
72
|
+
|
73
|
+
# Gathers all tags until first @cfg or @constructor into the first
|
74
|
+
# bare :class group. We have a special case for @xtype which in
|
75
|
+
# ExtJS comments often appears after @constructor - so we
|
76
|
+
# explicitly place it into :class group.
|
77
|
+
#
|
78
|
+
# Then gathers each @cfg and tags following it into :cfg group, so
|
79
|
+
# that it becomes array of arrays of tags. This is to allow some
|
80
|
+
# configs to be marked with @private or whatever else.
|
81
|
+
#
|
82
|
+
# Finally gathers tags after @constructor into its group.
|
83
|
+
def group_class_docs(docs)
|
84
|
+
groups = {:class => [], :cfg => [], :constructor => []}
|
85
|
+
group_name = :class
|
86
|
+
docs.each do |tag|
|
87
|
+
if tag[:tagname] == :cfg || tag[:tagname] == :constructor
|
88
|
+
group_name = tag[:tagname]
|
89
|
+
if tag[:tagname] == :cfg
|
90
|
+
groups[:cfg] << []
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
if tag[:tagname] == :xtype
|
95
|
+
groups[:class] << tag
|
96
|
+
elsif group_name == :cfg
|
97
|
+
groups[:cfg].last << tag
|
98
|
+
else
|
99
|
+
groups[group_name] << tag
|
100
|
+
end
|
101
|
+
end
|
102
|
+
groups
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_bare_class(docs, code)
|
106
|
+
doc_map = build_doc_map(docs)
|
107
|
+
return {
|
108
|
+
:tagname => :class,
|
109
|
+
:name => detect_name(:class, doc_map, code, :full_name),
|
110
|
+
:doc => detect_doc(docs),
|
111
|
+
:extends => detect_extends(doc_map, code),
|
112
|
+
:xtype => detect_xtype(doc_map),
|
113
|
+
:singleton => !!doc_map[:singleton],
|
114
|
+
:private => !!doc_map[:private],
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def create_method(docs, code)
|
119
|
+
doc_map = build_doc_map(docs)
|
120
|
+
return {
|
121
|
+
:tagname => :method,
|
122
|
+
:name => detect_name(:method, doc_map, code),
|
123
|
+
:member => detect_member(doc_map),
|
124
|
+
:doc => detect_doc(docs),
|
125
|
+
:params => detect_params(docs, code),
|
126
|
+
:return => detect_return(doc_map),
|
127
|
+
:private => !!doc_map[:private],
|
128
|
+
:static => !!doc_map[:static],
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_event(docs, code)
|
133
|
+
doc_map = build_doc_map(docs)
|
134
|
+
return {
|
135
|
+
:tagname => :event,
|
136
|
+
:name => detect_name(:event, doc_map, code),
|
137
|
+
:member => detect_member(doc_map),
|
138
|
+
:doc => detect_doc(docs),
|
139
|
+
:params => detect_params(docs, code),
|
140
|
+
:private => !!doc_map[:private],
|
141
|
+
}
|
142
|
+
end
|
143
|
+
|
144
|
+
def create_cfg(docs, code, member = nil)
|
145
|
+
doc_map = build_doc_map(docs)
|
146
|
+
return {
|
147
|
+
:tagname => :cfg,
|
148
|
+
:name => detect_name(:cfg, doc_map, code),
|
149
|
+
:member => detect_member(doc_map) || member,
|
150
|
+
:type => detect_type(:cfg, doc_map, code),
|
151
|
+
:doc => detect_doc(docs),
|
152
|
+
:private => !!doc_map[:private],
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
def create_property(docs, code)
|
157
|
+
doc_map = build_doc_map(docs)
|
158
|
+
return {
|
159
|
+
:tagname => :property,
|
160
|
+
:name => detect_name(:property, doc_map, code),
|
161
|
+
:member => detect_member(doc_map),
|
162
|
+
:type => detect_type(:property, doc_map, code),
|
163
|
+
:doc => detect_doc(docs),
|
164
|
+
:private => !!doc_map[:private],
|
165
|
+
:static => !!doc_map[:static],
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
def detect_name(tagname, doc_map, code, name_type = :last_name)
|
170
|
+
main_tag = doc_map[tagname] ? doc_map[tagname].first : {}
|
171
|
+
if main_tag[:name]
|
172
|
+
main_tag[:name]
|
173
|
+
elsif doc_map[:constructor]
|
174
|
+
"constructor"
|
175
|
+
elsif code[:type] == :function
|
176
|
+
code[:name]
|
177
|
+
elsif code[:type] == :assignment
|
178
|
+
name_type == :full_name ? code[:left].join(".") : code[:left].last
|
179
|
+
else
|
180
|
+
""
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def detect_member(doc_map)
|
185
|
+
if doc_map[:member]
|
186
|
+
doc_map[:member].first[:member]
|
187
|
+
else
|
188
|
+
nil
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def detect_type(tagname, doc_map, code)
|
193
|
+
main_tag = doc_map[tagname] ? doc_map[tagname].first : {}
|
194
|
+
if main_tag[:type]
|
195
|
+
main_tag[:type]
|
196
|
+
elsif doc_map[:type]
|
197
|
+
doc_map[:type].first[:type]
|
198
|
+
elsif code[:type] == :function
|
199
|
+
"Function"
|
200
|
+
elsif code[:type] == :assignment && code[:right]
|
201
|
+
if code[:right][:type] == :function
|
202
|
+
"Function"
|
203
|
+
elsif code[:right][:type] == :literal
|
204
|
+
code[:right][:class]
|
205
|
+
else
|
206
|
+
"Object"
|
207
|
+
end
|
208
|
+
else
|
209
|
+
"Object"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def detect_extends(doc_map, code)
|
214
|
+
if doc_map[:extends]
|
215
|
+
doc_map[:extends].first[:extends]
|
216
|
+
elsif code[:type] == :assignment && code[:right] && code[:right][:type] == :ext_extend
|
217
|
+
code[:right][:extend].join(".")
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def detect_xtype(doc_map)
|
222
|
+
doc_map[:xtype] ? doc_map[:xtype].first[:name] : nil
|
223
|
+
end
|
224
|
+
|
225
|
+
def detect_params(docs, code)
|
226
|
+
implicit = detect_implicit_params(code)
|
227
|
+
explicit = detect_explicit_params(docs)
|
228
|
+
# Override implicit parameters with explicit ones
|
229
|
+
params = []
|
230
|
+
[implicit.length, explicit.length].max.times do |i|
|
231
|
+
im = implicit[i] || {}
|
232
|
+
ex = explicit[i] || {}
|
233
|
+
params << {
|
234
|
+
:type => ex[:type] || im[:type] || "Object",
|
235
|
+
:name => ex[:name] || im[:name] || "",
|
236
|
+
:doc => ex[:doc] || im[:doc] || "",
|
237
|
+
}
|
238
|
+
end
|
239
|
+
params
|
240
|
+
end
|
241
|
+
|
242
|
+
def detect_implicit_params(code)
|
243
|
+
if code[:type] == :function
|
244
|
+
code[:params]
|
245
|
+
elsif code[:type] == :assignment && code[:right] && code[:right][:type] == :function
|
246
|
+
code[:right][:params]
|
247
|
+
else
|
248
|
+
[]
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
def detect_explicit_params(docs)
|
253
|
+
docs.find_all {|tag| tag[:tagname] == :param}
|
254
|
+
end
|
255
|
+
|
256
|
+
def detect_return(doc_map)
|
257
|
+
ret = doc_map[:return] ? doc_map[:return].first : {}
|
258
|
+
return {
|
259
|
+
:type => ret[:type] || "void",
|
260
|
+
:doc => ret[:doc] || "",
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
# Combines :doc-s of most tags
|
265
|
+
# Ignores tags that have doc comment themselves
|
266
|
+
def detect_doc(docs)
|
267
|
+
ignore_tags = [:param, :return]
|
268
|
+
doc_tags = docs.find_all { |tag| !ignore_tags.include?(tag[:tagname]) }
|
269
|
+
doc_tags.map { |tag| tag[:doc] }.compact.join(" ")
|
270
|
+
end
|
271
|
+
|
272
|
+
# Build map of at-tags for quick lookup
|
273
|
+
def build_doc_map(docs)
|
274
|
+
map = {}
|
275
|
+
docs.each do |tag|
|
276
|
+
if map[tag[:tagname]]
|
277
|
+
map[tag[:tagname]] << tag
|
278
|
+
else
|
279
|
+
map[tag[:tagname]] = [tag]
|
280
|
+
end
|
281
|
+
end
|
282
|
+
map
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|