form tag

form tag

error: pathspec 'app/assets/javascripts/pt/tags/form.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/pt/tags/form.js.coffee
+++ app/assets/javascripts/pt/tags/form.js.coffee
@@ -0,0 +1,10 @@
+window.pt ||= tags: []
+
+pt.tags.push
+  formRemove:
+    event: 'click'
+    callback: ->
+      $el     = $ this
+      attr    = $el.ptAttr()
+
+      $el.closest('form').remove()


adding in a smidge of JS debugging to help refine the searching

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rideconnection/clearinghouse.git/'


added Farsi translation

added Farsi translation

error: pathspec 't9n/fa.coffee' did not match any file(s) known to git

--- t9n/fa.coffee
+++ t9n/fa.coffee
@@ -0,0 +1,114 @@
+#Language: Farsi
+#Translators: pajooh
+
+fa =
+
+  add: "افزودن"
+  and: "و"
+  back: "برگشت"
+  changePassword: "تعویض گذرواژه"
+  choosePassword: "انتخاب یک گذرواژه"
+  clickAgree: "با انتخاب ثبت‌نام، شما موافق هستید با"
+  configure: "پیکربندی"
+  createAccount: "ایجاد یک حساب"
+  currentPassword: "گذرواژه کنونی"
+  dontHaveAnAccount: "یک حساب ندارید؟"
+  email: "رایانامه"
+  emailAddress: "آدرس رایانامه"
+  emailResetLink: "پیوند بازنشانی رایانامه"
+  forgotPassword: "گذرواژه‌تان را فراموش کرده‌اید؟"
+  ifYouAlreadyHaveAnAccount: "اگر هم‌اکنون یک حساب دارید"
+  newPassword: "گذرواژه جدید"
+  newPasswordAgain: "گذرواژه جدید (تکرار)"
+  optional: "اختيارى"
+  OR: "یا"
+  password: "گذرواژه"
+  passwordAgain: "گذرواژه (دوباره)"
+  privacyPolicy: "حریم خصوصی"
+  remove: "حذف"
+  resetYourPassword: "بازنشانی گذرواژه شما"
+  setPassword: "تنظیم گذرواژه"
+  sign: "نشان"
+  signIn: "ورود"
+  signin: "ورود"
+  signOut: "خروج"
+  signUp: "ثبت‌نام"
+  signupCode: "کد ثبت‌نام"
+  signUpWithYourEmailAddress: "با آدرس رایانامه‌تان ثبت‌نام کنید"
+  terms: "قوانین استفاده"
+  updateYourPassword: "گذرواژه‌تان را به روز کنید"
+  username: "نام کاربری"
+  usernameOrEmail: "نام کاربری یا رایانامه"
+  with: "با"
+
+
+  info:
+    emailSent: "رایانامه ارسال شد"
+    emailVerified: "رایانامه تایید شد"
+    passwordChanged: "گذرواژه تغییر کرد"
+    passwordReset: "گذرواژه بازنشانی شد"
+
+
+  error:
+    emailRequired: "رایانامه ضروری است."
+    minChar: "گذرواژه حداقل ۷ کاراکتر."
+    pwdsDontMatch: "گذرواژه‌ها تطابق ندارند"
+    pwOneDigit: "گذرواژه باید لااقل یک رقم داشته باشد."
+    pwOneLetter: "گذرواژه یک حرف نیاز دارد."
+    signInRequired: "برای انجام آن باید وارد شوید."
+    signupCodeIncorrect: "کد ثبت‌نام نادرست است."
+    signupCodeRequired: "کد ثبت‌نام ضروری است."
+    usernameIsEmail: "نام کاربری نمی‌توان آدرس رایانامه باشد."
+    usernameRequired: "نام کاربری ضروری است."
+
+
+    accounts:
+
+      #---- accounts-base
+      #"@" + domain + " email required"
+      #"A login handler should return a result or undefined"
+      "Email already exists.": "رایانامه هم‌اکنون وجود دارد."
+      "Email doesn't match the criteria.": "رایانامه با ضوابط تطابق ندارد."
+      "Invalid login token": "علامت ورود نامعتبر است"
+      "Login forbidden": "ورود ممنوع است"
+      #"Service " + options.service + " already configured"
+      "Service unknown": "سرویس ناشناس"
+      "Unrecognized options for login request": "گزینه‌های نامشخص برای درخواست ورود"
+      "User validation failed": "اعتبارسنجی کاربر ناموفق"
+      "Username already exists.": "نام کاربری هم‌اکنون وجود دارد."
+      "You are not logged in.": "شما وارد نشده‌اید."
+      "You've been logged out by the server. Please log in again.": "شما توسط سرور خارج شده‌اید. لطفأ دوباره وارد شوید."
+      "Your session has expired. Please log in again.": "جلسه شما منقضی شده است. لطفا دوباره وارد شوید."
+
+
+      #---- accounts-oauth
+      "No matching login attempt found": "تلاش ورود مطابق یافت نشد"
+
+
+      #---- accounts-password-client
+      "Password is old. Please reset your password.": "گذرواژه قدیمی است. لطفأ گذرواژه‌تان را بازتنظیم کنید."
+
+
+      #---- accounts-password
+      "Incorrect password": "گذرواژه نادرست"
+      "Invalid email": "رایانامه نامعتبر"
+      "Must be logged in": "باید وارد شوید"
+      "Need to set a username or email": "یک نام کاربری یا ایمیل باید تنظیم شود"
+      "old password format": "قالب گذرواژه قدیمی"
+      "Password may not be empty": "گذرواژه نمی‌تواند خالی باشد"
+      "Signups forbidden": "ثبت‌نام ممنوع"
+      "Token expired": "علامت رمز منقظی شده است"
+      "Token has invalid email address": "علامت رمز دارای آدرس رایانامه نامعتبر است"
+      "User has no password set": "کاربر گذرواژه‌ای تنظیم نکرده است"
+      "User not found": "کاربر یافت نشد"
+      "Verify email link expired": "پیوند تایید رایانامه منقضی شده است"
+      "Verify email link is for unknown address": "پیوند تایید رایانامه برای آدرس ناشناخته است"
+
+      #---- match
+      "Match failed": "تطابق ناموفق"
+
+      #---- Misc...
+      "Unknown error": "خطای ناشناخته"
+
+
+T9n.map "fa", fa


update Chinese (simplified)

update Chinese (simplified)

update ‘…’ to ‘……’
add ‘ ’ before and after for each english in Chinese
add ‘。’ for some value
add translation value for ‘email_notifications_description’
update ‘customize_wizard’
update ‘:’ to ‘：’
update ‘!’ to ‘！’

--- app/locale/zh-HANS.coffee
+++ app/locale/zh-HANS.coffee
@@ -1,8 +1,8 @@
 module.exports = nativeDescription: "简体中文", englishDescription: "Chinese (Simplified)", translation:
   common:
-    loading: "读取中..."
+    loading: "读取中……"
     saving: "保存中……"
-    sending: "发送中..."
+    sending: "发送中……"
     cancel: "退出"
 #    save: "Save"
     delay_1_sec: "1 秒"
@@ -53,33 +53,33 @@

   signup:
 #    create_account_title: "Create Account to Save Progress"
-    description: "这是免费的。简单易学："
+    description: "这是免费的，简单易学："
     email_announcements: "通过邮件接收通知"
-    coppa: "13 岁以上或非美国用户"
+    coppa: "13岁以上或非美国用户"
     coppa_why: "为什么？"
-    creating: "账户创建中..."
+    creating: "账户创建中……"
     sign_up: "注册"
     log_in: "登录"

   home:
     slogan: "通过玩儿游戏学到Javascript脚本语言"
-    no_ie: "抱歉！Internet Explorer 9等更旧的预览器打不开此网站"
+    no_ie: "抱歉！Internet Explorer 9等更旧的预览器打不开此网站。"
     no_mobile: "CodeCombat 不是针对手机设备设计的，所以可能不好用！"
     play: "玩"

   play:
     choose_your_level: "选取难度"
-    adventurer_prefix: "你可以选择以下任意关卡，或者讨论以上的关卡 "
-    adventurer_forum: "冒险家论坛"
+    adventurer_prefix: "你可以选择以下任意关卡，或者讨论以上的关卡。"
+    adventurer_forum: "冒险者论坛"
     adventurer_suffix: "."
     campaign_beginner: "新手作战"
-    campaign_beginner_description: "...在这里可以学到编程技巧。"
+    campaign_beginner_description: "……在这里可以学到编程技巧。"
     campaign_dev: "随机困难关卡"
-    campaign_dev_description: "...在这里你可以学到做一些复杂功能的接口。"
+    campaign_dev_description: "……在这里你可以学到做一些复杂功能的接口。"
     campaign_multiplayer: "多人竞技场"
-    campaign_multiplayer_description: "...在这里你可以和其他玩家们进行代码肉搏战。"
+    campaign_multiplayer_description: "……在这里你可以和其他玩家们进行代码肉搏战。"
     campaign_player_created: "已创建的玩家"
-    campaign_player_created_description: "...在这里你可以与你的小伙伴的创造力战斗 技术指导."
+    campaign_player_created_description: "……在这里你可以与你的小伙伴的创造力战斗 技术指导."
     level_difficulty: "难度"

   contact:
@@ -90,13 +90,13 @@
     contribute_suffix: "！"
     forum_prefix: "对任何公共部分，放手去干吧 "
     forum_page: "我们的论坛"
-    forum_suffix: "代替。"
+    forum_suffix: "代替 "
     send: "意见反馈"

   diplomat_suggestion:
-    title: "帮我们翻译CodeCombat"
+    title: "帮我们翻译 CodeCombat"
     sub_heading: "我们需要您的语言技能"
-    pitch_body: "我们开发了CodeCombat的英文版，但是现在我们的玩家遍布全球。很多人想玩中文（简体）版的，却不会说英语，所以如果你中英文都会，请考虑一下参加我们的翻译工作，帮忙把 CodeCombat 网站还有所有的关卡翻译成中文（简体）。"
+    pitch_body: "我们开发了 CodeCombat 的英文版，但是现在我们的玩家遍布全球。很多人想玩中文（简体）版的，却不会说英语，所以如果你中英文都会，请考虑一下参加我们的翻译工作，帮忙把 CodeCombat 网站还有所有的关卡翻译成中文（简体）。"
     missing_translations: "未翻译的文本将显示为英文。"
     learn_more: "了解更多有关成为翻译人员的说明"
     subscribe_as_diplomat: "提交翻译人员申请"
@@ -122,7 +122,7 @@
     new_password_verify: "核实"
     email_subscriptions: "邮箱验证"
     email_announcements: "通知"
-#    email_notifications_description: "Get periodic notifications for your account."
+    email_notifications_description: "定期接受来自你的账户的通知。"
     email_announcements_description: "接收关于 CodeCombat 最近的新闻和发展的邮件。"
     contributor_emails: "贡献者通知"
     contribute_prefix: "我们在寻找志同道合的人！请到 "
@@ -153,7 +153,7 @@
     level_load_error: "关卡不能载入。"
     done: "完成"
     grid: "格子"
-    customize_wizard: "自定义巫师"
+    customize_wizard: "自定义向导"
     home: "主页"
     guide: "指南"
     multiplayer: "多人游戏"
@@ -168,7 +168,7 @@
     victory_title_suffix: " 完成"
     victory_sign_up: "保存进度"
     victory_sign_up_poke: "想保存你的代码？创建一个免费账户吧！"
-    victory_rate_the_level: "评估关卡: "
+    victory_rate_the_level: "评估关卡："
     victory_play_next_level: "下一关"
     victory_go_home: "返回主页"
     victory_review: "给我们反馈！"
@@ -178,7 +178,7 @@
     multiplayer_link_description: "把这个链接告诉小伙伴们，一起玩吧。"
     multiplayer_hint_label: "提示："
     multiplayer_hint: " 点击全选，然后按 Apple-C（苹果电脑）或 Ctrl-C 复制链接。"
-    multiplayer_coming_soon: "多人游戏的更多特性!"
+    multiplayer_coming_soon: "多人游戏的更多特性！"
     guide_title: "指南"
     tome_minion_spells: "助手的咒语"
     tome_read_only_spells: "只读的咒语"
@@ -190,7 +190,7 @@
     tome_select_spell: "选择一个法术"
     tome_select_a_thang: "选择人物来 "
     tome_available_spells: "可用的法术"
-    hud_continue: "继续 (按 shift-空格)"
+    hud_continue: "继续（按 shift-空格）"
 #    spell_saved: "Spell Saved"

 #  admin:


removal of some comments

removal of some comments

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/DogFoodBurrito/aviary.git/'


Fix incorrect scrolling test

Fix incorrect scrolling test

--- test/javascript/turbolinks_visit_test.coffee
+++ test/javascript/turbolinks_visit_test.coffee
@@ -277,15 +277,15 @@
     @window.scrollTo(42, 42)
     @Turbolinks.visit('iframe2.html')

-  test "restores scroll position on history.back() cache miss", (done) ->
-    change = 0
-    @document.addEventListener 'page:change', =>
-      change += 1
-      if change is 1
+  test "doesn't restore scroll position on history.back() cache miss", (done) ->
+    load = 0
+    @document.addEventListener 'page:load', =>
+      load += 1
+      assert.equal @window.pageXOffset, 0
+      assert.equal @window.pageYOffset, 0
+      if load is 1
         setTimeout (=> @history.back()), 0
-      else if change is 2
-        assert.equal @window.pageXOffset, 42
-        assert.equal @window.pageYOffset, 42
+      else if load is 2
         done()
     @window.scrollTo(42, 42)
     @Turbolinks.pagesCached(0)


Updated variable regex

Updated variable regex

error: pathspec 'grammars/silverstripe' did not match any file(s) known to git
error: pathspec 'templates.cson' did not match any file(s) known to git


fix you on reactions

fix you on reactions

--- packages/rocketchat-ui-message/client/message.coffee
+++ packages/rocketchat-ui-message/client/message.coffee
@@ -120,7 +120,8 @@
 			total = reaction.usernames.length
 			usernames = '@' + reaction.usernames.slice(0, 15).join(', @')

-			usernames = usernames.replace('@'+userUsername, t('You').toLowerCase())
+			reg = new RegExp('@'+userUsername+'$')
+			usernames = usernames.replace(reg, t('You').toLowerCase())

 			if total > 15
 				usernames = usernames + ' ' + t('And_more', { length: total - 15 }).toLowerCase()


adding in select reading component for both reading and homeworks

error: pathspec 'src/components/task-plan/select-topics.cjsx' did not match any file(s) known to git

--- src/components/task-plan/select-topics.cjsx
+++ src/components/task-plan/select-topics.cjsx
@@ -0,0 +1,136 @@
+React = require 'react'
+_ = require 'underscore'
+BS = require 'react-bootstrap'
+Dialog = require '../dialog'
+{TocStore, TocActions} = require '../../flux/toc'
+{TaskPlanStore, TaskPlanActions} = require '../../flux/task-plan'
+
+SectionTopic = React.createClass
+  displayName: 'SectionTopic'
+
+  propTypes:
+    planId: React.PropTypes.any.isRequired
+    section: React.PropTypes.object.isRequired
+    active: React.PropTypes.bool
+
+  render: ->
+    classes = ['section']
+    classes.push('selected') if @props.active
+    isChecked = 'checked' if @props.active
+    classes = classes.join(' ')
+
+

+
+        <input type="checkbox" checked={isChecked}/>
+
+      {@props.section.number}
+      {@props.section.title}
+

+
+  toggleSection: ->
+    section = @props.section
+    if (TaskPlanStore.hasTopic(@props.planId, section.id))
+      TaskPlanActions.removeTopic(@props.planId, section.id)
+    else
+      TaskPlanActions.addTopic(@props.planId, section.id)
+
+ChapterAccordion = React.createClass
+  displayName: 'ChapterAccordion'
+
+  propTypes:
+    planId: React.PropTypes.any.isRequired
+    courseId: React.PropTypes.any.isRequired
+    chapter: React.PropTypes.object.isRequired
+    hide: React.PropTypes.func.isRequired
+    selected: React.PropTypes.array
+
+  renderSections: (section) ->
+    active = TaskPlanStore.hasTopic(@props.planId, section.id)
+    <SectionTopic active={active} section={section} planId={@props.planId} />
+
+  areAllSectionsSelected: (allSelected, section) ->
+    @props.selected.indexOf(section.id) >= 0 and allSelected
+
+  toggleAllSections: (e) ->
+    if e.target.checked
+      action = TaskPlanActions.addTopic
+    else
+      action = TaskPlanActions.removeTopic
+
+    planId = @props.planId
+    _.each @props.chapter.children, (section) ->
+      action(planId, section.id)
+
+  areAnySectionsSelected: (anySelected, section) ->
+    @props.selected.indexOf(section.id) >= 0 or anySelected
+
+  render: ->
+    chapter = @props.chapter
+    sections = _.map(chapter.children, @renderSections)
+    allChecked = _.reduce(chapter.children, @areAllSectionsSelected, true)
+    expandAccordion = _.reduce(chapter.children, @areAnySectionsSelected, true) or @props.i is 0
+    activeKey = chapter.id if expandAccordion
+
+    header =
+

+
+          <input type="checkbox" id="chapter-checkbox-#{chapter.id}"
+            onChange={@toggleAllSections} checked={allChecked}/>
+
+        {chapter.number}
+        {chapter.title}
+

+
+    <BS.Accordion activeKey={activeKey}>
+      <BS.Panel key={chapter.id} header={header} eventKey={chapter.id}>
+        {sections}
+      </BS.Panel>
+    </BS.Accordion>
+
+SelectTopics = React.createClass
+  displayName: 'SelectTopics'
+  propTypes:
+    planId: React.PropTypes.any.isRequired
+    courseId: React.PropTypes.any.isRequired
+    hide: React.PropTypes.func.isRequired
+    selected: React.PropTypes.array
+
+  getInitialState: ->
+    {courseId} = @props
+    TocActions.load(courseId) unless TocStore.isLoaded()
+    { }
+
+  componentWillMount:   -> TocStore.addChangeListener(@update)
+  componentWillUnmount: -> TocStore.removeChangeListener(@update)
+
+  update: -> @setState({})
+
+
+  renderChapterPanels: (chapter, i) ->
+    <ChapterAccordion {...@props} chapter={chapter}/>
+
+
+  render: ->
+
+    {courseId, planId, selected, hide, header, primary} = @props
+    unless TocStore.isLoaded()
+      TocActions.load(courseId)
+      return Loading...
+
+    selected = TaskPlanStore.getTopics(planId)
+    chapters = _.map(TocStore.get(), @renderChapterPanels)
+
+    <Dialog
+      className="my-dialog-class"
+      header={header}
+      primary={primary}
+      confirmMsg="Are you sure you want to close?"
+      isChanged={-> true}
+      onCancel={hide}>
+
+

+        {chapters}
+

+    </Dialog>
+
+module.exports = SelectTopics


Add cache module

Add cache module

error: pathspec 'coffee/model/cache.coffee' did not match any file(s) known to git

--- coffee/model/cache.coffee
+++ coffee/model/cache.coffee
@@ -0,0 +1,8 @@
+"use strict"
+
+port = process.env.DOTCLOUD_CACHE_REDIS_PORT or 6379
+host = process.env.DOTCLOUD_CACHE_REDIS_HOST or 'localhost'
+pass = process.env.DOTCLOUD_CACHE_REDIS_PASSWORD or null
+
+module.exports = redisClient port, host, auth_pass: pass
+


Bring back moving earth, yay!

Bring back moving earth, yay!

error: pathspec 'core/app/assets/javascripts/base/earth.coffee' did not match any file(s) known to git

--- core/app/assets/javascripts/base/earth.coffee
+++ core/app/assets/javascripts/base/earth.coffee
@@ -0,0 +1,10 @@
+$window = $(window)
+$earth = $('.header-earth')
+
+if $earth.is(':visible')
+  scrollHandler = ->
+    $earth.css 'margin-top', 30-0.3*Math.max($window.scrollTop(), 0)
+  $window.scroll scrollHandler
+  scrollHandler()
+else
+  $earth.hide()


ide/terminal: menu options fixed

ide/terminal: menu options fixed

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


Formatting

Formatting

--- app/lib/badge-definitions.coffee
+++ app/lib/badge-definitions.coffee
@@ -205,7 +205,7 @@
           return false
     collection: 'ornithological'
   ,
-    name: 'First-Level Multi-Collections Badge'
+    name: "Novice Collection's Explorer"
     url: 'badges/multi/beginner.png'
     description: 'You earn this badge for transcribing 1 record from 3 collections'
     awardText: 'You earned this badge for transcribing 1 record from 3 collections'
@@ -213,11 +213,11 @@
       func: (details) ->
         checkWorkSpread.call details.user, 1, 3
   ,
-    name: 'Second-Level Multi-Collections Badge'
+    name: "Intermediate Collection's Explorer"
     url: 'badges/multi/intermediate.png'
     description: 'You earn this badge for transcribing 25 record from 3 collections'
     awardText: 'You earned this badge for transcribing 25 record from 3 collections'
     condition:
       func: (details) ->
-        checkWorkSpread.call details.user, 3, 3
+        checkWorkSpread.call details.user, 25, 3
 ]


generateStackTemplateTitle: util to get generated stack template title

error: pathspec 'client/app/lib/util/generateStackTemplateTitle.coffee' did not match any file(s) known to git

--- client/app/lib/util/generateStackTemplateTitle.coffee
+++ client/app/lib/util/generateStackTemplateTitle.coffee
@@ -0,0 +1,5 @@
+nick = require './nick'
+
+module.exports = ->
+
+  "#{nick().capitalize()}'s Stack"


correct build order

correct build order

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/amit-bansil/wiretrap.git/'


雨雲レーダの詳しいページURL削除

雨雲レーダの詳しいページURL削除

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/askdkc/aw_hubot.git/'


Added integer ui element.

Added integer ui element.

error: pathspec 'app/assets/javascripts/app/controllers/_ui_element/integer.coffee' did not match any file(s) known to git

--- app/assets/javascripts/app/controllers/_ui_element/integer.coffee
+++ app/assets/javascripts/app/controllers/_ui_element/integer.coffee
@@ -0,0 +1,6 @@
+# coffeelint: disable=camel_case_classes
+class App.UiElement.integer
+  @render: (attribute) ->
+    attribute.type = 'number'
+    attribute.step = '1'
+    $( App.view('generic/input')( attribute: attribute ) )


added Jax.Material.Surface

added Jax.Material.Surface

actually, the current Jax.Material.Legacy is the same thing,
but that's about to change to be more backward compatible,
so cloning it now as Jax.Material.Surface makes sense.

error: pathspec 'lib/assets/javascripts/jax/material/surface.js.coffee' did not match any file(s) known to git

--- lib/assets/javascripts/jax/material/surface.js.coffee
+++ lib/assets/javascripts/jax/material/surface.js.coffee
@@ -0,0 +1,96 @@
+class Jax.Material.Surface extends Jax.Material.Custom
+  @addLayer 'Position'
+  @addLayer 'VertexColor'
+  @addLayer 'WorldAmbient'
+  @addLayer 'LightAmbient'
+  @addLayer 'LambertDiffuse'
+  @addLayer 'PhongSpecular'
+  @addLayer 'ShadowMap'
+  @addLayer 'Attenuation'
+  @addLayer 'ClampColor'
+
+  @define 'intensity',
+    get: -> @_intensity
+    set: (obj) ->
+      intensity = @_intensity
+      if typeof(obj) is 'number'
+        intensity.ambient  = intensity.diffuse  = intensity.specular = obj
+      else
+        intensity.ambient  = obj.ambient  if obj.ambient  isnt undefined
+        intensity.diffuse  = obj.diffuse  if obj.diffuse  isnt undefined
+        intensity.specular = obj.specular if obj.specular isnt undefined
+
+  @define 'color',
+    get: -> @_color
+    set: (obj) ->
+      color = @_color
+      isColor = typeof(obj) isnt 'object' or  \
+                (obj.ambient is undefined and \
+                 obj.diffuse is undefined and \
+                 obj.specular is undefined)
+      if isColor
+        color.ambient  = color.diffuse  = color.specular = obj
+      else
+        color.ambient  = obj.ambient  if obj.ambient  isnt undefined
+        color.diffuse  = obj.diffuse  if obj.diffuse  isnt undefined
+        color.specular = obj.specular if obj.specular isnt undefined
+
+  @define 'shininess',
+    get: -> @_shininess
+    set: (s) ->
+      @findLayer(Jax.Material.Layer.PhongSpecular)?.shininess = s
+      @_shininess = s
+
+  @define 'pcf',
+    get: -> @_pcf
+    set: (s) ->
+      @findLayer(Jax.Material.Layer.ShadowMap)?.pcf = s
+      @_pcf = s
+
+  constructor: (options, name) ->
+    # FIXME These should probably become classes.
+    @_intensity = {}
+    mat = this
+    Object.defineProperty @_intensity, 'ambient',
+      get:     -> @_ambient
+      set: (i) ->
+        mat.findLayer(Jax.Material.Layer.WorldAmbient)?.intensity = i
+        mat.findLayer(Jax.Material.Layer.LightAmbient)?.intensity = i
+        @_ambient = i
+    Object.defineProperty @_intensity, 'diffuse',
+      get:     -> @_diffuse
+      set: (i) ->
+        mat.findLayer(Jax.Material.Layer.LambertDiffuse)?.intensity = i
+        @_diffuse = i
+    Object.defineProperty @_intensity, 'specular',
+      get:     -> @_specular
+      set: (i) ->
+        mat.findLayer(Jax.Material.Layer.PhongSpecular)?.intensity = i
+        @_specular = i
+
+    @_color = {}
+    mat = this
+    Object.defineProperty @_color, 'ambient',
+      get:     -> @_ambient
+      set: (c) ->
+        mat.findLayer(Jax.Material.Layer.WorldAmbient)?.color = Jax.Color.parse c
+        mat.findLayer(Jax.Material.Layer.LightAmbient)?.color = Jax.Color.parse c
+        @_ambient = c
+    Object.defineProperty @_color, 'diffuse',
+      get:     -> @_diffuse
+      set: (c) ->
+        mat.findLayer(Jax.Material.Layer.LambertDiffuse)?.color = Jax.Color.parse c
+        @_diffuse = c
+    Object.defineProperty @_color, 'specular',
+      get:     -> @_specular
+      set: (c) ->
+        mat.findLayer(Jax.Material.Layer.PhongSpecular)?.color = Jax.Color.parse c
+        @_specular = c
+
+
+    options or= {}
+    options.intensity = 1      if options.intensity is undefined
+    options.color     = '#fff' if options.color     is undefined
+    options.shininess = 60     if options.shininess is undefined
+    options.pcf       = true   if options.pcf       is undefined
+    super options, name


route for commit pagination

route for commit pagination

[#96451412]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/netguru/review.git/'


Use current snapshot note instead of hard-coding to recordings

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-dashboard.git/'


Process up to 100 frames without a break

--- app/assets/javascripts/player/movie.js.coffee
+++ app/assets/javascripts/player/movie.js.coffee
@@ -13,6 +13,7 @@
     @playing = false
     @lastFrameTime = undefined
     @timeElapsedBeforePause = undefined
+    @framesProcessed = 0

   isLoaded: ->
     @model.get('escaped_stdout_data') != undefined
@@ -133,9 +134,11 @@
     if frame = @timing()[@frameNo]
       [delay, count] = frame

-      if delay <= @MIN_DELAY
+      if delay <= @MIN_DELAY and @framesProcessed < 100
+        @framesProcessed += 1
         @processFrame()
       else
+        @framesProcessed = 0
         realDelay = delay * 1000 * (1.0 / @options.speed)
         @processFrameWithDelay(realDelay)


on duty!

on duty!

error: pathspec 'scripts/onduty.coffee' did not match any file(s) known to git

--- scripts/onduty.coffee
+++ scripts/onduty.coffee
@@ -0,0 +1,6 @@
+# Display a teemo video if anyone says on duty
+#
+
+module.exports = (robot) ->
+  robot.hear /on duty/i, (msg) ->
+    msg.send "http://vimeo.com/34497207"


Replaced capped collection with 1-hour expiry index

--- server/queues/task/ScoringTask.coffee
+++ server/queues/task/ScoringTask.coffee
@@ -1,6 +1,7 @@
 mongoose = require('mongoose')

 ScoringTaskSchema = new mongoose.Schema(
+  createdAt: {type: Date, expires: 3600} #expire document 1 hour after they are created
   calculator: {type:mongoose.Schema.Types.ObjectId}
   sentDate: {type: Number}
   messageIdentifierString: {type: String}
@@ -8,5 +9,5 @@
   sessions: {type: Array, default: []}
 )

-ScoringTaskSchema.set 'capped', 104857600 #100MB capped collection
+#ScoringTaskSchema.set 'capped', 104857600 #100MB capped collection
 module.exports = mongoose.model('scoringTask', ScoringTaskSchema)


Add index Messages u._id

Add index Messages u._id

--- packages/rocketchat-lib/server/models/Messages.coffee
+++ packages/rocketchat-lib/server/models/Messages.coffee
@@ -4,6 +4,7 @@

 		@tryEnsureIndex { 'rid': 1, 'ts': 1 }
 		@tryEnsureIndex { 'ts': 1 }
+		@tryEnsureIndex { 'u._id': 1 }
 		@tryEnsureIndex { 'editedAt': 1 }, { sparse: 1 }
 		@tryEnsureIndex { 'editedBy._id': 1 }, { sparse: 1 }
 		@tryEnsureIndex { 'rid': 1, 't': 1, 'u._id': 1 }


Add a stack to getElementFromPoint To prevent infinite recursion

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/poacher2k/vimium.git/'


Now that folds are linewise, we don't need to adjust the start row of buffer change events

--- src/app/renderer.coffee
+++ src/app/renderer.coffee
@@ -111,17 +111,12 @@
     @handleHighlighterChange(@lastHighlighterChangeEvent)

   handleHighlighterChange: (e) ->
-    oldBufferRange = e.oldRange.copy()
-    newBufferRange = e.newRange.copy()
-
-    oldBufferRange.start.row = @bufferRowForScreenRow(@screenRowForBufferRow(oldBufferRange.start.row))
-    newBufferRange.start.row = @bufferRowForScreenRow(@screenRowForBufferRow(newBufferRange.start.row))
-
-    oldScreenRange = @screenLineRangeForBufferRange(oldBufferRange)
-    newScreenLines = @buildLinesForBufferRows(newBufferRange.start.row, newBufferRange.end.row)
-
+    { oldRange, newRange } = e
+
+    oldScreenRange = @screenLineRangeForBufferRange(oldRange)
+    newScreenLines = @buildLinesForBufferRows(newRange.start.row, newRange.end.row)
     @lineMap.replaceScreenRows oldScreenRange.start.row, oldScreenRange.end.row, newScreenLines
-    newScreenRange = @screenLineRangeForBufferRange(newBufferRange)
+    newScreenRange = @screenLineRangeForBufferRange(newRange)

     @trigger 'change', { oldRange: oldScreenRange, newRange: newScreenRange, bufferChanged: true }


Add atom prefix to rootView reference

Add atom prefix to rootView reference

--- src/atom-package.coffee
+++ src/atom-package.coffee
@@ -219,11 +219,11 @@
   subscribeToActivationEvents: ->
     return unless @metadata.activationEvents?
     if _.isArray(@metadata.activationEvents)
-      rootView.command(event, @handleActivationEvent) for event in @metadata.activationEvents
+      atom.rootView.command(event, @handleActivationEvent) for event in @metadata.activationEvents
     else if _.isString(@metadata.activationEvents)
-      rootView.command(@metadata.activationEvents, @handleActivationEvent)
-    else
-      rootView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
+      atom.rootView.command(@metadata.activationEvents, @handleActivationEvent)
+    else
+      atom.rootView.command(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents

   handleActivationEvent: (event) =>
     bubblePathEventHandlers = @disableEventHandlersOnBubblePath(event)
@@ -234,11 +234,11 @@

   unsubscribeFromActivationEvents: ->
     if _.isArray(@metadata.activationEvents)
-      rootView.off(event, @handleActivationEvent) for event in @metadata.activationEvents
+      atom.rootView.off(event, @handleActivationEvent) for event in @metadata.activationEvents
     else if _.isString(@metadata.activationEvents)
-      rootView.off(@metadata.activationEvents, @handleActivationEvent)
-    else
-      rootView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents
+      atom.rootView.off(@metadata.activationEvents, @handleActivationEvent)
+    else
+      atom.rootView.off(event, selector, @handleActivationEvent) for event, selector of @metadata.activationEvents

   disableEventHandlersOnBubblePath: (event) ->
     bubblePathEventHandlers = []


Added signature model.

Added signature model.

error: pathspec 'app/assets/javascripts/app/models/signature.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/app/models/signature.js.coffee
+++ app/assets/javascripts/app/models/signature.js.coffee
@@ -0,0 +1,15 @@
+class App.Signature extends App.Model
+  @configure 'Signature', 'name', 'body', 'note', 'active'
+  @extend Spine.Model.Ajax
+  @url: '/api/signatures'
+
+  @configure_attributes = [
+    { name: 'name',                 display: 'Name',              tag: 'input',    type: 'text', limit: 100, 'null': false, 'class': 'span4' },
+    { name: 'body',                 display: 'Text',              tag: 'textarea',               limit: 250, 'null': true, 'class': 'span4' },
+    { name: 'note',                 display: 'Note',              tag: 'textarea', note: 'Notes are visible to agents only, never to customers.', limit: 250, 'null': true, 'class': 'span4' },
+    { name: 'updated_at',           display: 'Updated',           type: 'time',    readonly: 1 },
+    { name: 'active',               display: 'Active',            tag: 'boolean',  type: 'boolean', 'default': true, 'null': false, 'class': 'span4' },
+  ]
+  @configure_overview = [
+    'name',
+  ]


Follow order: First public, then private methods

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/ChHeLeJa/SpaceTrader.git/'


fix some egrarious spacing issues with the miniterm

--- salvus/page/project_miniterm.cjsx
+++ salvus/page/project_miniterm.cjsx
@@ -148,7 +148,7 @@
         # NOTE: The style in form below offsets Bootstrap's form margin-bottom of +15 to look good.
         # We don't use inline, since we still want the full horizontal width.

-            <form onSubmit={(e) => e.preventDefault(); @execute_command()} style={marginBottom: '-10px'}>
+            <form onSubmit={(e) => e.preventDefault(); @execute_command()} style={marginBottom: '-10px', marginTop:'-15px'}>
                 <Input
                     type        = "text"
                     value       = {@state.input}
@@ -159,7 +159,7 @@
                     buttonAfter = {@render_button()}
                     />
             </form>
-

+

                 {@render_output(@state.error, {color:'darkred', margin:0})}
                 {@render_output(@state.stdout, {margin:0})}


Watching out for finding a null session when getting two games.

--- server/queues/scoring/getTwoGames.coffee
+++ server/queues/scoring/getTwoGames.coffee
@@ -17,7 +17,7 @@
 sendSessionsResponse = (res) ->
   (err, sessions) ->
     if err then return errors.serverError res, "Couldn't get two games to simulate: #{err}"
-    unless sessions.length is 2
+    unless _.filter(sessions).length is 2
       console.log 'No games to score.', sessions.length
       res.send 204, 'No games to score.'
       return res.end()
@@ -110,5 +110,3 @@
     return callback err if err
     result = earliestSubmissionCache[cacheKey] = earliest?.submitDate
     callback null, result
-
-


fix user registration

fix user registration

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bekite/knignish.git/'


add Notification model and collection

add Notification model and collection

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rremizov/github-notifier.git/'


path fix

path fix

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/conduktor/web.git/'


add note on vibrate implementation

add note on vibrate implementation

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/supersonic.git/'


fix breakpoint

fix breakpoint

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/tkraak/elm.git/'


Add Editor:onDidSave

Add Editor:onDidSave

--- src/editor.coffee
+++ src/editor.coffee
@@ -257,6 +257,16 @@
   onDidInsertText: (callback) ->
     @emitter.on 'did-insert-text', callback

+  # Public: Invoke the given callback after the buffer is saved to disk.
+  #
+  # * `callback` {Function} to be called after the buffer is saved.
+  #   * `event` {Object} with the following keys:
+  #     * `path` The path to which the buffer was saved.
+  #
+  # Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
+  onDidSave: (callback) ->
+    @getBuffer().onDidSave(callback)
+
   # Extended: Calls your `callback` when a {Cursor} is added to the editor.
   # Immediately calls your callback for each existing cursor.
   #


Don't dispose emitter, specs fail

Don't dispose emitter, specs fail

--- src/editor.coffee
+++ src/editor.coffee
@@ -172,7 +172,6 @@
     @displayBuffer.destroy()
     @languageMode.destroy()
     @emitter.emit 'did-destroy'
-    @emitter.dispose()

   ###
   Section: Event Subscription


Remove timelapse status and add embed code in info tab. (#1772)


Set width to 0 on tester element

Set width to 0 on tester element

--- src/app/gutter.coffee
+++ src/app/gutter.coffee
@@ -13,14 +13,15 @@
   highestNumberWidth: null

   afterAttach: (onDom) ->
-    @editor()?.on 'cursor-move', => @highlightCursorLine()
+    @editor().on 'cursor-move', => @highlightCursorLine()
     @calculateWidth() if onDom

   editor: ->
     @parentView

-  lineNumberPadding: ->
+  calculateLineNumberPadding: ->
     widthTesterElement = $$ -> @div {class: 'line-number'}, ""
+    widthTesterElement.width(0)
     @append(widthTesterElement)
     lineNumberPadding = widthTesterElement.outerWidth()
     widthTesterElement.remove()
@@ -53,7 +54,7 @@
     highestNumberWidth = @editor().getLineCount().toString().length * @editor().charWidth
     if highestNumberWidth != @highestNumberWidth
       @highestNumberWidth = highestNumberWidth
-      @lineNumbers.width(highestNumberWidth + @lineNumberPadding())
+      @lineNumbers.width(highestNumberWidth + @calculateLineNumberPadding())
       @widthChanged?(@outerWidth())

   highlightCursorLine: ->


add space, enable to view markdown

add space, enable to view markdown

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/kutsuzawa/gitnotification.git/'


Client: Activity: Created searchquerystore tests

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


Added initial viewer code. Needs debugging.

error: pathspec 'src/viewer.coffee' did not match any file(s) known to git

--- src/viewer.coffee
+++ src/viewer.coffee
@@ -0,0 +1,188 @@
+geom = require './geom'
+viewer = exports
+
+STYLES = {
+  vert: "fill: white; r: 0.03; stroke: black; stroke-width: 0.005;"
+  face: "stroke: none; fill-opacity: 0.8;"
+  top: "fill: cyan;", bot: "fill: yellow;"
+  edge: "fill: none; stroke-width: 0.01; stroke-linecap: round;"
+  axis: "fill: none; stroke-width: 0.01; stroke-linecap: round;"
+  text: "fill: black; font-size: 0.04; text-anchor: middle;
+    font-family: sans-serif;"
+  B: "stroke: black;", V: "stroke: blue;"
+  M: "stroke: red;", U: "stroke: white"
+  x0: "stroke: blue;", x1: "stroke: red;", x2: "stroke: green;"
+}
+
+### UTILITIES ###
+
+viewer.processInput = (text, view) ->
+  view.fold = JSON.parse(text)
+  view.model = viewer.makeModel(view.fold)
+  viewer.addRotation(view.svg, view.cam)
+  viewer.draw(view)
+  viewer.update(view)
+
+viewer.importURL = (url, view) ->
+  xhr = new XMLHttpRequest()
+  xhr.onload = (e) => viewer.processInput(e.target.responseText, view)
+  xhr.open('GET', url); xhr.send()
+
+viewer.importFile = (file, view) ->
+  file_reader = new FileReader()
+  file_reader.onload = (e) => viewer.processInput(e.target.result, view)
+  file_reader.readAsText file
+
+viewer.getId = (id) ->
+  document.getElementById(id)
+
+viewer.listenId = (id, event, callback) ->
+  viewer.getId(id).addEventListener(event, callback)
+
+viewer.setAttrs = (el, attrs) ->
+  (el.setAttribute(k, v) for k, v of attrs); el
+
+SVGNS = 'http://www.w3.org/2000/svg'
+viewer.appendSVG = (svg, tag, attrs) ->
+  svg.appendChild(setAttrs(document.createElementNS(SVGNS, tag),attrs))
+
+viewer.makePath = (coords) ->
+  (for c, i in coords
+    "#{if (i is 0) then 'M' else 'L'} #{c[0]} #{c[1]} "
+  ).reduce geom.sum
+
+### CAMERA FUNCTIONS ###
+
+viewer.initCam = () -> {
+  c: [0,0,0], x: [1,0,0], y: [0,1,0], z: [0,0,1], rad: 1, last: null
+  show: {faces: false, edges: true, vertices: false, faceText: false}}
+
+viewer.proj = (p, cam) ->
+  [geom.dot(geom.sub(p, cam.c), cam.x), -geom.dot(geom.sub(p, cam.c), cam.y), 0]
+
+viewer.setCamXY = (cam, x, y) ->
+  [cam.x, cam.y, cam.z] = [x, y, geom.cross(x,y)]
+
+viewer.addRotation = (svg, cam) ->
+  for s in ['contextmenu','selectstart','dragstart']
+    svg.on(s, (e) -> e.preventDefault())
+  svg.mousedown (e) => cam.last = [e.clientX, e.clientY]
+  svg.mousemove (e) => viewer.rotateCam([e.clientX, e.clientY])
+  svg.mouseup (e) => viewer.rotateCam([e.clientX, e.clientY]); cam.last = null
+
+viewer.rotateCam = (p, cam) ->
+  return if not cam.last?
+  d = geom.sub(p, cam.last)
+  return if not geom.mag(d) > 0
+  u = geom.unit(geom.plus(geom.mul(cam.x, -d[1]), geom.mul(cam.y, -d[0])))
+  [x,y] = (geom.rot(cam[c], u, geom.mag(d) * 0.01) for c in ['x','y'])
+  viewer.setCamXY(x, y)
+  cam.last = p
+  viewer.update(view)
+
+### VIEWER FUNCTIONS ###
+
+viewer.initView = () ->
+  {svg: null, cam: viewer.initCam(), fold: null, model: null}
+
+viewer.faceAbove = (f1, f2, n) ->
+  [p1,p2] = ((v.ps for v in f.vs) for f in [f1,f2])
+  [dp,disjoint,np] = geom.sepNormal(p1,p2)
+  return null if disjoint # projections do not overlap
+  [v1,v2] = ((v.cs for v in f.vs) for f in [f1,f2])
+  [dv,disjoint,nv] = geom.sepNormal(v1,v2)
+  return 0 > geom.dot(nv, n) if (dv is 3) and disjoint # triangles 3D disjoint
+  ord = f1.ord["#{f2.i}"]
+  return 0 < geom.dot(f1.n, n) * ord if (dv is 2) and ord? # triangles 2D overlap
+  return null
+
+viewer.makeModel = (fold) ->
+  m = {vs: null, fs: null, es: {}}
+  m.vs = ({i: i, cs: cs} for cs, i in fold.vertices_coords)
+  (m.vs[i].cs[2] = 0 for v, i in m.vs when v.cs.length is 2)
+  m.fs = ({i: i, vs: (m.vs[v] for v in vs)} for vs, i in fold.faces_vertices)
+  if fold.edges_vertices?
+    for v, i in fold.edges_vertices
+      [a,b] = if v[0] > v[1] then [v[1],v[0]] else [v[0],v[1]]
+      m.es["e#{a}e#{b}"] = {
+        v1: m.vs[a], v2: m.vs[b], as: fold.edges_assignment[i]}
+  else
+    for f, i in m.fs
+      for v, j in f.vs
+        w = f.vs[geom.next(j,f.vs.length)]
+        [a,b] = if v.i > w.i then [w,v] else [v,w]
+        m.es["e#{a.i}e#{b.i}"] = {v1: a, v2: b, as: 'B'}
+  for f, i in m.fs
+    m.fs[i].n = geom.triangleNormal(v.cs for v in f.vs)
+    m.fs[i].c = geom.centroid(v.cs for v in f.vs)
+    m.fs[i].es = {}
+    m.fs[i].es = (for v, j in f.vs
+      w = f.vs[geom.next(j, f.vs.length)]
+      [a,b] = if v.i > w.i then [w,v] else [v,w]
+      m.es["e#{a.i}e#{b.i}"])
+    m.fs[i].ord = {}
+  if fold.faceOrders?
+    m.fs[l[0]].ord["#{l[1]}"] = l[2] for l in fold.faceOrders when l[2] isnt 0
+  return m
+
+viewer.orderFaces = (faces, direction) ->
+  (f.children = [] for f in faces)
+  for f1, i in faces
+    for f2, j in faces when j > i
+      f1_above = viewer.aboveFace(f1, f2, geom.mul(direction, -1))
+      if f1_above?
+        ([p,c] = if f1_above then [f1,f2] else [f2,f1])
+        p.children = p.children.concat([c])
+  geom.topologicalSort(faces)
+
+viewer.draw = (model, {svg: svg, cam: cam}) ->
+  svg.empty()
+  for k, v of viewer.STYLES
+    viewer.appendSVG(svg,'style',{id: k}).html(".#{k}{#{v}}")
+  min = ((v.cs[i] for v in model.vs).reduce(geom.min) for i in [0,1,2])
+  max = ((v.cs[i] for v in model.vs).reduce(geom.max) for i in [0,1,2])
+  cam.c = geom.mul(geom.plus(min, max), 0.5)
+  cam.r = geom.mag(geom.sub(max, min)) / 2 * 1.05
+  pc = viewer.proj(cam.c, cam)
+  svg.attr('viewBox', "#{pc[0] - cam.r},#{pc[1] - cam.r},#{2*cam.r},#{2*cam.r}")
+  t = "translate(0,0.01)"
+  for f, i in model.fs
+    g = viewer.appendSVG(svg, 'g')
+    f.path = viewer.appendSVG(g, 'path')
+    f.text = viewer.appendSVG(g, 'text',
+      {class: 'text', transform: t}).html("f#{f.i}")
+    for e, j in f.es when not e.path?
+      e.path = viewer.appendSVG(g, 'path')
+    for v, j in f.vs when not v.path?
+      v.path = viewer.appendSVG(g, 'circle', {class: 'vert'})
+      v.text = viewer.appendSVG(g, 'text',
+        {transform: 'translate(0, 0.01)', class: 'text'}).html("#{v.i}")
+    model.fs[i].svg = g
+  g = viewer.appendSVG(svg,'g',{transform: 'translate(-0.9,-0.9)'})
+  for c in ['x','y','z']
+    viewer.appendSVG(g,'path', {id: "a#{c}", class: "a#{c} axis"})
+
+viewer.update = ({model: model, cam: cam, svg: svg}) ->
+  (model.vs[i].ps = proj(v.cs, cam) for v, i in model.vs)
+  (model.fs[i].c2 = proj(f.c, cam)  for f, i in model.fs)
+  viewer.orderFaces(model.fs, cam.z)
+  show = {}
+  for attr in ['faceText','faces','edges','vertices']
+    show[attr] = if cam.show[attr] then 'visible' else 'hidden'
+  for f, i in model.fs when f.path?
+    visibleSide = if geom.dot(f.n, cam.z) > 0 then 'top' else 'bot'
+    setAttrs(f.text, {x: f.c2[0], y: f.c2[1], visibility: show.faceText})
+    setAttrs(f.path, {
+      d: viewer.makePath(v.ps for v in f.vs) + 'Z'
+      visibility: show.faces, class: "face #{visibleSide}"})
+    for e, j in f.es
+      setAttrs(e.path, {
+        d: viewer.makePath([e.v1.ps, e.v2.ps])
+        visibility: show.edges, class: "edge #{e.as}"})
+    for v, j in f.vs
+      setAttrs(v.path, {cx: v.ps[0], cy: v.ps[1], visibility: show.vertices})
+      setAttrs(v.text, {x: v.ps[1], y: v.ps[1], visibility: show.vertices})
+  for c, v of {x: [1,0,0], y: [0,1,0], z: [0,0,1]}
+    end = geom.plus(geom.mul(v, 0.05), cam.c)
+    setAttrs(document.getElementById("a#{c}"), {
+      d: viewer.makePath(viewer.proj(p, cam) for p in [cam.c, end])})


Changed structure.coffee to fit demo.

Changed structure.coffee to fit demo.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/generator-steroids.git/'


Added base parameter in REST.autoRegister

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/renanhangai/servitude.git/'


Add first simple tests (not working yet).

error: pathspec 'src/spec/producttypegenerator.spec.coffee' did not match any file(s) known to git

--- src/spec/producttypegenerator.spec.coffee
+++ src/spec/producttypegenerator.spec.coffee
@@ -0,0 +1,11 @@
+ProductTypeGenerator = require('../lib/producttypegenerator').ProductTypeGenerator
+
+describe 'ProductTypeGenerator', ->
+  beforeEach ->
+    @generator = new ProductTypeGenerator('foo')
+
+  it 'should initialize', ->
+    expect(@generator).toBeDefined()
+
+  it 'should initialize with options', ->
+    expect(@generator._options).toBe 'foo'


impr (modules) Add better default template for module load indicator.


Add email base URI.

Add email base URI.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/philbooth/GitHubReminder.git/'


added helpers

added helpers

error: pathspec 'src/helpers.coffee' did not match any file(s) known to git

--- src/helpers.coffee
+++ src/helpers.coffee
@@ -0,0 +1,8 @@
+module.exports.merge = (a, b) ->
+  x = {}
+  for key, value of a
+    x[key] = value
+  for key, value of b
+    x[key] = value
+
+  x


process.nextTick FTW

process.nextTick FTW

`process.nextTick copyQueue.shift()`
27 Jul 04:05:11 - info: copied 2738 files in 56381ms
27 Jul 04:18:14 - info: copied 1579 files in 2697ms
27 Jul 04:23:30 - info: copied 1579 files in 2585ms
27 Jul 04:49:18 - info: copied 4501 files in 318125ms

`setImmediate copyQueue.shift()`
27 Jul 04:08:16 - info: copied 2738 files in 62688ms
27 Jul 04:16:18 - info: copied 1579 files in 3249ms
27 Jul 04:24:12 - info: copied 1579 files in 3651ms
27 Jul 04:55:27 - info: copied 4501 files in 310449ms

`(copyQueue.shift())()`
27 Jul 04:10:26 - info: copied 2738 files in 61596ms
27 Jul 04:17:27 - info: copied 1579 files in 2564ms
27 Jul 04:22:10 - info: copied 1579 files in 3261ms
27 Jul 04:41:28 - info: copied 4501 files in 342951ms

`setTimeout copyQueue.shift(), 0`
27 Jul 04:12:34 - info: copied 2738 files in 60466ms
27 Jul 04:19:39 - info: copied 1579 files in 12030ms
27 Jul 04:24:58 - info: copied 1579 files in 13887ms

--- src/fs_utils/common.coffee
+++ src/fs_utils/common.coffee
@@ -77,7 +77,7 @@
     output.on 'error', fsStreamErrHandler
     output.on 'finish', ->
       if --copyCounter < 1 and copyQueue.length
-        setImmediate copyQueue.shift()
+        process.nextTick copyQueue.shift()
       callback()
   parentDir = sysPath.dirname(destination)
   exports.exists parentDir, (exists) ->


Issue #1547 'use strict' tests

Issue #1547 'use strict' tests

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/maowug/coffeescript.git/'


Use element.readOnly instead of getAttribute "readonly"

--- lib/dom_utils.coffee
+++ lib/dom_utils.coffee
@@ -72,7 +72,7 @@
             elements.concat areas
           false
         else if (tagName == "input" and DomUtils.isSelectable element) or tagName == "textarea"
-          not (element.disabled or element.hasAttribute "readonly")
+          not (element.disabled or element.readOnly)
         else if (tagName == "input" and element.getAttribute("type")?.toLowerCase() != "hidden") or
                 tagName in ["button", "select"]
           not element.disabled


Add comment

Add comment

--- lib/Serializer.coffee
+++ lib/Serializer.coffee
@@ -17,7 +17,8 @@

   toExternal: (internalObject) -> @transform(internalObject, "toExternal")

-  keymap: -> throw "Implement me! At the very least, I need the mapping between external object id field and our _uid field"
+  # an external object identifier field may be called "id", which conflicts with our PostgreSQL "id" field
+  keymap: -> throw "Implement me! At the very least, map the external object identifier field and internal object _uid field"

   forJSONResponse: ->
     transformers = {}


Social: add a model for channel container


Minor tweak for clarity.

Minor tweak for clarity.

--- pages/vomnibar.coffee
+++ pages/vomnibar.coffee
@@ -29,8 +29,7 @@
       .split(/[\?&]/)
       .map((option) ->
         [name, value] = option.split "="
-        options[name] = value
-        options[name] = unescape(value) if value
+        options[name] = if value? then unescape(value) else true
       )

     # Set boolean options.


Remove double-hash comments.

Remove double-hash comments.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/JoshuaToenyes/stout-core.git/'


user profile component

user profile component

error: pathspec 'src/user/profile.cjsx' did not match any file(s) known to git

--- src/user/profile.cjsx
+++ src/user/profile.cjsx
@@ -0,0 +1,22 @@
+React = require 'react'
+BS = require 'react-bootstrap'
+
+AccountsIframe = require './accounts-iframe-mixin'
+
+UserProfile = React.createClass
+
+  mixins: [AccountsIframe]
+  propTypes:
+    onComplete: React.PropTypes.func.isRequired
+
+  # called by iframe when it's content is loaded and it's ready for requests
+  iFrameReady: -> @sendCommand('loadPage', 'profile')
+
+  render: ->
+    <div className="-user-profile">
+      <i className='close-icon pull-right' onClick={@props.onComplete}/>
+      {@renderIframe()}
+    </div>
+
+
+module.exports = UserProfile


Always load the snapshot range from evercam-media

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-dashboard.git/'


Added jQuery and Turbolinks to JS manifest

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/cobalthq/cobalt-shared.git/'


PrivateMessage: Add ReplyInputWidget

PrivateMessage: Add ReplyInputWidget


#10116: Universal-Analytics-Adapter and bugfix

--- app/assets/javascripts/ga_events.js.coffee
+++ app/assets/javascripts/ga_events.js.coffee
@@ -60,11 +60,14 @@
     data.non_interaction = true
     window.dataLayer.push data

+class GaEvents.GoogleUniversalAnalyticsAdapter
+  push: (h) -> window.ga "send", "event", h.category, h.action, h.label, h.value
+
 class GaEvents.GoogleAnalyticsAdapter
   # Send events non_interactive => no influence on bounce rates
   push: (h) ->
     window._gaq.push(
-      ["_trackEvent", h.action, h.category, h.label, h.value, true])
+      ["_trackEvent", h.category, h.action, h.label, h.value, true])

 class GaEvents.NullAdapter
   push: (obj) -> console.log obj if console?


Improve Documentation

Improve Documentation

--- src/fairy.coffee
+++ src/fairy.coffee
@@ -71,7 +71,7 @@
   client.auth options.password if options.password?
   new Fairy client

-# ### Exception Handling
+# ### Exception & Interruption Handling
 #
 # Use `uncaughtException` and `SIGINT` to provide elegant exception and user
 # interruption handling.
@@ -80,7 +80,7 @@
 # task.
 exiting = off

-# Keep all registered workers of the process in an array, rely on this array to
+# Keep current process's all registered workers an array, rely on this array to
 # count cleaned workers on exiting.
 registered_workers = []

@@ -91,6 +91,12 @@
     registered_worker = registered_worker.split '|'
     console.log "  * Client Id: #{registered_worker[0]}, Task: #{registered_worker[1]}"

+# Fairy will enter cleanup mode before exit when:
+#
+#   + Received `SIGINT` or `SIGUSR2`.
+#   + `uncaughtException` captured.
+#
+# If there's no registered workers, exit directly.
 enter_cleanup_mode = ->
   logging_registered_workers()
   return process.exit() unless registered_workers.length
@@ -111,7 +117,7 @@
   console.log 'Fairy will block all processing groups before exit.'
   enter_cleanup_mode()

-# Say goodbye.
+# Say goodbye on exit.
 process.on 'exit', ->
   console.log "Fairy cleaned up, exiting..."


mission plot controller unit tests

mission plot controller unit tests

error: pathspec 'test/scripts/controllers/missionPlotController.coffee' did not match any file(s) known to git

--- test/scripts/controllers/missionPlotController.coffee
+++ test/scripts/controllers/missionPlotController.coffee
@@ -0,0 +1,30 @@
+describe "missionPlotController", ->
+  beforeEach module 'app'
+  beforeEach inject ($rootScope, $controller, _$httpBackend_) ->
+    loadJSONFixtures 'user.json'
+    loadJSONFixtures 'dseries.json'
+
+    @scope = $rootScope.$new()
+    @user = getJSONFixture 'user.json'
+    @dseries = getJSONFixture 'dseries.json'
+
+    routeParamsStub = jasmine.createSpy('routeParamsStub')
+    routeParamsStub.id = 218
+
+    @missionPlotController = $controller('missionPlotController', { '$scope': @scope, '$routeParams': routeParamsStub })
+    @urlBase = 'http://api.droneshare.com/api/v1'
+    @httpBackend = _$httpBackend_
+    @httpBackend.expectGET("#{@urlBase}/auth/user").respond 200, @user
+    @httpBackend.expectGET("#{@urlBase}/mission/#{routeParamsStub.id}/dseries").respond 200, @dseries
+
+  it 'gets mission record plot data by params', ->
+    expect(@scope.plotData).toEqual {}
+    @scope.$apply()
+    @httpBackend.flush()
+    expect(@scope.plotData).not.toEqual {}
+
+  it 'sets options for flot directive', ->
+    expect(@scope.plotOptions.xaxis.mode).toEqual 'time'
+    expect(@scope.plotOptions.xaxis.timeformat).toEqual '%M:%S'
+    expect(@scope.plotOptions.zoom.interactive).toBeTruthy()
+    expect(@scope.plotOptions.pan.interactive).toBeTruthy()


update tooltip for charts

update tooltip for charts

--- app/assets/javascripts/app/chart.coffee
+++ app/assets/javascripts/app/chart.coffee
@@ -32,7 +32,7 @@
         '<h3>' + moment(d).format('MMMM') + '</h3>'

       chart.tooltip.valueFormatter (d) ->
-        accounting.formatMoney(d, {symbol: '€', format: '%v %s', decimal: ',', thousand: '.'})
+        accounting.formatMoney(d, {symbol: '€', format: '%v %s', decimal: ',', thousand: '.'}) if d

       chart.xAxis
         .tickPadding(10)


Refactors some code for presets in terrain generator

--- app/views/editor/level/modals/TerrainRandomizeModal.coffee
+++ app/views/editor/level/modals/TerrainRandomizeModal.coffee
@@ -50,7 +50,7 @@
   }
 }

-sizes = {
+presetSizes = {
   'small': {
     'x':80
     'y':68
@@ -59,6 +59,9 @@
     'x':160
     'y':136
   }
+}
+
+thangSizes = {
   'floorSize': {
     'x':20
     'y':17
@@ -96,55 +99,55 @@

   randomizeThangs: (presetName, presetSize) ->
     preset = presets[presetName]
-    presetSize = sizes[presetSize]
+    presetSize = presetSizes[presetSize]
     @thangs = []
     @randomizeFloor preset, presetSize
     @randomizeBorder preset, presetSize
     @randomizeDecorations preset, presetSize

   randomizeFloor: (preset, presetSize) ->
-    for i in _.range(0, presetSize.x, sizes.floorSize.x)
-      for j in _.range(0, presetSize.y, sizes.floorSize.y)
+    for i in _.range(0, presetSize.x, thangSizes.floorSize.x)
+      for j in _.range(0, presetSize.y, thangSizes.floorSize.y)
         @thangs.push {
           'id': @getRandomThang(preset.floors)
           'pos': {
-            'x': i + sizes.floorSize.x/2
-            'y': j + sizes.floorSize.y/2
+            'x': i + thangSizes.floorSize.x/2
+            'y': j + thangSizes.floorSize.y/2
           }
         }

   randomizeBorder: (preset, presetSize) ->
-    for i in _.range(0, presetSize.x, sizes.borderSize.x)
-      for j in _.range(sizes.borderSize.thickness)
+    for i in _.range(0, presetSize.x, thangSizes.borderSize.x)
+      for j in _.range(thangSizes.borderSize.thickness)
         @thangs.push {
           'id': @getRandomThang(preset.borders)
           'pos': {
-            'x': i + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2)
-            'y': 0 + _.random(-sizes.borderSize.y/2, sizes.borderSize.y)
+            'x': i + _.random(-thangSizes.borderSize.x/2, thangSizes.borderSize.x/2)
+            'y': 0 + _.random(-thangSizes.borderSize.y/2, thangSizes.borderSize.y)
           }
         }
         @thangs.push {
           'id': @getRandomThang(preset.borders)
           'pos': {
-            'x': i + _.random(-sizes.borderSize.x/2, sizes.borderSize.x/2)
-            'y': presetSize.y + _.random(-sizes.borderSize.y, sizes.borderSize.y/2)
+            'x': i + _.random(-thangSizes.borderSize.x/2, thangSizes.borderSize.x/2)
+            'y': presetSize.y + _.random(-thangSizes.borderSize.y, thangSizes.borderSize.y/2)
           }
         }

-    for i in _.range(0, presetSize.y, sizes.borderSize.y)
+    for i in _.range(0, presetSize.y, thangSizes.borderSize.y)
       for j in _.range(3)
         @thangs.push {
           'id': @getRandomThang(preset.borders)
           'pos': {
-            'x': 0 + _.random(-sizes.borderSize.x/2, sizes.borderSize.x)
-            'y': i + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2)
+            'x': 0 + _.random(-thangSizes.borderSize.x/2, thangSizes.borderSize.x)
+            'y': i + _.random(-thangSizes.borderSize.y/2, thangSizes.borderSize.y/2)
           }
         }
         @thangs.push {
           'id': @getRandomThang(preset.borders)
           'pos': {
-            'x': presetSize.x + _.random(-sizes.borderSize.x, sizes.borderSize.x/2)
-            'y': i + _.random(-sizes.borderSize.y/2, sizes.borderSize.y/2)
+            'x': presetSize.x + _.random(-thangSizes.borderSize.x, thangSizes.borderSize.x/2)
+            'y': i + _.random(-thangSizes.borderSize.y/2, thangSizes.borderSize.y/2)
           }
         }


helper for relative time

helper for relative time

error: pathspec 'app/assets/javascripts/helpers/time_relative.js.coffee' did not match any file(s) known to git

--- app/assets/javascripts/helpers/time_relative.js.coffee
+++ app/assets/javascripts/helpers/time_relative.js.coffee
@@ -0,0 +1,2 @@
+Ember.Handlebars.helper 'timeRelative', (value, options)->
+  moment(value).fromNow()


remove hashtag when on html5 compatable browser

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/ofoso/ofo.git/'


sidebar: add SidebarSectionsView

sidebar: add SidebarSectionsView


Add error for ajax:error when submitting comments

Fixes #13814

--- app/assets/javascripts/notes.js.coffee
+++ app/assets/javascripts/notes.js.coffee
@@ -29,6 +29,9 @@
     # add note to UI after creation
     $(document).on "ajax:success", ".js-main-target-form", @addNote
     $(document).on "ajax:success", ".js-discussion-note-form", @addDiscussionNote
+
+    # catch note ajax errors
+    $(document).on "ajax:error", ".js-main-target-form", @addNoteError

     # change note in UI after update
     $(document).on "ajax:success", "form.edit-note", @updateNote
@@ -309,6 +312,10 @@
   addNote: (xhr, note, status) =>
     @renderNote(note)

+  addNoteError: (xhr, note, status) =>
+    flash = new Flash('Your comment could not be submitted! Please check your network connection and try again.', 'alert')
+    flash.pinTo('.md-area')
+
   ###
   Called in response to the new note form being submitted


middleware to check that user is admin

middleware to check that user is admin

error: pathspec 'client/lib/middleware/admin_only.coffee' did not match any file(s) known to git

--- client/lib/middleware/admin_only.coffee
+++ client/lib/middleware/admin_only.coffee
@@ -0,0 +1,5 @@
+module.exports = adminOnly = (req, res, next) ->
+  if not req.user.details?.type isnt 'Admin'
+    res.err 401, 'Must be an admin or the user being accessed.'
+  else
+    next()


Move click event handler into the same grouped `on` call as the mouse enter/leave events.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/lonelyplanet/rizzo.git/'


added method for getting the current trello user

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/jonasby/trello-sprints.git/'


Visual/edit modes: handle "0" as count prefix, when appropriate.

--- content_scripts/mode_visual_edit.coffee
+++ content_scripts/mode_visual_edit.coffee
@@ -221,8 +221,8 @@
     "(": "backward sentence"
     "}": "forward paragraph"
     "{": "backward paragraph"
+    "0": "backward lineboundary"
     "$": "forward lineboundary"
-    "0": "backward lineboundary"
     "G": "forward documentboundary"
     "gg": "backward documentboundary"

@@ -254,6 +254,10 @@
             if command and (@movements[command] or @commands[command])
               @selection = window.getSelection()
               @keyQueue = ""
+
+              # We need to treat "0" specially.  It can be either a movement, or a continutation of a count
+              # prefix.  Don't treat it as a movement if we already have a count prefix.
+              return @continueBubbling if command == "0" and 0 < @countPrefix

               if @commands[command]
                 @commands[command].call @, @getCountPrefix()


Build: site gulpfile symlink added to boilerplate

error: pathspec 'client/landing/site.boilerplate/gulpfile.coffee' did not match any file(s) known to git


Create application adapter

Create application adapter

error: pathspec 'app/assets/javascripts/store/application_adapter.coffee' did not match any file(s) known to git

--- app/assets/javascripts/store/application_adapter.coffee
+++ app/assets/javascripts/store/application_adapter.coffee
@@ -0,0 +1,5 @@
+Dashboard.ApplicationAdapter = DS.RESTAdapter.extend
+  namespace: 'api'
+
+Dashboard.ApplicationStore = DS.Store.extend
+  adapter: Dashboard.ApplicationAdapter.create()


Show correct data at admin/rooms

Show correct data at admin/rooms

Closes #5620 #5538

--- packages/rocketchat-ui-admin/admin/rooms/adminRooms.coffee
+++ packages/rocketchat-ui-admin/admin/rooms/adminRooms.coffee
@@ -1,3 +1,5 @@
+AdminChatRoom = new Meteor.Collection('rocketchat_room')
+
 Template.adminRooms.helpers
 	isReady: ->
 		return Template.instance().ready?.get()
@@ -10,10 +12,10 @@
 	roomCount: ->
 		return Template.instance().rooms?().count()
 	name: ->
-		# if @t is 'c' or @t is 'p'
-		return @name
-		# else if @t is 'd'
-		# 	return @usernames.join ' x '
+		if @t is 'c' or @t is 'p'
+			return @name
+		else if @t is 'd'
+			return @usernames.join ' x '
 	type: ->
 		if @t is 'c'
 			return TAPi18n.__ 'Channel'
@@ -86,7 +88,7 @@
 		if types.length
 			query['t'] = { $in: types }

-		return ChatRoom.find(query, { limit: instance.limit?.get(), sort: { default: -1, name: 1 } })
+		return AdminChatRoom.find(query, { limit: instance.limit?.get(), sort: { default: -1, name: 1 } })

 	@getSearchTypes = ->
 		return _.map $('[name=room-type]:checked'), (input) -> return $(input).val()


Macro invocations can be macro!(), macro!{} or macro![]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/pyfisch/atom-language-rust.git/'


Remove semicolon

Remove semicolon

[#97185164]

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/netguru/review.git/'


Remove unused functions from Predictor directive

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/UM-USElab/gradecraft-development.git/'


Handle multiple inputs properly for ajax handling.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bmedx/modulestore.git/'


:lipstick:

:lipstick:

--- src/packages/editor-stats/src/editor-stats-view.coffee
+++ src/packages/editor-stats/src/editor-stats-view.coffee
@@ -32,7 +32,7 @@
   @serialize: ->
     @instance.serialize()

-  eventLog: [],
+  eventLog: []

   initialize: (@rootView, @eventLog = {}) ->
     super
@@ -117,7 +117,7 @@
     @.insertBefore @statusBar
     @draw()

-  detach: =>
+  detach: ->
     super
     @rootView.focus()


Move d3 require to top

Move d3 require to top

--- src/packages/editor-stats/src/editor-stats-view.coffee
+++ src/packages/editor-stats/src/editor-stats-view.coffee
@@ -2,6 +2,7 @@
 ScrollView = require 'scroll-view'
 $ = require 'jquery'
 _ = require 'underscore'
+d3 = require 'd3.v3'

 module.exports =
 class EditorStatsView extends ScrollView
@@ -14,7 +15,6 @@
     "#{hour}:#{minute}"

   startDate = new Date
-  d3 = require 'd3.v3'
   x  = d3.scale.ordinal().domain d3.range(hours * 60)
   y  = d3.scale.linear()


Reorganize editor normalizeIndentOnPaste specs

--- spec/text-editor-spec.coffee
+++ spec/text-editor-spec.coffee
@@ -2567,13 +2567,23 @@
             ])

       describe ".pasteText()", ->
+        copyText = (text, {startColumn, textEditor}={}) ->
+          startColumn ?= 0
+          textEditor ?= editor
+          textEditor.setCursorBufferPosition([0, 0])
+          textEditor.insertText(text)
+          numberOfNewlines = text.match(/\n/g)?.length
+          endColumn = text.match(/[^\n]*$/)[0]?.length
+          textEditor.getLastSelection().setBufferRange([[0,startColumn], [numberOfNewlines,endColumn]])
+          textEditor.cutSelectedText()
+
         it "pastes text into the buffer", ->
           atom.clipboard.write('first')
           editor.pasteText()
           expect(editor.lineTextForBufferRow(0)).toBe "var first = function () {"
           expect(editor.lineTextForBufferRow(1)).toBe "  var first = function(items) {"

-        describe "when config.autoIndentOnPaste is true", ->
+        describe "when `autoIndentOnPaste` is true", ->
           beforeEach ->
             atom.config.set("editor.autoIndentOnPaste", true)

@@ -2600,8 +2610,81 @@
               console.log JSON.stringify(editor.lineTextForBufferRow(1))
               expect(editor.lineTextForBufferRow(1)).toBe("    y(); z();")

-        describe "when config.autoIndentOnPaste is false", ->
+        describe "when `autoIndentOnPaste` is false and `normalizeIndentOnPaste` is true", ->
           beforeEach ->
+            atom.config.set('editor.autoIndentOnPaste', false)
+            atom.config.set('editor.normalizeIndentOnPaste', true)
+
+          describe "when the inserted text contains no newlines", ->
+            it "does not adjust the indentation level of the text", ->
+              editor.setCursorBufferPosition([5, 2])
+              editor.insertText("foo", indentBasis: 5)
+              expect(editor.lineTextForBufferRow(5)).toBe "  foo    current = items.shift();"
+
+            it "does not adjust the whitespace if there are preceding characters", ->
+              copyText(" foo")
+              editor.setCursorBufferPosition([5, 30])
+              editor.pasteText()
+
+              expect(editor.lineTextForBufferRow(5)).toBe "      current = items.shift(); foo"
+
+          describe "when the inserted text contains newlines", ->
+            describe "when the cursor is preceded only by whitespace characters", ->
+              it "normalizes indented lines to the cursor's current indentation level", ->
+                copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 2})
+                editor.setCursorBufferPosition([3, 4])
+                editor.pasteText()
+
+                expect(editor.lineTextForBufferRow(3)).toBe "    while (true) {"
+                expect(editor.lineTextForBufferRow(4)).toBe "      foo();"
+                expect(editor.lineTextForBufferRow(5)).toBe "    }"
+                expect(editor.lineTextForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];"
+
+            describe "when the cursor is preceded by non-whitespace characters", ->
+              it "normalizes the indentation level of all lines based on the level of the existing first line", ->
+                copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 0})
+                editor.setCursorBufferPosition([1, Infinity])
+                editor.pasteText()
+
+                expect(editor.lineTextForBufferRow(1)).toBe "  var sort = function(items) {while (true) {"
+                expect(editor.lineTextForBufferRow(2)).toBe "    foo();"
+                expect(editor.lineTextForBufferRow(3)).toBe "  }"
+                expect(editor.lineTextForBufferRow(4)).toBe ""
+
+          describe 'when scoped settings are used', ->
+            coffeeEditor = null
+            beforeEach ->
+              waitsForPromise ->
+                atom.packages.activatePackage('language-coffee-script')
+              waitsForPromise ->
+                atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o
+
+              runs ->
+                atom.config.set('.source.js', 'editor.normalizeIndentOnPaste', true)
+                atom.config.set('.source.coffee', 'editor.normalizeIndentOnPaste', false)
+
+            afterEach: ->
+              atom.packages.deactivatePackages()
+              atom.packages.unloadPackages()
+
+            it "normalizes the indentation level based on scoped settings", ->
+              copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 2, textEditor: coffeeEditor})
+              coffeeEditor.setCursorBufferPosition([4, 4])
+              coffeeEditor.pasteText()
+              expect(coffeeEditor.lineTextForBufferRow(4)).toBe "      while (true) {"
+              expect(coffeeEditor.lineTextForBufferRow(5)).toBe "      foo();"
+              expect(coffeeEditor.lineTextForBufferRow(6)).toBe "    }"
+
+              copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 2})
+              editor.setCursorBufferPosition([3, 4])
+              editor.pasteText()
+              expect(editor.lineTextForBufferRow(3)).toBe "    while (true) {"
+              expect(editor.lineTextForBufferRow(4)).toBe "      foo();"
+              expect(editor.lineTextForBufferRow(5)).toBe "    }"
+
+        describe "when `autoIndentOnPaste` and `normalizeIndentOnPaste` are both false", ->
+          beforeEach ->
+            atom.config.set('editor.normalizeIndentOnPaste', false)
             atom.config.set("editor.autoIndentOnPaste", false)

           it "does not auto-indent the pasted text", ->
@@ -2610,6 +2693,14 @@
             editor.pasteText()
             expect(editor.lineTextForBufferRow(5)).toBe("console.log(x);")
             expect(editor.lineTextForBufferRow(6)).toBe("console.log(y);")
+
+          it "does not normalize the indentation level of the text", ->
+            copyText("   function() {\nvar cool = 1;\n  }\n")
+            editor.setCursorBufferPosition([5, 2])
+            editor.pasteText()
+            expect(editor.lineTextForBufferRow(5)).toBe "     function() {"
+            expect(editor.lineTextForBufferRow(6)).toBe "var cool = 1;"
+            expect(editor.lineTextForBufferRow(7)).toBe "  }"

         describe 'when the clipboard has many selections', ->
           it "pastes each selection separately into the buffer", ->
@@ -3264,16 +3355,6 @@
         expect(editor.tokenizedLineForScreenRow(0).tokens.length).toBeGreaterThan 1

   describe "auto-indent", ->
-    copyText = (text, {startColumn, textEditor}={}) ->
-      startColumn ?= 0
-      textEditor ?= editor
-      textEditor.setCursorBufferPosition([0, 0])
-      textEditor.insertText(text)
-      numberOfNewlines = text.match(/\n/g)?.length
-      endColumn = text.match(/[^\n]*$/)[0]?.length
-      textEditor.getLastSelection().setBufferRange([[0,startColumn], [numberOfNewlines,endColumn]])
-      textEditor.cutSelectedText()
-
     describe "editor.autoIndent", ->
       describe "when editor.autoIndent is false (default)", ->
         describe "when `indent` is triggered", ->
@@ -3403,87 +3484,6 @@
           coffeeEditor.setCursorBufferPosition([1, 18])
           coffeeEditor.insertText("\n")
           expect(coffeeEditor.lineTextForBufferRow(2)).toBe ""
-
-    describe "editor.normalizeIndentOnPaste", ->
-      beforeEach ->
-        atom.config.set('editor.autoIndentOnPaste', false)
-        atom.config.set('editor.normalizeIndentOnPaste', true)
-
-      it "does not normalize the indentation level of the text when editor.normalizeIndentOnPaste is false", ->
-        copyText("   function() {\nvar cool = 1;\n  }\n")
-        atom.config.set('editor.normalizeIndentOnPaste', false)
-        editor.setCursorBufferPosition([5, 2])
-        editor.pasteText()
-        expect(editor.lineTextForBufferRow(5)).toBe "     function() {"
-        expect(editor.lineTextForBufferRow(6)).toBe "var cool = 1;"
-        expect(editor.lineTextForBufferRow(7)).toBe "  }"
-
-      describe "when the inserted text contains no newlines", ->
-        it "does not adjust the indentation level of the text", ->
-          editor.setCursorBufferPosition([5, 2])
-          editor.insertText("foo", indentBasis: 5)
-          expect(editor.lineTextForBufferRow(5)).toBe "  foo    current = items.shift();"
-
-        it "does not adjust the whitespace if there are preceding characters", ->
-          copyText(" foo")
-          editor.setCursorBufferPosition([5, 30])
-          editor.pasteText()
-
-          expect(editor.lineTextForBufferRow(5)).toBe "      current = items.shift(); foo"
-
-      describe "when the inserted text contains newlines", ->
-        describe "when the cursor is preceded only by whitespace characters", ->
-          it "normalizes indented lines to the cursor's current indentation level", ->
-            copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 2})
-            editor.setCursorBufferPosition([3, 4])
-            editor.pasteText()
-
-            expect(editor.lineTextForBufferRow(3)).toBe "    while (true) {"
-            expect(editor.lineTextForBufferRow(4)).toBe "      foo();"
-            expect(editor.lineTextForBufferRow(5)).toBe "    }"
-            expect(editor.lineTextForBufferRow(6)).toBe "var pivot = items.shift(), current, left = [], right = [];"
-
-        describe "when the cursor is preceded by non-whitespace characters", ->
-          it "normalizes the indentation level of all lines based on the level of the existing first line", ->
-            copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 0})
-            editor.setCursorBufferPosition([1, Infinity])
-            editor.pasteText()
-
-            expect(editor.lineTextForBufferRow(1)).toBe "  var sort = function(items) {while (true) {"
-            expect(editor.lineTextForBufferRow(2)).toBe "    foo();"
-            expect(editor.lineTextForBufferRow(3)).toBe "  }"
-            expect(editor.lineTextForBufferRow(4)).toBe ""
-
-      describe 'when scoped settings are used', ->
-        coffeeEditor = null
-        beforeEach ->
-          waitsForPromise ->
-            atom.packages.activatePackage('language-coffee-script')
-          waitsForPromise ->
-            atom.project.open('coffee.coffee', autoIndent: false).then (o) -> coffeeEditor = o
-
-          runs ->
-            atom.config.set('.source.js', 'editor.normalizeIndentOnPaste', true)
-            atom.config.set('.source.coffee', 'editor.normalizeIndentOnPaste', false)
-
-        afterEach: ->
-          atom.packages.deactivatePackages()
-          atom.packages.unloadPackages()
-
-        it "normalizes the indentation level based on scoped settings", ->
-          copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 2, textEditor: coffeeEditor})
-          coffeeEditor.setCursorBufferPosition([4, 4])
-          coffeeEditor.pasteText()
-          expect(coffeeEditor.lineTextForBufferRow(4)).toBe "      while (true) {"
-          expect(coffeeEditor.lineTextForBufferRow(5)).toBe "      foo();"
-          expect(coffeeEditor.lineTextForBufferRow(6)).toBe "    }"
-
-          copyText("    while (true) {\n      foo();\n    }\n", {startColumn: 2})
-          editor.setCursorBufferPosition([3, 4])
-          editor.pasteText()
-          expect(editor.lineTextForBufferRow(3)).toBe "    while (true) {"
-          expect(editor.lineTextForBufferRow(4)).toBe "      foo();"
-          expect(editor.lineTextForBufferRow(5)).toBe "    }"

     it "autoIndentSelectedRows auto-indents the selection", ->
       editor.setCursorBufferPosition([2, 0])


Add common plugin spec document.

Add common plugin spec document.

error: pathspec 'docs/nwdrome_common_plugin_spec.coffee' did not match any file(s) known to git

--- docs/nwdrome_common_plugin_spec.coffee
+++ docs/nwdrome_common_plugin_spec.coffee
@@ -0,0 +1,148 @@
+# nwdrome-renderer-plugin example
+# Copyright 2014, Ragg(@_ragg_)
+
+#
+# Plugin interface specification
+#
+
+# Register plugin
+#   JSdrome.addRendererPlugin(function)
+#   JSdrome.addCommonPlugin(insert_flag, function)
+#
+#   addRendererPlugin
+#       function    plugin constructor factory (returns constructor)
+#
+#   addCommonPlugin
+#       string      BEFORE_FILTER|AFTER_FILTER  Specify common plugin rendering timing.
+#       function    plugin constructor factory (returns constructor)
+#
+#   addEffectorPlugin
+#       function    plugin constructor factory (returns constructor)
+#
+
+
+
+##
+# Renderer plugin (& common plugin) structure
+#
+JSdrome.addRendererPlugin (pluginConfig)->
+    class RendererPlugin
+
+        # Plugin detail setting to instance or prototype
+        id          : "vendor.Plugin-ID"
+        description : "Plugin \nDescription"
+        thumbnail   : "path/to/thumbnail.image" # relative from plugin root
+
+        # @param HTMLCanvasElement Rendering result destination canvas
+        constructor : (canvas) ->
+            # do initialize
+            @_canvas = canvas
+            @_ctx    = canvas.getContext "2d"
+
+        onStart     : ->
+            # Call when starting draw.
+
+        onStop      : ->
+            # Call when stopping draw.
+
+        # @param float Current opacity(0.0 - 1.0)
+        onFade      : (opacity) ->
+            # Call when opacity changed.
+
+        # @param float Realtime volume
+        # @param float Part volume
+        onAudio     : (moment, period) ->
+            # The state of the audio volume will be notified.
+
+        # @param int new width
+        # @param int new height
+        onResize    : (width, height) ->
+            # Be notified of canvas size change.
+
+        onTimer     : ->
+            # Call from jsdrome's requestAnimationFrame.
+            # Will rendering process write here.
+
+        # @param int keyCode
+        onKeydown   : (keyCode) ->
+            # If plugin in foreground, will be notified of key input.
+
+        # Unknown...
+        onMidi      : (a1, a2, a3) ->
+            # Be notified of midi input
+
+    # return constructor
+    return RendererPlugin
+
+
+
+# nwdrome-common-plugin spec
+# Copyright 2014, Ragg(@_ragg_)
+
+###
+
+# Nwdrome common plugin specification
+
+## Register plugin
+Call `nwdrome.plugin.addCommon` with `factory function`
+Factory function given plugin config object.
+
+Below Plugin config object properties.
+
+- appUrl  :string  Application(nwdrome) root path. End with "/"
+- url     :string  Plugin root path. End with "/"
+
+## Plugin information
+Plugin constructor must having plugin info properties!!
+
+- id            :string  Plugin ID (example: "yourname.pluginname")
+- description   :string  Plugin description.
+- thumbnail     :string  Path to plugin thumbnail.
+###
+
+
+###
+Exapmle
+###
+nwdrome.plugin.addCommon (pluginConfig)->
+
+    class CommonPlugin
+        # Plugin detail set to plugin constructor
+        @id          : "vendor.Plugin-ID"
+        @description : "Plugin \nDescription"
+        @thumbnail   : pluginConfig.url + "path/to/thumbnail.image"
+
+
+        constructor : () ->
+
+        onStart     : () ->
+            # Call when start.
+
+        onStop      : () ->
+            # Call when stop.
+
+        # @param float Realtime volume
+        # @param float Part volume
+        onAudio     : (moment, period) ->
+            # The state of the audio volume will be notified.
+
+        # @param int new width
+        # @param int new height
+        onResize    : (width, height) ->
+            # Be notified of canvas size change.
+
+        onTimer     : ->
+            # Call from nwdrome when requestAnimationFrame fired.
+            # Will rendering process write here.
+
+        # @param int keyCode
+        onKeydown   : (keyCode) ->
+            # Call on key input and route to this instance.
+
+
+        onMidi      : (a1, a2, a3) ->
+            # Be notified of midi input(maybe...)
+
+    # return constructor
+    return CommonPlugin
+


Remove some log messages

Remove some log messages

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/MicrosmartSA/ubiquity-ui.git/'


Add LikeView, we can use it whenever we need Like buttons :)

error: pathspec 'client/landing/app/CommonViews/LikeView.coffee' did not match any file(s) known to git

--- client/landing/app/CommonViews/LikeView.coffee
+++ client/landing/app/CommonViews/LikeView.coffee
@@ -0,0 +1,87 @@
+class LikeView extends KDView
+
+  constructor:(options={}, data)->
+
+    options.tagName  or= 'span'
+    options.cssClass or= 'like-view'
+
+    super options, data
+
+    @_lastUpdatedCount = -1
+    @_currentState = no
+
+    @likeCount    = new ActivityLikeCount
+      tooltip     :
+        gravity   : "se"
+        title     : ""
+      bind        : "mouseenter"
+      mouseenter  : => @fetchLikeInfo()
+      attributes  :
+        href      : "#"
+        title     : "Click to view..."
+      click       : =>
+        if data.meta.likes > 0
+          data.fetchLikedByes {},
+              sort : timestamp : -1
+            , (err, likes) =>
+              new FollowedModalView {title:"Members who liked #{data.body}"}, likes
+      , data
+
+    @likeLink = new ActivityActionLink
+    @setTemplate @pistachio()
+
+    data.checkIfLikedBefore (err, likedBefore)=>
+      @likeLink.updatePartial if likedBefore then "Unlike" else "Like"
+      @_currentState = likedBefore
+
+  fetchLikeInfo:->
+
+    data = @getData()
+
+    return if @_lastUpdatedCount is data.meta.likes
+    @likeCount.updateTooltip { title: "Loading..." }
+
+    if data.meta.likes is 0
+      @likeLink.updatePartial "Like"
+      return
+
+    data.fetchLikedByes {},
+      limit : 3
+      sort  : timestamp : -1
+    , (err, likes) =>
+
+      peopleWhoLiked   = []
+
+      if likes
+
+        likes.forEach (item)=>
+          if peopleWhoLiked.length < 3
+            {firstName, lastName} = item.profile
+            peopleWhoLiked.push "" + firstName + " " + lastName + ""
+          else return
+
+        sep = ', '
+        tooltip =
+          switch data.meta.likes
+            when 0 then ""
+            when 1 then "#{peopleWhoLiked[0]}"
+            when 2 then "#{peopleWhoLiked[0]} and #{peopleWhoLiked[1]}"
+            when 3 then "#{peopleWhoLiked[0]}#{sep}#{peopleWhoLiked[1]} and #{peopleWhoLiked[2]}"
+            else "#{peopleWhoLiked[0]}#{sep}#{peopleWhoLiked[1]}#{sep}#{peopleWhoLiked[2]} and #{data.meta.likes - 3} more.</stron>"
+
+        @likeCount.updateTooltip { title: tooltip }
+        @_lastUpdatedCount = likes.length
+
+  click:(event)->
+
+    if $(event.target).is("a.action-link")
+      if KD.isLoggedIn()
+        @getData().like (err)=>
+          if err
+            log "Something went wrong while like:", err
+          else
+            @_currentState = not @_currentState
+            @likeLink.updatePartial if @_currentState is yes then "Unlike" else "Like"
+
+  pistachio:->
+    """{{> @likeLink}}{{> @likeCount}}"""


add onToggle callback to hist mode setting

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/xaun/impac-angular.git/'


filefinder ignores directories

filefinder ignores directories

--- extensions/filefinder/filefinder.coffee
+++ extensions/filefinder/filefinder.coffee
@@ -1,4 +1,5 @@
 _ = require 'underscore'
+fs = require 'fs'

 Extension = require 'extension'
 ModalSelector = require 'modal-selector'
@@ -10,7 +11,8 @@
     atom.on 'project:open', @startup

   startup: (@project) =>
-    @pane = new ModalSelector @project.allURLs()
+    @pane = new ModalSelector _.reject @project.allURLs(), ({url}) ->
+      fs.isDirectory url

   toggle: ->
     @pane?.toggle()


Use coffee syntax

Use coffee syntax


Update example.coffee 最高気温追加

Update example.coffee
最高気温追加

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/askdkc/cb_slackbot.git/'


Client: Activity: Created CreateNewChannelParticipantsSearchQueryStore.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


Update copy task

Update copy task

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/frostney/shopkeeper.git/'


Constrain the end of the old screen range to the lastRenderedScreenRow, not maxScreenRow

Constraining the end of the new range max screen row instead of the last rendered row is what allows the buffer to get longer when the last rendered screen row is smaller than the last visible screen row. But constraining the end of the old range to this was causing artifacts. The old range should always be constrained to what is rendered on screen now, not what "could be". What "could be" is the domain of the new range.

--- src/app/editor.coffee
+++ src/app/editor.coffee
@@ -466,9 +466,9 @@
         oldScreenRange.end.row += delta

       newScreenRange.start.row = Math.max(newScreenRange.start.row, @firstRenderedScreenRow)
+      oldScreenRange.end.row = Math.min(oldScreenRange.end.row, @lastRenderedScreenRow)
       oldScreenRange.start.row = Math.max(oldScreenRange.start.row, @firstRenderedScreenRow)
       newScreenRange.end.row = Math.min(newScreenRange.end.row, maxEndRow)
-      oldScreenRange.end.row = Math.min(oldScreenRange.end.row, maxEndRow)

       lineElements = @buildLineElements(newScreenRange.start.row, newScreenRange.end.row)
       @replaceLineElements(oldScreenRange.start.row, oldScreenRange.end.row, lineElements)


renamed AddonHelper to ClassHelper

renamed AddonHelper to ClassHelper

error: pathspec 'src/ClassHelper.coffee' did not match any file(s) known to git

--- src/ClassHelper.coffee
+++ src/ClassHelper.coffee
@@ -0,0 +1,23 @@
+# Credits to "The Little Book on CoffeeScript"
+# @ https://arcturo.github.io/library/coffeescript/03_classes.html
+
+moduleKeywords = ['extended', 'included']
+
+class ClassHelper
+
+  @extend: (obj) ->
+    for key, value of obj when key not in moduleKeywords
+      @[key] = value
+
+    obj.extended?.apply(@)
+    this
+
+  @include: (obj) ->
+    for key, value of obj when key not in moduleKeywords
+      @::[key] = value
+
+    obj.included?.apply(@)
+    this
+
+
+module.exports = ClassHelper


Remove missing sections

Remove missing sections

--- resources/assets/coffee/react/profile-page/extra.coffee
+++ resources/assets/coffee/react/profile-page/extra.coffee
@@ -81,7 +81,7 @@
         el 'div',
           className: tabsClasses
           'data-sticky-header-id': 'profile-extra-tabs'
-          ['recent_activities', 'historical', 'beatmaps', 'kudosu', 'achievements'].map (m) =>
+          ['recent_activities', 'kudosu'].map (m) =>
             el ProfilePage.ExtraTab, key: m, mode: m, currentMode: @state.mode

       el ProfilePage.RecentActivities


sidebar: create SidebarSections component

error: pathspec 'client/activity/lib/components/sidebarsections/index.coffee' did not match any file(s) known to git

--- client/activity/lib/components/sidebarsections/index.coffee
+++ client/activity/lib/components/sidebarsections/index.coffee
@@ -0,0 +1,31 @@
+kd                     = require 'kd'
+React                  = require 'kd-react'
+ActivityFlux           = require 'activity/flux'
+KDReactorMixin         = require 'app/flux/reactormixin'
+SidebarChannelsSection = require 'activity/components/sidebarchannelssection'
+
+
+module.exports = class SidebarSections extends React.Component
+
+  @include [KDReactorMixin]
+
+  { getters } = ActivityFlux
+
+  getDataBindings: ->
+    return {
+      publicChannels: getters.followedPublicChannelThreads
+      selectedThreadId: getters.selectedChannelThreadId
+    }
+
+
+  renderChannelsSection: ->
+    <SidebarChannelsSection
+      threads={@state.publicChannels}
+      selectedId={@state.selectedThreadId} />
+
+
+  render: ->
+    <div className="SidebarSections">
+      {@renderChannelsSection()}
+    </div>
+


Add game class

Add game class

error: pathspec 'public/javascripts/game.photography.coffee' did not match any file(s) known to git

--- public/javascripts/game.photography.coffee
+++ public/javascripts/game.photography.coffee
@@ -0,0 +1,6 @@
+jQuery(document).ready ->
+  class photographyGame
+    constructor: (@debug, @map) ->
+
+    init: () ->
+  return


fix for properties if used by more than one multipleter

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/saijim/Multipleter.git/'


Stop app specs from running.

Stop app specs from running.

These will be the last thing to implement.

--- spec/atom/app-spec.coffee
+++ spec/atom/app-spec.coffee
@@ -1,7 +1,7 @@
 App = require 'app'
 fs = require 'fs'

-describe "App", ->
+xdescribe "App", ->
   app = null

   beforeEach ->


See #96. Add example CJSX file

See #96. Add example CJSX file

error: pathspec 'spec/samples/example.cjsx' did not match any file(s) known to git

--- spec/samples/example.cjsx
+++ spec/samples/example.cjsx
@@ -0,0 +1,8 @@
+Car = React.createClass
+  render: ->
+    <Vehicle doors={4} locked={isLocked()} data-colour="red" on>
+      <Parts.FrontSeat />
+      <Parts.BackSeat />
+
Which seat can I take? {@props?.seat or 'none'}

+      {# also, this is a comment }
+    </Vehicle>


Fix text-editor-component-spec failure

Fix text-editor-component-spec failure

Grouping intervals are exclusive now. It shouldn't affect anybody
since it's a one-millisecond change to the meaning of
grouping-interval, but it required changing some time intervals
in this spec.

--- spec/text-editor-component-spec.coffee
+++ spec/text-editor-component-spec.coffee
@@ -2340,10 +2340,10 @@
       editor.setText("")
       componentNode.dispatchEvent(buildTextInputEvent(data: 'x', target: inputNode))

-      currentTime += 100
+      currentTime += 99
       componentNode.dispatchEvent(buildTextInputEvent(data: 'y', target: inputNode))

-      currentTime += 100
+      currentTime += 99
       componentNode.dispatchEvent(new CustomEvent('editor:duplicate-lines', bubbles: true, cancelable: true))

       currentTime += 101