Changed Dutch (NL) ambassador_summary to match the English version

--- app/locale/nl.coffee
+++ app/locale/nl.coffee
@@ -334,7 +334,7 @@
     art_paragraph_1: "Voor toekenning, gelieve de naam en link naar codecombat.com te plaatsen waar dit passend is voor de vorm waarin het voorkomt. Bijvoorbeeld:"
     use_list_1: "Wanneer gebruikt in een film of een ander spel, voeg codecombat.com toe in de credits."
     use_list_2: "Wanneer toegepast op een website, inclusief een link naar het gebruik, bijvoorbeeld onderaan een afbeelding. Of in een algemene webpagina waar je eventueel ook andere Create Commons werken en open source software vernoemd die je gebruikt op de website. Iets dat alreeds duidelijk is gespecificeerd met CodeCombat, zoals een blog artikel, dat CodeCombat vernoemt, heeft geen aparte vermelding nodig."
-    art_paragraph_2: "Wanneer de gebruikte inhoud is gemaakt door een gebruiker van codecombat.com, vernoem hem/haar in plaats van ons. en volg verspreidingsaanwijzingen van die brons als die er zijn."
+    art_paragraph_2: "Wanneer de gebruikte inhoud is gemaakt door een gebruiker van codecombat.com, vernoem hem/haar in plaats van ons en volg verspreidingsaanwijzingen van die brons als die er zijn."
     rights_title: "Rechten Voorbehouden"
     rights_desc: "Alle rechten zijn voorbehouden voor de Levels. Dit omvat:"
     rights_scripts: "Scripts"
@@ -342,15 +342,15 @@
     rights_description: "Beschrijvingen"
     rights_writings: "Literaire werken"
     rights_media: "Media (geluid, muziek) en eender welke creatieve inhoud, specifiek gemaakt voor dat level en niet verkrijgbaar bij het maken van levels."
-    rights_clarification: "Om het duidelijk te maken, iets dat beschikbaar is in de Level editor voor het maken van level, valt onder de CC licentie. Terwijl de inhoud gemaakt met de Level Editor of geupload in de loop van de creatie van de levels, hier not onder vallen."
+    rights_clarification: "Om het duidelijk te maken, iets dat beschikbaar is in de Level editor voor het maken van levels, valt onder de CC licentie. Terwijl de inhoud gemaakt met de Level Editor of geüpload in de loop van de creatie van de levels, hier niet onder vallen."
     nutshell_title: "In een notendop"
-    nutshell_description: "Alle midellen die wij aanbieden in de Level Editor zijn gratis te gebruiken om levels aan te maken. Maar wij behouden ons het recht om levels die gemaakt zijn op codecombat.com te beperken, en hier in de toekomst geld voor te vragen, moest dat ooit gebeuren."
+    nutshell_description: "Alle middelen die wij aanbieden in de Level Editor zijn gratis te gebruiken om levels aan te maken. Wij behouden ons echter het recht voor om levels die gemaakt zijn op codecombat.com te beperken, en hier in de toekomst geld voor te vragen, moest dat ooit gebeuren."
     canonical: "De Engelse versie van dit document is de definitieve en kanonieke versie. Bij verschillen tussen vertalingen heeft de Engelse versie voorrang."

   contribute:
     page_title: "Bijdragen"
     character_classes_title: "Karakter Klassen"
-    introduction_desc_intro: "We hebben hoge verwachten over CodeCombat."
+    introduction_desc_intro: "We hebben hoge verwachtingen over CodeCombat."
     introduction_desc_pref: "We willen zijn waar programmeurs van alle niveaus komen om te leren en samen te spelen, anderen introduceren aan de wondere wereld van code, en de beste delen van de gemeenschap te reflecteren. We kunnen en willen dit niet alleen doen; wat projecten zoals GitHub, Stack Overflow en Linux groots en succesvol maken, zijn de mensen die deze software gebruiken en verbeteren. Daartoe, "
     introduction_desc_github_url: "CodeCombat is volledig open source"
     introduction_desc_suf: ", en we mikken ernaar om zoveel mogelijk manieren mogelijk maken voor u om deel te nemen en dit project van zowel jou als ons te maken."
@@ -360,7 +360,7 @@
     alert_account_message_pref: "Om je te abonneren voor de klasse e-mails, moet je eerst "
     alert_account_message_suf: "."
     alert_account_message_create_url: "een account aanmaken"
-    archmage_summary: "Geïnteresserd in werken aan game graphics, user interface design, database- en serverorganisatie, multiplayer networking, physics, geluid of game engine  prestaties? Wil jij helpen een game te bouwen wat anderen leert waar jij goed in bent? We moeten nog veel doen en als jij een ervaren programmeur bent en wil ontwikkelen voor CodeCombat, dan is dit de klasse voor jou. We zouden graag je hulp hebben bij het maken van de beste programmeergame ooit."
+    archmage_summary: "Geïnteresserd in werken aan game graphics, user interface design, database- en serverorganisatie, multiplayer networking, physics, geluid of game engine prestaties? Wil jij helpen een game te bouwen wat anderen leert waar jij goed in bent? We moeten nog veel doen en als jij een ervaren programmeur bent en wil ontwikkelen voor CodeCombat, dan is dit de klasse voor jou. We zouden graag je hulp hebben bij het maken van de beste programmeergame ooit."
     archmage_introduction: "Een van de beste aspecten aan het maken van spelletjes is dat zij zoveel verschillende zaken omvatten. Visualisaties, geluid, real-time netwerken, sociale netwerken, en natuurlijk veel van de voorkomende aspecten van programmeren, van low-level database beheer en server administratie tot gebruiksvriendelijke interfaces maken. Er is veel te doen, en als jij een ervaren programmeur bent met de motivatie om je handen veel te maken met CodeCombat, dan ben je de tovenaar die wij zoeken! We zouden graag jouw help hebben met het bouwen aan het allerbeste programmeerspel ooit."
     class_attributes: "Klasse kenmerken"
     archmage_attribute_1_pref: "Ervaring met "
@@ -386,7 +386,7 @@
     artisan_join_step1: "Lees de documentatie."
     artisan_join_step2: "Maak een nieuw level en bestudeer reeds bestaande levels."
     artisan_join_step3: "Praat met ons in ons publieke (Engelstalige) HipChat kanaal voor hulp. (optioneel)"
-    artisan_join_step4: "Maak een bericht over jou level op ons forum voor feedback."
+    artisan_join_step4: "Maak een bericht over jouw level op ons forum voor feedback."
     more_about_artisan: "Leer meer over hoe je een Creatieve Ambachtsman kan worden."
     artisan_subscribe_desc: "Ontvang e-mails met nieuws over de Level Editor."
     adventurer_sumamry: "Laten we duidelijk zijn over je rol: jij bent de tank. Jij krijgt de zware klappen te verduren. We hebben mensen nodig om spiksplinternieuwe levels te proberen en te kijken hoe deze beter kunnen. De pijn zal groot zijn, het maken van een goede game is een lang proces en niemand doet het de eerste keer goed. Als jij dit kan verduren en een hoge constitution score hebt, dan is dit de klasse voor jou."
@@ -403,7 +403,7 @@
     scribe_introduction_pref: "CodeCombat is meer dan slechts een aantal levels, het zal ook een bron van kennis kennis zijn en een wiki met programmeerconcepten waar levels op in kunnen gaan. Op die manier zal elk Ambachtslied niet in detail hoeven uit te leggen wat een vergelijkingsoperator is, maar een link kunnen geven naar een artikel wat deze informatie bevat voor de speler. Net zoiets als het  "
     scribe_introduction_url_mozilla: "Mozilla Developer Network"
     scribe_introduction_suf: " heeft gebouwd. Als jij het leuk vindt om programmeerconcepten uit te leggen in Markdown-vorm, dan is deze klasse wellicht iets voor jou."
-    scribe_attribute_1: "Taal-skills zijn praktisch alles wat je nodig hebt. Niet alleen grammatica of spelling, maar ook moeilijke ideas overbrengen aan anderen."
+    scribe_attribute_1: "Taal-skills zijn praktisch alles wat je nodig hebt. Niet alleen grammatica of spelling, maar ook moeilijke ideeën overbrengen aan anderen."
     contact_us_url: "Contacteer ons"
     scribe_join_description: "vertel ons wat over jezelf, je ervaring met programmeren en over wat voor soort dingen je graag zou schrijven. Verder zien we wel!"
     more_about_scribe: "Leer meer over het worden van een ijverige Klerk."
@@ -412,22 +412,22 @@
     diplomat_summary: "Er is grote interesse in CodeCombat in landen waar geen Engels wordt gesproken! We zijn op zoek naar vertalers wie tijd willen spenderen aan het vertalen van de site's corpus aan woorden zodat CodeCombat zo snel mogelijk toegankelijk wordt voor heel de wereld. Als jij wilt helpen met CodeCombat internationaal maken, dan is dit de klasse voor jou."
     diplomat_introduction_pref: "Dus, als er iets is wat we geleerd hebben van de "
     diplomat_launch_url: "release in oktober"
-    diplomat_introduction_suf: "dan is het wel dat er een significante interesse is in CodeCombat in andere landen, vooral Brazilïe! We zijn een corps aan vertalers aan het creëren dat ijverig de ene set woorden in een andere omzet om CodeCombat zo toegankelijk te maken als mogelijk in hel de wereld. Als jij het leuk vindt glimpsen op te vangen van aankomende content en deze levels zo snel mogelijk naar je landgenoten te krijgen, dan is dit de klasse voor jou."
-    diplomat_attribute_1: "Vloeiend Engels en de taal waar naar je wilt vertalen kunnen spreken. Wanneer je moeilijke ideas wilt overbrengen, is het belangrijk beide goed te kunnen!"
+    diplomat_introduction_suf: "dan is het wel dat er een significante interesse is in CodeCombat in andere landen, vooral Brazilië! We zijn een corps aan vertalers aan het creëren dat ijverig de ene set woorden in een andere omzet om CodeCombat zo toegankelijk te maken als mogelijk in heel de wereld. Als jij het leuk vindt glimpsen op te vangen van aankomende content en deze levels zo snel mogelijk naar je landgenoten te krijgen, dan is dit de klasse voor jou."
+    diplomat_attribute_1: "Vloeiend Engels en de taal waar naar je wilt vertalen kunnen spreken. Wanneer je moeilijke ideeën wilt overbrengen, is het belangrijk beide goed te kunnen!"
     diplomat_join_pref_github: "Vind jouw taal haar locale bestand "
     diplomat_github_url: "op GitHub"
-    diplomat_join_suf_github: ", edit het online, en submit een pull request. Daarnaast kun je hieronder aanvinken alsj e up-to-date wilt worden gehouden met nieuwe internationalisatie-ontwikkelingen."
+    diplomat_join_suf_github: ", edit het online, en submit een pull request. Daarnaast kun je hieronder aanvinken als je up-to-date wilt worden gehouden met nieuwe internationalisatie-ontwikkelingen."
     more_about_diplomat: "Leer meer over het worden van een geweldige Diplomaat"
     diplomat_subscribe_desc: "Ontvang e-mails over i18n ontwikkelingen en levels om te vertalen."
-    ambassador_summary: "We proberen een gemeenschap te bouwen en elke gemeenschap heeft een supportteam nodig wanneer er problemen zijn. We hebben chats, e-mails en sociale netwerken met een hoop mensen om mee te praten en wie je kunt helpen bekend te worden met het spel en er van te leren. Als jij mensen wilt helpen betrokken te raken en plezier te hebben, én een goed gevoel van de levenslijn van CodeCombat te krijgen en waar we naar toe gaan, dan is dit wellicht de klasse voor jou."
+    ambassador_summary: "We proberen een gemeenschap te bouwen en elke gemeenschap heeft een supportteam nodig wanneer er problemen zijn. We hebben chats, e-mails en sociale netwerken zodat onze gebruikers het spel kunnen leren kennen. Als jij mensen wilt helpen betrokken te raken, plezier te hebben en wat te leren programmeren, dan is dit wellicht de klasse voor jou."
     ambassador_attribute_1: "Communicatieskills. Problemen die spelers hebben kunnen identificeren en ze helpen deze op te lossen. Verder zul je ook de rest van ons geïnformeerd houden over wat de spelers zeggen, wat ze leuk vinden, wat ze minder vinden en waar er meer van moet zijn!"
     ambassador_join_desc: "vertel ons wat over jezelf, wat je hebt gedaan en wat je graag zou doen. We zien verder wel!"
     ambassador_join_note_strong: "Opmerking"
     ambassador_join_note_desc: "Een van onze topprioriteiten is om een multiplayer te bouwen waar spelers die moeite hebben een level op te lossen een wizard met een hoger level kunnen oproepen om te helpen. Dit zal een goede manier zijn voor ambassadeurs om hun ding te doen. We houden je op de hoogte!"
     more_about_ambassador: "Leer meer over het worden van een behulpzame Ambassadeur"
     ambassador_subscribe_desc: "Ontvang e-mails met updates over ondersteuning en multiplayer-ontwikkelingen."
-    counselor_summary: "Geen van de rollen hierboven in jouw interessegebied? Maak je geen zorgen, we zijn op zoek naar iedereen die wil helpen met het ontwikkelen van CodeCombat! Als je geïnteresseerd bent in lesgeven, gameontwikkeling, open source management of iets anders waarvan je denk dat het relevant voor ons is, dan is dit de klasse voor jou."
-    counselor_introduction_1: "Heb jij levenservaring? Een afwijkend perspectief op zaken die ons kunnen helpen CodeCombat te vormen? Van alle rollen neemt deze wellicht de minste tijd in, maar individiueel maak je misschien het grootste verschil. We zijn op zoek naar wijze tovenaars, vooral in het gebied van lesgeven, gameontwikkeling, open source projectmanagement, technische recrutering, ondernemerschap of design."
+    counselor_summary: "Geen van de rollen hierboven in jouw interessegebied? Maak je geen zorgen, we zijn op zoek naar iedereen die wil helpen met het ontwikkelen van CodeCombat! Als je geïnteresseerd bent in lesgeven, gameontwikkeling, open source management of iets anders waarvan je denkt dat het relevant voor ons is, dan is dit de klasse voor jou."
+    counselor_introduction_1: "Heb jij levenservaring? Een afwijkend perspectief op zaken die ons kunnen helpen CodeCombat te vormen? Van alle rollen neemt deze wellicht de minste tijd in, maar individueel maak je misschien het grootste verschil. We zijn op zoek naar wijze tovenaars, vooral in het gebied van lesgeven, gameontwikkeling, open source projectmanagement, technische recrutering, ondernemerschap of design."
     counselor_introduction_2: "Of eigenlijk alles wat relevant is voor de ontwikkeling van CodeCombat. Als jij kennis hebt en deze wilt dezen om dit project te laten groeien, dan is dit misschien de klasse voor jou."
     counselor_attribute_1: "Ervaring, in enig van de bovenstaande gebieden of iets anders waarvan je denkt dat het behulpzaam zal zijn."
     counselor_attribute_2: "Een beetje vrije tijd!"


Update ru.coffee

Update ru.coffee

More translations after propagination

--- app/locale/ru.coffee
+++ app/locale/ru.coffee
@@ -307,7 +307,7 @@
     tip_premature_optimization: "Поспешная оптимизация - корень всех зол. - Donald Knuth"
     tip_brute_force: "Когда сомневаешься используй грубую силу. - Кен Томпсон"
     tip_extrapolation: "Есть два типа людей: те, кто могут экстраполировать неполные данные..."
-#    tip_superpower: "Coding is the closest thing we have to a superpower."
+    tip_superpower: "Программирование делает нас ближе к обретению суперсилы."

   game_menu:
     inventory_tab: "Инвентарь"
@@ -329,7 +329,7 @@
   inventory:
     choose_inventory: "Выбрать предметы"
     equipped_item: "Выбранный"
-#    required_purchase_title: "Required"
+    required_purchase_title: "Необходимо"
     available_item: "Доступно"
     restricted_title: "Ограничено"
     should_equip: "(двойной клик чтобы надеть)"
@@ -482,13 +482,13 @@
     forum_prefix: "Для любых публичных обсуждений, пожалуйста, используйте "
     forum_page: "наш форум"
     forum_suffix: "."
-#    faq_prefix: "There's also a"
-#    faq: "FAQ"
+    faq_prefix: "Так же у нас есть"
+    faq: "ЧаВо"
     subscribe_prefix: "Если вам нужна помощь в прохождении уровня, пожалуйста,"
     subscribe: "купите подписку CodeCombat,"
     subscribe_suffix: "и мы будем рады помочь вам с вашим кодом."
     subscriber_support: "Ваши электронные письма получают нашу приоритетную поддержку, если вы подписчик CodeCombat."
-#    screenshot_included: "Screenshot included."
+    screenshot_included: "Скриншот прилагается."
     where_reply: "Куда мы должны ответить?"
     send: "Отправить отзыв"
     contact_candidate: "Связаться с кандидатом" # Deprecated


Update ru.coffee

Update ru.coffee

tip_open_source_contribute and clear_storage

--- app/locale/ru.coffee
+++ app/locale/ru.coffee
@@ -335,7 +335,7 @@
     tip_google: "У вас проблема, которую вы не можете решить? Гуглите!"
     tip_adding_evil: "Добавим щепотку зла."
     tip_hate_computers: "Есть одна вещь в людях, которые думают, что они ненавидят компьютеры. Что они на самом деле ненавидят, так это плохих программистов. - Larry Niven"
-#    tip_open_source_contribute: "You can help CodeCombat improve!"
+    tip_open_source_contribute: "Вы можете помочь сделать CodeCombat лучше!"

   game_menu:
     inventory_tab: "Инвентарь"
@@ -797,7 +797,7 @@
     level_completion: "Выполнение уровня"
     pop_i18n: "Популяризируйте I18N"
     tasks: "Задачи"
-#    clear_storage: "Clear your local changes"
+    clear_storage: "Очистить ваши локальные изменения"

   article:
     edit_btn_preview: "Предпросмотр"


Add computed property for expiration display

[#98105252]

--- review_front/app/models/commit.coffee
+++ review_front/app/models/commit.coffee
@@ -35,6 +35,10 @@
     @get('state') == 'accepted'
   )

+  hasExpiration: Ember.computed('state', ->
+    @get('state') != 'fixed' and @get('state') != 'accepted'
+  )
+
   belongsToMe: Ember.computed ->
     @store.find('user', 'me').get('person') is @get('author')


Update ru.

Update ru.

Sync lines to en.coffee a bit

--- app/locale/ru.coffee
+++ app/locale/ru.coffee
@@ -226,13 +226,6 @@
     victory_sign_up_poke: "Хотите сохранить ваш код? Создайте бесплатный аккаунт!"
     victory_rate_the_level: "Оцените уровень:" # Only in old-style levels.
     victory_return_to_ladder: "Вернуться к ладдеру"
-    victory_play_continue: "Продолжить"
-    victory_play_skip: "Пропустить"
-    victory_play_next_level: "Следующий уровень"
-    victory_play_more_practice: "Попрактиковаться еще"
-    victory_play_too_easy: "Очень легко"
-    victory_play_just_right: "То, что надо"
-    victory_play_too_hard: "Очень сложно"
     victory_saving_progress: "Процесс сохранения"
     victory_go_home: "На главную" # Only in old-style levels.
     victory_review: "Расскажите нам больше!" # Only in old-style levels.
@@ -339,7 +332,7 @@

   subscribe:
     subscribe_title: "Подпишись"
-    levels: "Разблокируйте 25 уровней! И еще 5 каждую неделю!"
+    levels: "Разблокируйте 17 уровней! И еще 5 каждую неделю!"
     heroes: "Более сильные герои!"
     gems: "3500 бонусных самоцветов каждый месяц!"
     items: "Более 250 бонусных предметов!"


Around hundred new lines of Slovak translation

Completed translations of home, nav, diplomat_suggestion, play, common, general, almost whole play_level, buy_gems, skill_docs, versions

--- app/locale/sk.coffee
+++ app/locale/sk.coffee
@@ -6,12 +6,12 @@
     play: "Hraj" # The big play button that opens up the campaign view.
     old_browser: "Ajaj, prehliadač je príliš starý. CodeCombat na ňom nepôjde. Je nám to ľúto!" # Warning that shows up on really old Firefox/Chrome/Safari
     old_browser_suffix: "Skúsiť sa to dá, ale asi to nepôjde."
-#    ipad_browser: "Bad news: CodeCombat doesn't run on iPad in the browser. Good news: our native iPad app is awaiting Apple approval."
+    ipad_browser: "Zlé správy: CodeCombat nebeží na iPade v prehliadači. Dobré správy: naša iPad aplikácia čaká na schválenie od Apple."
     campaign: "Kampaň"
     for_beginners: "Pre začiatočníkov"
-#    multiplayer: "Multiplayer" # Not currently shown on home page
+    multiplayer: "Viac hráčov" # Not currently shown on home page
     for_developers: "Pre vývojárov" # Not currently shown on home page.
-#    or_ipad: "Or download for iPad"
+    or_ipad: "Alebo stiahni pre iPad"

   nav:
     play: "Hraj" # The top nav bar entry where players choose which levels to play
@@ -40,50 +40,50 @@
     page_not_found: "Stránka nenájdená"

   diplomat_suggestion:
-#    title: "Help translate CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
-#    sub_heading: "We need your language skills."
+    title: "Pomôžte preložiť CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
+    sub_heading: "Potrebujeme tvoje jazykové zručnosti."
     pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Slovak but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Slovak."
     missing_translations: "Until we can translate everything into Slovak, you'll see English when Slovak isn't available."
-#    learn_more: "Learn more about being a Diplomat"
-#    subscribe_as_diplomat: "Subscribe as a Diplomat"
+    learn_more: "Zisti viac, ako byť Diplomat"
+    subscribe_as_diplomat: "Prihlásiť sa ako Diplomat"

   play:
     play_as: "Hraj ako" # Ladder page
-    spectate: "Sleduj" # Ladder page
-#    players: "players" # Hover over a level on /play
-#    hours_played: "hours played" # Hover over a level on /play
-#    items: "Items" # Tooltip on item shop button from /play
-#    unlock: "Unlock" # For purchasing items and heroes
-#    confirm: "Confirm"
-#    owned: "Owned" # For items you own
-#    locked: "Locked"
-#    purchasable: "Purchasable" # For a hero you unlocked but haven't purchased
-#    available: "Available"
-#    skills_granted: "Skills Granted" # Property documentation details
-#    heroes: "Heroes" # Tooltip on hero shop button from /play
-#    achievements: "Achievements" # Tooltip on achievement list button from /play
-#    account: "Account" # Tooltip on account button from /play
-#    settings: "Settings" # Tooltip on settings button from /play
-#    next: "Next" # Go from choose hero to choose inventory before playing a level
-#    change_hero: "Change Hero" # Go back from choose inventory to choose hero
-#    choose_inventory: "Equip Items"
-#    buy_gems: "Buy Gems"
-#    subscription_required: "Subscription Required"
-#    free: "Free"
-#    subscribed: "Subscribed"
-#    older_campaigns: "Older Campaigns"
-#    anonymous: "Anonymous Player"
+    spectate: "Sledovať" # Ladder page
+    players: "hráči" # Hover over a level on /play
+    hours_played: "odohratých hodín" # Hover over a level on /play
+    items: "Predmety" # Tooltip on item shop button from /play
+    unlock: "Odomknúť" # For purchasing items and heroes
+    confirm: "Potvrdiť"
+    owned: "Vlastníš" # For items you own
+    locked: "Zamknuté"
+    purchasable: "Môžeš zakúpiť" # For a hero you unlocked but haven't purchased
+    available: "Dostupné"
+    skills_granted: "Získané skúsenosti" # Property documentation details
+    heroes: "Hrdinovia" # Tooltip on hero shop button from /play
+    achievements: "Úspechy" # Tooltip on achievement list button from /play
+    account: "Účet" # Tooltip on account button from /play
+    settings: "Nastavenia" # Tooltip on settings button from /play
+    next: "Ďalší" # Go from choose hero to choose inventory before playing a level
+    change_hero: "Zmeniť hrdinu" # Go back from choose inventory to choose hero
+    choose_inventory: "Vyzbrojiť sa s predmetmy"
+    buy_gems: "Zakúpiť drahokamy"
+    subscription_required: "Vyžaduje sa rredplatné"
+    free: "Zdarma"
+    subscribed: "Predplatené"
+    older_campaigns: "Staršie kampane"
+    anonymous: "Anonymný hráč"
     level_difficulty: "Obtiažnosť."
-    campaign_beginner: "Ťaženie pre začiatočníkov"
-#    awaiting_levels_adventurer_prefix: "We release five levels per week."
-#    awaiting_levels_adventurer: "Sign up as an Adventurer"
-#    awaiting_levels_adventurer_suffix: "to be the first to play new levels."
-#    adjust_volume: "Adjust volume"
+    campaign_beginner: "Kampaň pre začiatočníkov"
+    awaiting_levels_adventurer_prefix: "Každy týždeň 5 nových levelov."
+    awaiting_levels_adventurer: "Prihlás sa ako Dobrodruh"
+    awaiting_levels_adventurer_suffix: "budeš ako prvý hrať nové levely."
+    adjust_volume: "Zmeniť hlasitosť"
     choose_your_level: "Vyber si úroveň" # The rest of this section is the old play view at /play-old and isn't very important.
     adventurer_prefix: "Môže si vybrať ktorúkoľvek z úrovní alebo ich prediskutovať na "
     adventurer_forum: "fóre pre dobrodruhov"
     adventurer_suffix: "."
-#    campaign_old_beginner: "Old Beginner Campaign"
+    campaign_old_beginner: "Staré kampane pre začiatočníkov"
     campaign_old_beginner_description: "... v ktorom sa naučíš mágiu programovania."
     campaign_dev: "Náhodné ťažšie úrovne"
     campaign_dev_description: "... v ktorych sa naučíš používať rozhranie a čeliť väčším výzvam."
@@ -91,8 +91,8 @@
     campaign_multiplayer_description: "... v ktorej si zmeriaš svoje programátorské sily proti ostatným hráčom."
     campaign_player_created: "Hráčmi vytvorené úrovne"
     campaign_player_created_description: "... v ktorých sa popasuješ s kreativitou svojich kúzelníckych súdruhov."
-#    campaign_classic_algorithms: "Classic Algorithms"
-#    campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
+    campaign_classic_algorithms: "Klasické Algoritmy"
+    campaign_classic_algorithms_description: "... v kterých sa naučíte najobľúbenejšie algoritmy v IT"

 #  share_progress_modal:
 #    blurb: "You’re making great progress! Tell someone how much you've learned with CodeCombat."
@@ -141,8 +141,8 @@
     books: "Knihy"

   common:
-#    back: "Back" # When used as an action verb, like "Navigate backward"
-#    continue: "Continue" # When used as an action verb, like "Continue forward"
+    back: "Späť" # When used as an action verb, like "Navigate backward"
+    continue: "Pokračovať" # When used as an action verb, like "Continue forward"
     loading: "Načítava sa..."
     saving: "Ukladá sa..."
     sending: "Odosiela sa..."
@@ -152,16 +152,16 @@
     publish: "Publikuj"
     create: "Vytvoriť"
     manual: "Manuál"
-#    fork: "Fork"
+    fork: "Klonovať"
     play: "Hraj" # When used as an action verb, like "Play next level"
     retry: "Znova"
-#    actions: "Actions"
+    actions: "Príkazy"
     info: "Info"
     help: "Pomoc"
     watch: "Sleduj"
     unwatch: "Zruš sledovanie"
-#    submit_patch: "Submit Patch"
-#    submit_changes: "Submit Changes"
+    submit_patch: "Odoslať Opravu"
+    submit_changes: "Odoslať zmeny"

   general:
     and: "a"
@@ -172,19 +172,19 @@
     pending: "Vybavuje sa"
     accepted: "Prijaté"
     rejected: "Zamietnuté"
-#    withdrawn: "Withdrawn"
+    withdrawn: "Uzatvorené"
     submitter: "Odosielateľ"
     submitted: "Odoslané"
-#    commit_msg: "Commit Message"
-#    review: "Review"
-#    version_history: "Version History"
-#    version_history_for: "Version History for: "
-#    select_changes: "Select two changes below to see the difference."
+    commit_msg: "Popis ukladania"
+    review: "Preskúmať"
+    version_history: "História verzií"
+    version_history_for: "História verzií pre: "
+    select_changes: "Vyber dve zmeny pre porovnanie."
     undo_prefix: "Späť"
     undo_shortcut: "(Ctrl+Z)"
     redo_prefix: "Dopredu"
     redo_shortcut: "(Ctrl+Shift+Z)"
-#    play_preview: "Play preview of current level"
+    play_preview: "Prehraj náhľad tohto levelu"
     result: "Výsledok"
     results: "Výsledky"
     description: "Popis"
@@ -206,7 +206,7 @@
     medium: "Stredná"
     hard: "Ťažká"
     player: "Hráč"
-#    player_level: "Level" # Like player level 5, not like level: Dungeons of Kithgard
+    player_level: "Úroveň" # Like player level 5, not like level: Dungeons of Kithgard
     warrior: "Bojovník"
     ranger: "Strelec"
     wizard: "Mág"
@@ -229,8 +229,8 @@

   play_level:
     done: "Hotovo"
-#    home: "Home" # Not used any more, will be removed soon.
-#    level: "Level" # Like "Level: Dungeons of Kithgard"
+    home: "Domov" # Not used any more, will be removed soon.
+    level: "Úroveň" # Like "Level: Dungeons of Kithgard"
     skip: "Preskočiť"
     game_menu: "Menu hry"
     guide: "Návod"
@@ -241,50 +241,50 @@
     success: "Úspech!"
     incomplete: "Nekompletné"
     timed_out: "Čas uplynul"
-#    failing: "Failing"
-#    action_timeline: "Action Timeline"
-#    click_to_select: "Click on a unit to select it."
-#    control_bar_multiplayer: "Multiplayer"
-#    control_bar_join_game: "Join Game"
+    failing: "Zlyhanie"
+    action_timeline: "Časová os"
+    click_to_select: "Vyberte kliknutím."
+    control_bar_multiplayer: "Viac hráčov"
+    control_bar_join_game: "Vstúpiť do hry"
     reload: "Znova"
-#    reload_title: "Reload All Code?"
-#    reload_really: "Are you sure you want to reload this level back to the beginning?"
+    reload_title: "Načítať celý kód odznova?"
+    reload_really: "Naozaj chcete reštartovať túto úroveň od začiatkúu"
     reload_confirm: "Obnoviť všetko"
     victory: "Víťazstvo"
-#    victory_title_prefix: ""
+    victory_title_prefix: ""
     victory_title_suffix: " Kompletné"
-#    victory_sign_up: "Sign Up to Save Progress"
-#    victory_sign_up_poke: "Want to save your code? Create a free account!"
-#    victory_rate_the_level: "Rate the level: " # Only in old-style levels.
-#    victory_return_to_ladder: "Return to Ladder"
+    victory_sign_up: "Přihlásit se pre uloženie progresu"
+    victory_sign_up_poke: "Chceš uložiť svoj kód? Vytvorte si účet zdarma!"
+    victory_rate_the_level: "Ohodnoťte túto úroveň: " # Only in old-style levels.
+    victory_return_to_ladder: "Vrátiť sa na Rebríčky"
     victory_play_continue: "Pokračovať"
     victory_saving_progress: "Stav ukladania"
-#    victory_go_home: "Go Home" # Only in old-style levels.
-#    victory_review: "Tell us more!" # Only in old-style levels.
-#    victory_hour_of_code_done: "Are You Done?"
-#    victory_hour_of_code_done_yes: "Yes, I'm finished with my Hour of Code™!"
+    victory_go_home: "Návrat Domov" # Only in old-style levels.
+    victory_review: "Povedz nám viac!" # Only in old-style levels.
+    victory_hour_of_code_done: "Skončil si?"
+    victory_hour_of_code_done_yes: "Áno, pre dnešok som skončil™!"
     victory_experience_gained: "Získaných skúseností"
     victory_gems_gained: "Získaných kryštálov"
     guide_title: "Návod"
-#    tome_minion_spells: "Your Minions' Spells" # Only in old-style levels.
-#    tome_read_only_spells: "Read-Only Spells" # Only in old-style levels.
-#    tome_other_units: "Other Units" # Only in old-style levels.
+    tome_minion_spells: "Vaše obľúbené kúzla" # Only in old-style levels.
+    tome_read_only_spells: "Kúzla iba na čítanie" # Only in old-style levels.
+    tome_other_units: "Ostatné jednotky" # Only in old-style levels.
     tome_cast_button_run: "Spustiť"
-#    tome_cast_button_running: "Running"
-#    tome_cast_button_ran: "Ran"
+    tome_cast_button_running: "Prebieha"
+    tome_cast_button_ran: "Spustené"
     tome_submit_button: "Odoslať"
-#    tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
-#    tome_select_method: "Select a Method"
-#    tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methdos).
-#    tome_select_a_thang: "Select Someone for "
-#    tome_available_spells: "Available Spells"
+    tome_reload_method: "Znovu načítať pôvodný kód pre túto metódu" # Title text for individual method reload button.
+    tome_select_method: "Vybrať metódu"
+    tome_see_all_methods: "Vybrať všetky metódy, ktoré môžu byť upravené" # Title text for method list selector (shown when there are multiple programmable methdos).
+    tome_select_a_thang: "Zvoľte niekoho pre "
+    tome_available_spells: "Dostupné kúzla"
     tome_your_skills: "Tvoje schopnosti"
     tome_help: "Pomoc"
-#    tome_current_method: "Current Method"
+    tome_current_method: "Súčasná metóda"
     hud_continue_short: "Pokračovať"
     code_saved: "Kód uložený"
     skip_tutorial: "Preskoč (esc)"
-#    keyboard_shortcuts: "Key Shortcuts"
+    keyboard_shortcuts: "Klávesové skratky"
     loading_ready: "Pripravené!"
     loading_start: "Začať level"
     problem_alert_title: "Oprav svoj kód"
@@ -294,22 +294,22 @@
     time_goto: "Choď na:"
     infinite_loop_try_again: "Skús znova"
     infinite_loop_reset_level: "Reštartuj level"
-#    infinite_loop_comment_out: "Comment Out My Code"
-#    tip_toggle_play: "Toggle play/paused with Ctrl+P."
-#    tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward."
-#    tip_guide_exists: "Click the guide, inside game menu (at the top of the page), for useful info."
-#    tip_open_source: "CodeCombat is 100% open source!"
-#    tip_beta_launch: "CodeCombat launched its beta in October, 2013."
-#    tip_think_solution: "Think of the solution, not the problem."
-#    tip_theory_practice: "In theory, there is no difference between theory and practice. But in practice, there is. - Yogi Berra"
-#    tip_error_free: "There are two ways to write error-free programs; only the third one works. - Alan Perlis"
-#    tip_debugging_program: "If debugging is the process of removing bugs, then programming must be the process of putting them in. - Edsger W. Dijkstra"
-#    tip_forums: "Head over to the forums and tell us what you think!"
-#    tip_baby_coders: "In the future, even babies will be Archmages."
-#    tip_morale_improves: "Loading will continue until morale improves."
-#    tip_all_species: "We believe in equal opportunities to learn programming for all species."
-#    tip_reticulating: "Reticulating spines."
-#    tip_harry: "Yer a Wizard, "
+infinite_loop_comment_out: "Zakomentovať môj kód"
+    tip_toggle_play: "Prepnite prehrávanie/pauzu pomocou Ctrl+P."
+    tip_scrub_shortcut: "Ctrl+[ a Ctrl+] pre pretočenie a rychlý presun."
+    tip_guide_exists: "Kliknite na sprievodcu v hernom menu (hore na stránke), pre užitočné informácie."
+    tip_open_source: "CodeCombat je 100% open source!"
+    tip_beta_launch: "CodeCombat spustil svoju beta verziu v Októbri, 2013."
+    tip_think_solution: "Myslite na riešenie, nie na problém."
+    tip_theory_practice: "Teoreticky nie je žiaden rozdiel medzi teoriou a praxou. Ale v praxi ten rozdiel je. - Yogi Berra"
+    tip_error_free: "Sú dva spôsoby ako písať programy bez chýb; iba ten tretí funguje. - Alan Perlis"
+    tip_debugging_program: "Pokiaľ je ladenie proces, pri ktorom sa odstraňujú chyby, programovanie musí potom byť proces, ktorým sa chyby pridávajú. - Edsger W. Dijkstra"
+    tip_forums: "Choďte na naše fórum a povedzte nám, čo si myslíte!"
+    tip_baby_coders: "V budúcnosti budoú i bábätká Arcikúzelníci."
+    tip_morale_improves: "Načítánie bude prebiehať, pokiaľ sa nezlepší morálka."
+    tip_all_species: "Veríme v rovnaké možnosti učenia sa programovať pre všetky druhy."
+    tip_reticulating: "Sieťovanie chrbtíc."
+    tip_harry: "Hej kúzelík, "
 #    tip_great_responsibility: "With great coding skill comes great debug responsibility."
 #    tip_munchkin: "If you don't eat your vegetables, a munchkin will come after you while you're asleep."
 #    tip_binary: "There are only 10 types of people in the world: those who understand binary, and those who don't."
@@ -376,7 +376,7 @@
     equipped_item: "Použité"
     required_purchase_title: "Požadované"
     available_item: "K dispozícii"
-    restricted_title: "RObmedzené"
+    restricted_title: "Zakázané"
     should_equip: "(klikni 2x pre použitie)"
     equipped: "(používa sa)"
     locked: "(zamknuté)"
@@ -384,18 +384,18 @@
     equip: "Použi"
     unequip: "Odlož"

-#  buy_gems:
-#    few_gems: "A few gems"
-#    pile_gems: "Pile of gems"
-#    chest_gems: "Chest of gems"
-#    purchasing: "Purchasing..."
-#    declined: "Your card was declined"
-#    retrying: "Server error, retrying."
-#    prompt_title: "Not Enough Gems"
-#    prompt_body: "Do you want to get more?"
-#    prompt_button: "Enter Shop"
-#    recovered: "Previous gems purchase recovered. Please refresh the page."
-#    or_subscribe: "Or 3500 gems/mo if you..."
+  buy_gems:
+    few_gems: "Pár drahokamov"
+    pile_gems: "Hromada drahokamov"
+    chest_gems: "Truhlica drahokamov"
+    purchasing: "Prebieha nákup..."
+    declined: "Vaša karta bola odmietnutá"
+    retrying: "Chyba servera, obnovovanie."
+    prompt_title: "Nedostatok drahokamov"
+    prompt_body: "Chcete získať viac?"
+    prompt_button: "Vstúpiť do obchodu"
+    recovered: "Obnovenie už zakúpených drahokamov prebehlo úspěšne. Aktualizujte stránku prosím."
+    or_subscribe: "Alebo 3500 drahokamov ak..."

 #  subscribe:
 #    comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
@@ -462,23 +462,23 @@
 #    level_to_unlock: "Level to unlock:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
 #    restricted_to_certain_heroes: "Only certain heroes can play this level."

-#  skill_docs:
-#    writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this
-#    read_only: "read-only"
-#    action_name: "name"
-#    action_cooldown: "Takes"
-#    action_specific_cooldown: "Cooldown"
-#    action_damage: "Damage"
-#    action_range: "Range"
-#    action_radius: "Radius"
-#    action_duration: "Duration"
-#    example: "Example"
-#    ex: "ex" # Abbreviation of "example"
-#    current_value: "Current Value"
-#    default_value: "Default value"
-#    parameters: "Parameters"
-#    returns: "Returns"
-#    granted_by: "Granted by"
+  skill_docs:
+    writable: "zapisovatelné" # Hover over "attack" in Your Skills while playing a level to see most of this
+    read_only: "iba na čítanie"
+    action_name: "názov"
+    action_cooldown: "Zaberie"
+    action_specific_cooldown: "Cooldown"
+    action_damage: "Poškodenie"
+    action_range: "Vzdialenosť"
+    action_radius: "Dosah"
+    action_duration: "Trvanie"
+    example: "Príklad"
+    ex: "pr." # Abbreviation of "example"
+    current_value: "Aktuálna hodnota"
+    default_value: "Východzia hodnota"
+    parameters: "Parametre"
+    returns: "Vracia"
+    granted_by: "Poskytnutné od"

   save_load:
     granularity_saved_games: "Uložené"
@@ -577,10 +577,10 @@
   versions:
     save_version_title: "Ulož novú verziu"
     new_major_version: "Nová primárna verzia"
-#    submitting_patch: "Submitting Patch..."
+    submitting_patch: "Odosielanie opravy..."
     cla_prefix: "Ak chcete uložiť svoje zmeny, musíte najprv súhlasiť s našou"
-#    cla_url: "CLA"
-#    cla_suffix: "."
+    cla_url: "licencia"
+    cla_suffix: "."
     cla_agree: "SÚHLASÍM"

   contact:
@@ -607,7 +607,7 @@
     autosave: "Zmeny sa uložia automaticky"
     me_tab: "Ja"
     picture_tab: "Obrázok"
-#    upload_picture: "Upload a picture"
+    upload_picture: "Nahraj obrázok"
     password_tab: "Heslo"
     emails_tab: "E-maily"
     admin: "Spravovať"


Teamwork: Implemented import action for dashboard.

--- client/landing/app/Applications/Teamwork.kdapplication/Views/teamworkdashboard.coffee
+++ client/landing/app/Applications/Teamwork.kdapplication/Views/teamworkdashboard.coffee
@@ -28,16 +28,19 @@
       cssClass    : "tw-dashboard-button"
       callback    : => @handleJoinSession()

-    @importInput  = new KDInputView
+    @importInput  = new KDHitEnterInputView
       cssClass    : "tw-dashboard-input"
       placeholder : "Url to import your VM"
-      callback    : ->
+      validate    :
+        rules     : required: yes
+        messages  : required: "Enter URL to import content."
+      callback    : => @handleImport()

     @importButton = new KDButtonView
       iconOnly    : yes
       iconClass   : "import"
       cssClass    : "tw-dashboard-button"
-      callback    : ->
+      callback    : => @handleImport()

     @playgrounds  = new KDCustomHTMLView
       cssClass    : "tw-playgrounds"


Update tr.coffee (#3842)

Update tr.coffee (#3842)

* Update tr.coffee

calendar

* Update tr.coffee

login, signup

--- app/locale/tr.coffee
+++ app/locale/tr.coffee
@@ -243,7 +243,7 @@

   login:
     sign_up: "Hesap Oluştur"
-#    email_or_username: "Email or username"
+    email_or_username: "E-posta veya kullanıcı adı"
     log_in: "Giriş Yap"
     logging_in: "Giriş Yapılıyor"
     log_out: "Çıkış Yap"
@@ -256,13 +256,13 @@
     signup_switch: "Hesap oluşturmak istiyor musun?"

   signup:
-#    create_student_header: "Create Student Account"
-#    create_teacher_header: "Create Teacher Account"
-#    create_individual_header: "Create Individual Account"
-#    create_header: "Create Account"
+    create_student_header: "Öğrenci Hesabı Oluştur"
+    create_teacher_header: "Öğretmen Hesabı Oluştur"
+    create_individual_header: "Bireysel Hesap Oluştur"
+    create_header: "Hesap Oluştur"
     email_announcements: "E-posta duyurularını almak istiyorum" # {change}
     creating: "Hesap oluşturuluyor..."
-#    create_account: "Create Account"
+    create_account: "Hesap Oluştur"
     sign_up: "Kaydol"
     log_in: "buradan giriş yapabilirsiniz."
     required: "Buraya gidebilmeniz için oturum açmanız gerekli."
@@ -278,46 +278,46 @@
     connected_facebook_p: "Kayıt işlemini bitir, artık Facebook hesabınla giriş yapabilirsin."
     facebook_exists: "Zaten Facebook ile ilişkilendirilmiş bir hesabın bulunuyor!"
     hey_students: "Öğrenciler, öğretmeninizin verdiği sınıf kodunu girin."
-#    birthday: "Birthday"
+    birthday: "Doğum günü"
 #    parent_email_blurb: "We know you can't wait to learn programming — we're excited too! Your parents will receive an email with further instructions on how to create an account for you. Email {{email_link}} if you have any questions."
 #    classroom_not_found: "No classes exist with this Class Code. Check your spelling or ask your teacher for help."
-#    checking: "Checking..."
+    checking: "Kontrol ediliyor..."
 #    account_exists: "This email is already in use:" # {change}
-#    sign_in: "Sign in"
-#    email_good: "Email looks good!"
+    sign_in: "Oturum aç"
+    email_good: "E-posta iyi görünüyor!"
 #    name_taken: "Username already taken! Try {{suggestedName}}?"
-#    name_available: "Username available!"
+    name_available: "Kullanıcı adı müsait!"
 #    name_is_email: "Username may not be an email"
-#    choose_type: "Choose your account type:"
+    choose_type: "Hesabınızın türünü seçin:"
 #    teacher_type_1: "Teach programming using CodeCombat!"
 #    teacher_type_2: "Set up your class"
 #    teacher_type_3: "Access Course Guides"
 #    teacher_type_4: "View student progress"
-#    signup_as_teacher: "Sign up as a Teacher"
-#    student_type_1: "Learn to program while playing an engaging game!"
-#    student_type_2: "Play with your class"
-#    student_type_3: "Compete in arenas"
-#    student_type_4: "Choose your hero!"
+    signup_as_teacher: "Öğretmen olarak Kaydol"
+    student_type_1: "İlgi çekici bir oyun oynarken program öğren!"
+    student_type_2: "Sınıfınla oyna"
+    student_type_3: "Arenalarda rekabet et"
+    student_type_4: "Kahramanını seç!"
 #    student_type_5: "Have your Class Code ready!"
-#    signup_as_student: "Sign up as a Student"
+    signup_as_student: "Öğrenci olarak Kaydol"
 #    individuals_or_parents: "Individuals & Parents"
 #    individual_type: "For players learning to code outside of a class. Parents should sign up for an account here."
-#    signup_as_individual: "Sign up as an Individual"
-#    enter_class_code: "Enter your Class Code"
-#    enter_birthdate: "Enter your birthdate:"
-#    ask_teacher_1: "Ask your teacher for your Class Code."
+    signup_as_individual: "Bireysel olarak Kaydol"
+    enter_class_code: "Sınıf Kodunu Gir"
+    enter_birthdate: "Doğum tarihini gir:"
+    ask_teacher_1: "Sınıf kodun için öğretmenine sor."
 #    ask_teacher_2: "Not part of a class? Create an "
-#    ask_teacher_3: "Individual Account"
+    ask_teacher_3: "Bireysel Hesap"
 #    ask_teacher_4: " instead."
 #    about_to_join: "You're about to join:"
 #    enter_parent_email: "Enter your parent’s email address:"
 #    parent_email_error: "Something went wrong when trying to send the email. Check the email address and try again."
 #    parent_email_sent: "We’ve sent an email with further instructions on how to create an account. Ask your parent to check their inbox."
-#    account_created: "Account Created!"
+    account_created: "Hesap Oluşturuldu!"
 #    confirm_student_blurb: "Write down your information so that you don't forget it. Your teacher can also help you reset your password at any time."
 #    confirm_individual_blurb: "Write down your login information in case you need it later. Verify your email so you can recover your account if you ever forget your password - check your inbox!"
 #    write_this_down: "Write this down:"
-#    start_playing: "Start Playing!"
+    start_playing: "Oynamaya Başla!"
 #    sso_connected: "Successfully connected with:"

   recover:


Update uk.coffee (#5571)

Update uk.coffee (#5571)

--- app/locale/uk.coffee
+++ app/locale/uk.coffee
@@ -2631,15 +2631,15 @@
     basic_event_handling: "Основи обробки подій"
     create_sharable_interactive_web_page: "Створи інтерактивну веб-сторінку, якою можна ділитися"

-#  anonymous_teacher:
-#    notify_teacher: "Notify Teacher"
-#    create_teacher_account: "Create free teacher account"
-#    enter_student_name: "Your name:"
-#    enter_teacher_email: "Your teacher's email:"
+  anonymous_teacher:
+    notify_teacher: "Повідомити вчителя"
+    create_teacher_account: "Створити безкоштовний акаунт вчителя"
+    enter_student_name: "Твоє ім'я:"
+    enter_teacher_email: "Електронна пошта твого вчителя:"
 #    teacher_email_placeholder: "teacher.email@example.com"
-#    student_name_placeholder: "type your name here"
-#    teachers_section: "Teachers:"
-#    students_section: "Students:"
+    student_name_placeholder: "напишіть своє ім'я тут"
+    teachers_section: "Вчителі:"
+    students_section: "Учні:"
 #    teacher_notified: "We've notified your teacher that you want to play more CodeCombat in your classroom!"

   delta:
@@ -2704,7 +2704,7 @@
     rights_clarification: "Для уточнення, будь-що що є доступним у редакторі рівнів, для створення нових рівнів, належить CC, тоді як зміст, створений редактором рівнів або завантажений у ході створення рівнів, не належить."
     nutshell_title: "Коротко"
     nutshell_description: "Будь-які ресурси, котрі ми надаємо в редакторі рівнів, є безкоштовними для використання за Вашим бажанням для створення рівнів. Але ми залишаємо за собою право обмежувати розповсюдження самих рівнів (котрі були створені на codecombat.com), тому в майбутньому за них може стягуватися плата, якщо в кінцевому результаті таке станеться."
-#    nutshell_see_also: "See also:"
+    nutshell_see_also: "Дивіться також:"
     canonical: "Англомовна версія цього документа є остаточною та канонічною версією. Якщо є будь-які невідповідності в перекладі, англійська версія документа є пріоритетною."
     third_party_title: "Сервіси сторонніх розробників"
     third_party_description: "CodeCombat використовує наступні сервіси сторонніх розробників (серед інших):"


Fix clipping of activity spinner

Fix clipping of activity spinner

--- src/smc-webapp/r_misc.cjsx
+++ src/smc-webapp/r_misc.cjsx
@@ -813,7 +813,7 @@
         trunc = (s) -> misc.trunc(s, n)
         for desc, i in @props.activity
             <div key={i} style={activity_item_style} >
-                <Icon name='circle-o-notch' spin /> {trunc(desc)}
+                <Icon style={padding:'2px 1px 1px 2px'} name='circle-o-notch' spin /> {trunc(desc)}
             </div>

     render: ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/expirable.coffee
+++ test/expirable.coffee
@@ -1,6 +1,4 @@
 module "Expirable"
-
-module("Durable")

 test "objects become inactive after their duration", ->
   obj = GameObject


Update vi.coffee

Update vi.coffee

contributors update

--- app/locale/vi.coffee
+++ app/locale/vi.coffee
@@ -15,7 +15,7 @@
     or_ipad: "Hoặc tải phiên bản dành cho iPad"

   nav:
-    play: "Chơi" # The top nav bar entry where players choose which levels to play
+    play: "Chơi!!" # The top nav bar entry where players choose which levels to play
     community: "Cộng đồng"
     courses: "Khoá học"
     editor: "Chỉnh sửa"
@@ -74,7 +74,7 @@
     buy_gems: "Mua ngọc"
     subscription_required: "Cần đăng kí"
     anonymous: "Người chơi vô danh"
-    level_difficulty: "Khó: "
+    level_difficulty: "Độ khó: "
     play_classroom_version: "Chơi Phiên Bản Lớp Học" # Choose a level in campaign version that you also can play in one of your courses
     campaign_beginner: "Chiến dịch chế độ đơn giản"
     awaiting_levels_adventurer_prefix: "Chúng tôi cho ra 5 bàn mới mỗi tuần." # {change}
@@ -92,7 +92,7 @@
     form_blurb: "Nhập địa chỉ email của người bạn muốn tìm và chúng tôi sẽ cho bạn thấy!"
     form_label: "Địa chỉ email"
     placeholder: "địa chỉ email"
-    title: "Làm tốt lắm, thực tập viên"
+    title: "Làm tốt lắm, thực tập viên!"

   login:
     sign_up: "Tạo tài khoản"
@@ -733,8 +733,11 @@
     clan: "Clan"
 #    clans: "Clans"
 #    new_name: "New clan name"
+    new_name: "Tên mới cho bè đảng"
 #    new_description: "New clan description"
+    new_description: "Miêu tả cho bè đảng mới này"
 #    make_private: "Make clan private"
+    make_private: "Tạo bè đảng kín"
 #    subs_only: "subscribers only"
     create_clan: "Tạo một clan mới"
 #    private_preview: "Preview"
@@ -809,7 +812,9 @@
 #    average_time: "Average level play time:"
     total_time: "Tổng thời gian chơi:"
 #    average_levels: "Average levels completed:"
+    average_levels: "Lượng cấp độ trung bình đã hoàn thành:"
 #    total_levels: "Total levels completed:"
+    total_levels: "Tổng số cấp độ đã hoàn thành"
 #    furthest_level: "Furthest level completed:"
 #    concepts_covered: "Concepts Covered"
 #    students: "Students"
@@ -1016,23 +1021,34 @@

   classes:
 #    archmage_title: "Archmage"
+    archmage: "Đại Pháp Sư"
     archmage_title_description: "(Lập trình viên)"
 #    archmage_summary: "If you are a developer interested in coding educational games, become an archmage to help us build CodeCombat!"
+    archmage_summary: "Nếu bạn là một lập trình viên và có hứng thú với việc viết những trò chơi học tập, hãy trở thành một Đại pháp sư và cùng chung tay với chúng tôi để xây dựng CodeCombat!"
+
 #    artisan_title: "Artisan"
+    artisan_title: "Thợ Thủ Công"
     artisan_title_description: "(Người xây dựng những bàn mới)"
 #    artisan_summary: "Build and share levels for you and your friends to play. Become an Artisan to learn the art of teaching others to program."
-    adventurer_title: "Nhà thám hiểm"
+    artisan_summary: "Gầy dựng và chia sẽ những cấp độ do bạn tạo ra cho các bạn của mình cùng chơi. Hãy trở thành thợ thủ công để học nghệ thuật hướng dẫn lập trình cho người khác."
+
+    adventurer_title: "Nhà Thám Hiểm"
     adventurer_title_description: "(Người chơi thử những bàn mới)"
 #    adventurer_summary: "Get our new levels (even our subscriber content) for free one week early and help us work out bugs before our public release."
-#    scribe_title: "Scribe"
+    adventurer_summary: "Dấn thân vào những cấp độ mới nhất(thậm chí là những nội dung chỉ có khi đăng kí) miễn phí trước một tuần và giúp chúng tôi tìm lỗi trước ngày thị chúng."
+    #    scribe_title: "Scribe"
+    scribe_title: "Thơ kí"
     scribe_title_description: "(Người chỉnh sửa những bài viết)"
 #    scribe_summary: "Good code needs good documentation. Write, edit, and improve the docs read by millions of players across the globe."
+    scribe_summary: "Dòng lệnh tốt cần tài liệu hay. Viết, chỉnh sửa, và phát triển những tài liệu được đọc bởi hàng triệu người khắp năm châu."
     diplomat_title: "Nhà Ngoại Giao"
     diplomat_title_description: "(Người phiên dịch)"
     diplomat_summary: "CodeCombat đã được địa phương hóa cho hơn 45 ngôn ngữ nhờ sự giúp đỡ của những nhà ngoại giao. Hãy giúp chúng tôi với việc dịch thuật nếu bạn có thể."
 #    ambassador_title: "Ambassador"
+    ambassador_title: "Sứ Giả"
     ambassador_title_description: "(Hỗ trợ)"
 #    ambassador_summary: "Tame our forum users and provide direction for those with questions. Our ambassadors represent CodeCombat to the world."
+    ambassador_summary: "Thuần hóa những thành viện trong diễn đàn và đưa ra hướng dẫn cho những thắc mắc. Đoàn sứ giả của chúng tôi là bộ mặt của CodeCombat gửi gắm cho thế giới."

   editor:
 #    main_title: "CodeCombat Editors"


Generalize tests

Generalize tests

--- spec/markdown-table-formatter-spec.coffee
+++ spec/markdown-table-formatter-spec.coffee
@@ -21,34 +21,46 @@
       for table in nonTables
         expect(table).not.toMatch(MarkdownTableFormatter.tableFormatter.regex)

+  testFormat = (formatter, modifier) -> (input, expected) ->
+    modifier ?= (x) -> x
+    rand = Math.random()
+    expect(formatter modifier(input, rand)).toEqual(modifier(expected, rand))
+
+  testSuiteSingle = (test, tbls) ->
+    it "should properly format these tables", ->
+      for table in tbls
+        test table.test, table.expected
+
+  testSuite = (test) ->
+    testSuiteSingle(test, testTables)
+
+    for just, tbls of testTablesDefault
+      describe "Default #{just} justification tests", ->
+        do (just) ->
+          beforeEach ->
+            MarkdownTableFormatter.tableFormatter.defaultTableJustification = just
+        testSuiteSingle test, tbls
+
   describe "format tests", ->
-    rx = null
+    test = testFormat (input) ->
+      rx = MarkdownTableFormatter.tableFormatter.regex
+      rx.lastIndex = 0
+      MarkdownTableFormatter.tableFormatter.formatTable rx.exec(input)

     beforeEach ->
-      rx = MarkdownTableFormatter.tableFormatter.regex
       MarkdownTableFormatter.tableFormatter.spacePadding = 1
       MarkdownTableFormatter.tableFormatter.keepFirstAndLastPipes = true
       MarkdownTableFormatter.tableFormatter.defaultTableJustification = 'Left'

-    it "should properly format this tables", ->
-      for table in testTables
-        rx.lastIndex = 0
-        rxtable = rx.exec(table.test)
-        formatted = MarkdownTableFormatter.tableFormatter.formatTable rxtable
-        expect(formatted).toEqual(table.expected)
-
-    describe "Default justification tests", ->
-      for just, tbls of testTablesDefault
-        it "should properly format this tables with #{just} justification", ->
-          MarkdownTableFormatter.tableFormatter.defaultTableJustification = just
-          for table in tbls
-            rx.lastIndex = 0
-            rxtable = rx.exec(table.test)
-            formatted = MarkdownTableFormatter.tableFormatter.formatTable rxtable
-            expect(formatted).toEqual(table.expected)
+    testSuite test

   describe "editor tests", ->
     editor = null
+
+    test = testFormat editorFormat = (input) ->
+      editor.setText input
+      MarkdownTableFormatter.tableFormatter.format editor
+      editor.getText()

     beforeEach ->
       editor = atom.workspace.buildTextEditor()
@@ -59,37 +71,27 @@
       MarkdownTableFormatter.tableFormatter.autoSelectEntireDocument = true
       MarkdownTableFormatter.tableFormatter.formatOnSave = false

-    it "should properly format test tables", ->
-      for table in testTables
-        editor.setText(table.test)
-        MarkdownTableFormatter.tableFormatter.format editor
-        expect(editor.getText()).toEqual(table.expected)
+    testSuite test

     it "shouldn't try to format non-tables", ->
       for nonTable in nonTables
-        editor.setText(nonTable)
-        MarkdownTableFormatter.tableFormatter.format editor
-        expect(editor.getText()).toEqual(nonTable)
+        test nonTable, nonTable

-    it "should format tables at the end of document", ->
-      for table in testTables
-        text = nonTables[Math.floor(Math.random() * nonTables.length)]
-        editor.setText(text + "\n" + table.test)
-        MarkdownTableFormatter.tableFormatter.format editor
-        expect(editor.getText()).toEqual(text + "\n" + table.expected)
+    describe "Tables at the end of document", ->
+      modTest = testFormat editorFormat, (text, rand) ->
+        nonTables[Math.floor(rand * nonTables.length)] + "\n" + text
+      testSuite modTest

-    it "should format tables at the beginning of document", ->
-      for table in testTables
-        text = nonTables[Math.floor(Math.random() * nonTables.length)]
-        editor.setText(table.test + "\n" + text)
-        MarkdownTableFormatter.tableFormatter.format editor
-        expect(editor.getText()).toEqual(table.expected + "\n" + text)
+    describe "Tables at the beginning of document", ->
+      modTest = testFormat editorFormat, (text, rand) ->
+        text + "\n" + nonTables[Math.floor(rand * nonTables.length)]
+      testSuite modTest

     it "should properly format large text", ->
+      edtext = ""
       expected = ""
       for table in testTables
         text = nonTables[Math.floor(Math.random() * nonTables.length)]
-        editor.setText(editor.getText() + "\n" + text + "\n" + table.test)
+        edtext += "\n" + text + "\n" + table.test
         expected += "\n" + text + "\n" + table.expected
-      MarkdownTableFormatter.tableFormatter.format editor
-      expect(editor.getText()).toEqual(expected)
+      test edtext, expected


strip document

strip document

--- daedalus/app/assets/javascripts/news_article/news_article_controller.js.coffee
+++ daedalus/app/assets/javascripts/news_article/news_article_controller.js.coffee
@@ -48,6 +48,6 @@
           DocumentType: tab_key
         },
       (data) ->
-        $scope.tab_text[tab_key] = data
+        $scope.tab_text[tab_key] = data['document']
       )
 )


fix tests with cozy-ical

fix tests with cozy-ical

--- test/ical_test.coffee
+++ test/ical_test.coffee
@@ -21,6 +21,7 @@
 PRODID:-//Cozy Cloud//NONSGML Cozy Agenda//EN
 BEGIN:VTIMEZONE
 TZID:Europe/Paris
+TZURL:http://tzurl.org/zoneinfo/Europe/Paris.ics
 BEGIN:STANDARD
 DTSTART:20130423T144000
 TZOFFSETFROM:-0200
@@ -33,17 +34,18 @@
 END:DAYLIGHT
 END:VTIMEZONE
 BEGIN:VTODO
-DTSTAMP:20130423T144000
+DTSTAMP:20130423T144000Z
 SUMMARY:Something to remind
-UID:undefined
-BEGIN:VALARM
-ACTION:AUDIO
-REPEAT:1
-TRIGGER:20130423T144000
+UID:[id-1]
+BEGIN:VALARM
+ACTION:DISPLAY
+REPEAT:1
+TRIGGER:20130423T144000Z
 END:VALARM
 END:VTODO
 BEGIN:VTIMEZONE
 TZID:Africa/Abidjan
+TZURL:http://tzurl.org/zoneinfo/Africa/Abidjan.ics
 BEGIN:STANDARD
 DTSTART:20130424T133000
 TZOFFSETFROM:+0000
@@ -56,17 +58,18 @@
 END:DAYLIGHT
 END:VTIMEZONE
 BEGIN:VTODO
-DTSTAMP:20130424T133000
+DTSTAMP:20130424T133000Z
 SUMMARY:Something else to remind
-UID:undefined
-BEGIN:VALARM
-ACTION:AUDIO
-REPEAT:1
-TRIGGER:20130424T133000
+UID:[id-2]
+BEGIN:VALARM
+ACTION:DISPLAY
+REPEAT:1
+TRIGGER:20130424T133000Z
 END:VALARM
 END:VTODO
 BEGIN:VTIMEZONE
 TZID:Pacific/Apia
+TZURL:http://tzurl.org/zoneinfo/Pacific/Apia.ics
 BEGIN:STANDARD
 DTSTART:20130425T113000
 TZOFFSETFROM:-1300
@@ -79,20 +82,21 @@
 END:DAYLIGHT
 END:VTIMEZONE
 BEGIN:VTODO
-DTSTAMP:20130425T113000
+DTSTAMP:20130425T113000Z
 SUMMARY:Another thing to remind
-UID:undefined
-BEGIN:VALARM
-ACTION:AUDIO
-REPEAT:1
-TRIGGER:20130425T113000
+UID:[id-3]
+BEGIN:VALARM
+ACTION:DISPLAY
+REPEAT:1
+TRIGGER:20130425T113000Z
 END:VALARM
 END:VTODO
 BEGIN:VEVENT
 DESCRIPTION:my description
-DTSTART:20130609T150000
-DTEND:20130610T150000
+DTSTART:20130609T150000Z
+DTEND:20130610T150000Z
 LOCATION:my place
+UID:[id-4]
 END:VEVENT
 END:VCALENDAR
 """.replace(/\n/g, '\r\n')
@@ -127,9 +131,9 @@
                 valarm = new VAlarm date
                 valarm.toString().should.equal """
 BEGIN:VALARM
-ACTION:AUDIO
-REPEAT:1
-TRIGGER:20130609T150000
+ACTION:DISPLAY
+REPEAT:1
+TRIGGER:20130609T150000Z
 END:VALARM""".replace(/\n/g, '\r\n')

         describe 'get vTodo string', ->
@@ -138,7 +142,7 @@
                 vtodo = new VTodo date, "superuser", "ma description"
                 vtodo.toString().should.equal """
 BEGIN:VTODO
-DTSTAMP:20130609T150000
+DTSTAMP:20130609T150000Z
 SUMMARY:ma description
 UID:superuser
 END:VTODO""".replace(/\n/g, '\r\n')
@@ -147,13 +151,14 @@
             it 'should return default vEvent string', ->
                 startDate = new Date 2013, 5, 9, 15, 0, 0
                 endDate = new Date 2013, 5, 10, 15, 0, 0
-                vevent = new VEvent startDate, endDate, "desc", "loc"
+                vevent = new VEvent startDate, endDate, "desc", "loc", "eid"
                 vevent.toString().should.equal """
 BEGIN:VEVENT
 DESCRIPTION:desc
-DTSTART:20130609T150000
-DTEND:20130610T150000
+DTSTART:20130609T150000Z
+DTEND:20130610T150000Z
 LOCATION:loc
+UID:eid
 END:VEVENT""".replace(/\n/g, '\r\n')

@@ -170,13 +175,13 @@
 VERSION:2.0
 PRODID:-//Cozy Cloud//NONSGML Cozy Agenda//EN
 BEGIN:VTODO
-DTSTAMP:20130609T150000
+DTSTAMP:20130609T150000Z
 SUMMARY:ma description
 UID:superuser
 BEGIN:VALARM
-ACTION:AUDIO
-REPEAT:1
-TRIGGER:20130609T150000
+ACTION:DISPLAY
+REPEAT:1
+TRIGGER:20130609T150000Z
 END:VALARM
 END:VTODO
 END:VCALENDAR""".replace(/\n/g, '\r\n')
@@ -203,19 +208,20 @@

             it 'toIcal', ->
                 alarm = new Alarm
+                    id: "testid"
                     action: "EMAIL"
                     description: "Something else to remind"
                     trigg: "Tue Apr 24 2013 13:30:00"
                     timezone: "Europe/Paris"
                 alarm.toIcal().toString().should.equal """
 BEGIN:VTODO
-DTSTAMP:20130424T133000
+DTSTAMP:20130424T133000Z
 SUMMARY:Something else to remind
-UID:undefined
-BEGIN:VALARM
-ACTION:AUDIO
-REPEAT:1
-TRIGGER:20130424T133000
+UID:testid
+BEGIN:VALARM
+ACTION:DISPLAY
+REPEAT:1
+TRIGGER:20130424T133000Z
 END:VALARM
 END:VTODO""".replace(/\n/g, '\r\n')

@@ -247,6 +253,7 @@
         describe 'Events', ->
             it 'toIcal', ->
                 event = new Event
+                    id: "testid"
                     place: "my place"
                     description: "my description"
                     start: "Tue Apr 24 2013 13:30:00"
@@ -254,9 +261,10 @@
                 event.toIcal().toString().should.equal """
 BEGIN:VEVENT
 DESCRIPTION:my description
-DTSTART:20130424T133000
-DTEND:20130425T133000
+DTSTART:20130424T133000Z
+DTEND:20130425T133000Z
 LOCATION:my place
+UID:testid
 END:VEVENT""".replace(/\n/g, '\r\n')

             it 'fromIcal', ->
@@ -296,6 +304,9 @@

     describe 'Resources', ->
         describe "GET /export/calendar.ics", ->
+
+            ids = null
+
             before (done) ->
                 initDb = (callback) ->
                     async.series [
@@ -312,7 +323,10 @@
                                             "Sun Jun 10 2013 15:00:00",
                                             "my place", "", "my description",
                                             "Indian/Cocos")
-                    ], ->
+                    ], (err, results) ->
+
+                        ids = results.map (doc) -> doc.id
+
                         callback()
                 helpers.cleanDb ->
                     initDb done
@@ -324,7 +338,13 @@
                 , false

             it "Then it should contains my alarms", ->
+
                 @body.should.equal expectedContent
+                    .replace('[id-1]', ids[0])
+                    .replace('[id-2]', ids[1])
+                    .replace('[id-3]', ids[2])
+
+                    .replace('[id-4]', ids[3])

         describe "POST /import/ical", ->


collision with regular bounds

collision with regular bounds

--- test/collision.coffee
+++ test/collision.coffee
@@ -47,7 +47,7 @@
   Collision.collide player, [enemy, enemy2], (p, e) ->
     ok(true)

-test "Collision.rayRectangle", ->
+test "Collision.rayRectangle with ", ->
   rect = GameObject
     x: 25
     y: 0


collision with regular bounds

collision with regular bounds

--- test/collision.coffee
+++ test/collision.coffee
@@ -59,5 +59,5 @@

   p1 = Collision.rayRectangle start, rect.bounds()

-  equals p1.
+  equals p1.y
 module()


finish #12934: 定義回傳 給 Trm 的 Conversion Pixel 的 Spec

--- test/main.spec.coffee
+++ test/main.spec.coffee
@@ -4,6 +4,7 @@
 trm.DEBUG = true

 describe "tracking system test", (done) ->
+
   it "run with path return", (done) ->
     optUrl = "caesarchi.com/test.js"
     trm.config(optUrl)
@@ -52,6 +53,7 @@
       done()

 describe "compress content", (done) ->
+
   it "only compress", (done) ->
     content = """
       var hello = function () {
@@ -60,7 +62,7 @@
       };
     """
     result = trm.compressContent(content)
-
+
     code = result.code
     code.should.be.a.string
     code.indexOf("\n").should.be.equal(-1)
@@ -74,6 +76,20 @@
     result.indexOf("-9999").should.not.be.equal(-1)
     done()

+  it  ", trackingCode response after calling PMD_TRACK server", (done) ->
+    # after calling window.analytics.send("");
+    result =
+      code: 200
+      status: "ok"
+      fbConversionInfo:
+        fbConversionIds: ["6030451885106"]
+    result.should.be.an.Object
+    result.code.should.equal(200)
+    result.status.should.equal('ok')
+    result.fbConversionInfo.should.be.Object
+    result.fbConversionInfo.fbConversionIds.should.be.Array
+    done()
+
 # TRM = require("../out/trm")
 # trmLib = new TRM()

@@ -83,4 +99,3 @@
 #     console.log trmLib
 #     result = trmLib._getAdGroupId(url)
 #     console.log result
-


New Spanish text from Hila Levy

New Spanish text from Hila Levy

--- src/translations/es.coffee
+++ src/translations/es.coffee
@@ -1,26 +1,26 @@
 module.exports =
-  home: 'Home'
+  home: 'Inicio'
   classify: 'Clasificar'
   profile: 'Perfil'
   science: 'Ciencia'
-  team: 'Equipos'
+  team: 'Equipo'

-  getStarted: 'Get started!'
-  thankYou: 'Thank you. Your classification has been recorded.'
+  getStarted: 'Comienza aquí!'
+  thankYou: 'Gracias. Su clasificación se ha registrado.'
   yes: 'Sí'
   no: 'No'
-  talkQuestion: 'Do you want to talk about this image?'
-  existingComments: 'There are already — comments.'
-  share: 'Share this image:'
-  next: 'Siguiente'
-  previous: 'Previous'
-  finished: 'Hecho'
-  back: 'Back'
+  talkQuestion: '¿Quiere comentar sobre esta imagen?'
+  existingComments: 'Ya hay — comentario(s).'
+  share: 'Comparte esta imagen:'
+  next: 'Siguiente'
+  previous: 'Anterior'
+  finished: 'He terminado'
+  back: 'Regresar'

   favorite: 'Favorito'
   favoriteIcon: ''
   favoriteIconChecked: ''
-  hideOldMarks: 'Hide old marks'
+  hideOldMarks: 'Ocultar marcas previas'
   hideOldMarksIcon: ''
   hideOldMarksIconChecked: ''
   restartTutorial: 'Ver tutorial'


Add People's contest digital archive

Add People's contest digital archive

--- app/router.cjsx
+++ app/router.cjsx
@@ -163,6 +163,7 @@
     <MonorepoRoute path="/projects/zookeeper/galaxy-zoo-weird-and-wonderful" />
     <MonorepoRoute path="/projects/hughdickinson/superwasp-black-hole-hunters" />
     <MonorepoRoute path="/projects/bogden/scarlets-and-blues" />
+    <MonorepoRoute path="/projects/kmc35/peoples-contest-digital-archive" />

     <Route path="/projects/mschwamb/planet-four/authors" component={() => <ExternalRedirect newUrl='https://authors.planetfour.org/' />} />


Check plan() and plans(), not plans() twice

--- js/inner.coffee
+++ js/inner.coffee
@@ -394,7 +394,7 @@
     # billing
     @plans = ko.observable()
     @individualPlan = @komp =>
-      if @plans()? and @plans()?
+      if @plan()? and @plans()?
         @plans()[@plan()]


rotatable tests

rotatable tests

--- test/rotatable.coffee
+++ test/rotatable.coffee
@@ -1,6 +1,6 @@
 test "Rotatable objects update their rotation", ->
   obj = GameObject
-    duration: 5
+    rotationalVelocity: Math.TAU / 4

   obj.include(Durable)


requie as dependency level, not in module

--- source/parrot.coffee
+++ source/parrot.coffee
@@ -3,4 +3,3 @@
 parrot = @parrot =
   version  : '0.12.14'
   $        : if $$? then $$ else $ # DOM Handler Facade
-  _partial : require 'fn-partial'


Fix invalid call to Util.logError

Fix invalid call to Util.logError

--- src/fleep.coffee
+++ src/fleep.coffee
@@ -42,7 +42,7 @@
     Util.debug 'Adapter options:'
     Util.debug @options

-    return @logError 'No email provided to Hubot' unless @options.email
+    return Util.logError 'No email provided to Hubot' unless @options.email
     return @logError 'No password provided to Hubot' unless @options.password
     return @logError 'No conversation IDs provided to Hubot' unless @options.conversations.length


test a tiqav image

test a tiqav image

--- test/lgtm_test.coffee
+++ test/lgtm_test.coffee
@@ -33,3 +33,13 @@

     adapter.receive(new TextMessage(user, 'lgtm'))

+  it 'should respond to a tiqav image', (done) ->
+    adapter.on 'send', (envelope, strings) ->
+      try
+        expect(strings[0]).to.match(/^https?:\/\/tiqav\.com\//)
+        done()
+      catch e
+        done e
+
+    adapter.receive(new TextMessage(user, 'hubot reply thanks'))
+


Show seconds in time tooltip

Show seconds in time tooltip

--- resources/assets/coffee/_classes/tooltip-default.coffee
+++ resources/assets/coffee/_classes/tooltip-default.coffee
@@ -133,7 +133,7 @@
       .text time.format('LL')
     $timeEl = $('<span>')
       .addClass 'tooltip-default__time'
-      .text "#{time.format('LT')} #{@tzString(time)}"
+      .text "#{time.format('LTS')} #{@tzString(time)}"

     $('<span>')
       .append $dateEl


Use destructuring assignment for expect.

--- spec/compiler.coffee
+++ spec/compiler.coffee
@@ -4,8 +4,10 @@
   chai = require 'chai' unless chai
   parser = require '../lib/ccss-compiler'

-
-parse = (source, expect, pending) ->
+{expect} = chai
+
+
+parse = (source, expectation, pending) ->
   itFn = if pending then xit else it

   describe source, ->
@@ -13,13 +15,13 @@

     itFn 'should do something', ->
       result = parser.parse source
-      chai.expect(result).to.be.an 'object'
+      expect(result).to.be.an 'object'
     itFn 'commands ✓', ->
-      chai.expect(result.commands).to.eql expect.commands or []
+      expect(result.commands).to.eql expectation.commands or []
     itFn 'selectors ✓', ->
-      chai.expect(result.selectors).to.eql expect.selectors or []
-      #chai.expect(result.vars).to.eql expect.vars or []
-      #chai.expect(result.constraints).to.eql expect.constraints or []
+      expect(result.selectors).to.eql expectation.selectors or []
+      #expect(result.vars).to.eql expectation.vars or []
+      #expect(result.constraints).to.eql expectation.constraints or []

 # Helper function for expecting errors to be thrown when parsing.
@@ -38,12 +40,12 @@

     it predicate, ->
       exercise = -> parser.parse source
-      chai.expect(exercise).to.throw Error, message
+      expect(exercise).to.throw Error, message

 describe 'CCSS-to-AST', ->
   it 'should provide a parse method', ->
-    chai.expect(parser.parse).to.be.a 'function'
+    expect(parser.parse).to.be.a 'function'

   # Basics
   # ====================================================================


syntax cleanup

syntax cleanup

--- spec/git-spec.coffee
+++ spec/git-spec.coffee
@@ -7,14 +7,14 @@
 pathToSubmoduleFile = Path.get "~/some/submodule/file"

 mockRepo =
-  getWorkingDirectory: () -> Path.get "~/some/repository"
-  refreshStatus: () -> undefined
+  getWorkingDirectory: -> Path.get "~/some/repository"
+  refreshStatus: -> undefined
   relativize: (path) -> "directory/file" if path is pathToRepoFile
   repo:
     submoduleForPath: (path) -> undefined

 mockSubmodule =
-  getWorkingDirectory: () -> Path.get "~/some/submodule"
+  getWorkingDirectory: -> Path.get "~/some/submodule"
   relativize: (path) -> "file" if path is pathToSubmoduleFile

 mockRepoWithSubmodule = Object.create(mockRepo)
@@ -41,63 +41,63 @@
       expect(git.getSubmodule(pathToRepoFile)).toBe undefined

     it "returns a submodule when given file is in a submodule of a project repo", ->
-      spyOn(atom.project, 'getRepositories').andCallFake () -> [mockRepoWithSubmodule]
+      spyOn(atom.project, 'getRepositories').andCallFake -> [mockRepoWithSubmodule]
       expect(git.getSubmodule(pathToSubmoduleFile).getWorkingDirectory()).toEqual Path.get "~/some/submodule"

   describe "git.relativize", ->
     it "returns relativized filepath for files in repo", ->
-      spyOn(atom.project, 'getRepositories').andCallFake () -> [mockRepo, mockRepoWithSubmodule]
+      spyOn(atom.project, 'getRepositories').andCallFake -> [mockRepo, mockRepoWithSubmodule]
       expect(git.relativize pathToRepoFile).toBe 'directory/file'
       expect(git.relativize pathToSubmoduleFile).toBe "file"

   describe "git.cmd", ->
     it "returns a promise", ->
       waitsForPromise ->
-        git.cmd().then () -> expect(true).toBeTruthy()
+        git.cmd().then -> expect(true).toBeTruthy()

   describe "git.add", ->
     it "calls git.cmd with ['add', '--all', {fileName}]", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve true
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve true
       waitsForPromise ->
         git.add(mockRepo, file: pathToSubmoduleFile).then (success) ->
           expect(git.cmd).toHaveBeenCalledWith(['add', '--all', pathToSubmoduleFile], cwd: mockRepo.getWorkingDirectory())

     it "calls git.cmd with ['add', '--all', '.'] when no file is specified", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve true
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve true
       waitsForPromise ->
         git.add(mockRepo).then (success) ->
           expect(git.cmd).toHaveBeenCalledWith(['add', '--all', '.'], cwd: mockRepo.getWorkingDirectory())

     it "calls git.cmd with ['add', '--update'...] when update option is true", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve true
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve true
       waitsForPromise ->
         git.add(mockRepo, update: true).then (success) ->
           expect(git.cmd).toHaveBeenCalledWith(['add', '--update', '.'], cwd: mockRepo.getWorkingDirectory())

   describe "git.reset", ->
     it "resets and unstages all files", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve true
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve true
       waitsForPromise ->
-        git.reset(mockRepo).then () ->
+        git.reset(mockRepo).then ->
           expect(git.cmd).toHaveBeenCalledWith ['reset', 'HEAD'], cwd: mockRepo.getWorkingDirectory()

   describe "git.stagedFiles", ->
     it "returns an empty array when there are no staged files", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve ''
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve ''
       waitsForPromise ->
         git.stagedFiles(mockRepo)
         .then (files) ->
           expect(files.length).toEqual 0

     it "returns an array with size 1 when there is a staged file", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve("M\tsomefile.txt")
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve("M\tsomefile.txt")
       waitsForPromise ->
         git.stagedFiles(mockRepo)
         .then (files) ->
           expect(files.length).toEqual 1

     it "returns an array with size 4 when there are 4 staged files", ->
-      spyOn(git, 'cmd').andCallFake () ->
+      spyOn(git, 'cmd').andCallFake ->
         Promise.resolve("M\tsomefile.txt\nA\tfoo.file\nD\tanother.text\nM\tagain.rb")
       waitsForPromise ->
         git.stagedFiles(mockRepo)
@@ -106,14 +106,14 @@

   describe "git.unstagedFiles", ->
     it "returns an empty array when there are no unstaged files", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve ''
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve ''
       waitsForPromise ->
         git.unstagedFiles(mockRepo)
         .then (files) ->
           expect(files.length).toEqual 0

     it "returns an array with size 1 when there is an unstaged file", ->
-      spyOn(git, 'cmd').andCallFake () -> Promise.resolve "M\tsomefile.txt"
+      spyOn(git, 'cmd').andCallFake -> Promise.resolve "M\tsomefile.txt"
       waitsForPromise ->
         git.unstagedFiles(mockRepo)
         .then (files) ->
@@ -121,7 +121,7 @@
           expect(files[0].mode).toEqual 'M'

     it "returns an array with size 4 when there are 4 unstaged files", ->
-      spyOn(git, 'cmd').andCallFake () ->
+      spyOn(git, 'cmd').andCallFake ->
         Promise.resolve("M\tsomefile.txt\nA\tfoo.file\nD\tanother.text\nM\tagain.rb")
       waitsForPromise ->
         git.unstagedFiles(mockRepo)
@@ -132,7 +132,7 @@

     describe "git.unstagedFiles and showUntracked: true", ->
       it "returns an array with size 1 when there is only an untracked file", ->
-        spyOn(git, 'cmd').andCallFake () ->
+        spyOn(git, 'cmd').andCallFake ->
           if git.cmd.callCount is 2
             Promise.resolve "somefile.txt"
           else
@@ -144,7 +144,7 @@
             expect(files[0].mode).toEqual '?'

       it "returns an array of size 2 when there is an untracked file and an unstaged file", ->
-        spyOn(git, 'cmd').andCallFake () ->
+        spyOn(git, 'cmd').andCallFake ->
           if git.cmd.callCount is 2
             Promise.resolve "untracked.txt"
           else
@@ -158,32 +158,32 @@

     describe "git.status", ->
       it "calls git.cmd with 'status' as the first argument", ->
-        spyOn(git, 'cmd').andCallFake () ->
+        spyOn(git, 'cmd').andCallFake ->
           args = git.cmd.mostRecentCall.args
           if args[0][0] is 'status'
             Promise.resolve true
-        git.status(mockRepo).then () -> expect(true).toBeTruthy()
+        git.status(mockRepo).then -> expect(true).toBeTruthy()

     describe "git.refresh", ->
       it "calls git.cmd with 'add' and '--refresh' arguments for each repo in project", ->
-        spyOn(git, 'cmd').andCallFake () ->
+        spyOn(git, 'cmd').andCallFake ->
           args = git.cmd.mostRecentCall.args[0]
           expect(args[0]).toBe 'add'
           expect(args[1]).toBe '--refresh'
-        spyOn(mockRepo, 'getWorkingDirectory').andCallFake () ->
+        spyOn(mockRepo, 'getWorkingDirectory').andCallFake ->
           expect(mockRepo.getWorkingDirectory.callCount).toBe 1
         git.refresh()

       it "calls repo.refreshStatus for each repo in project", ->
-        spyOn(atom.project, 'getRepositories').andCallFake () -> [ mockRepo ]
+        spyOn(atom.project, 'getRepositories').andCallFake -> [ mockRepo ]
         spyOn(mockRepo, 'refreshStatus')
-        spyOn(git, 'cmd').andCallFake () -> undefined
+        spyOn(git, 'cmd').andCallFake -> undefined
         git.refresh()
         expect(mockRepo.refreshStatus.callCount).toBe 1

     describe "git.diff", ->
       it "calls git.cmd with ['diff', '-p', '-U1'] and the file path", ->
-        spyOn(git, 'cmd').andCallFake () ->
+        spyOn(git, 'cmd').andCallFake ->
           args = git.cmd.mostRecentCall.args[0]
           if args[0] is 'diff' and args[1] is '-p' and args[2] is '-U1' and args[3] is pathToRepoFile
             Promise.resolve(true)


Test emojis in CDATA tags

Test emojis in CDATA tags

--- spec/e2e_spec.coffee
+++ spec/e2e_spec.coffee
@@ -176,3 +176,15 @@
       '  <testcase name="1"/>\n' +
       '  <testsuite name="2" tests="0" failures="0" errors="0" skipped="0"/>\n' +
       '  <testcase name="3"/>')
+
+
+  it 'should builder supports emojis in cdata tags', ->
+    emoji = String.fromCodePoint(0x1F926)
+    builder.testCase().standardOutput('Emoji: ' + emoji)
+
+    expect(builder.build()).toBe reportWith(
+      '  <testcase>\n' +
+      '    <system-out>\n' +
+      '      <![CDATA[Emoji: ' + emoji + ']]>\n' +
+      '    </system-out>\n' +
+      '  </testcase>')


Fix iframe parent element

Fix iframe parent element

--- spec/examples.coffee
+++ spec/examples.coffee
@@ -24,8 +24,9 @@
   if info.command
     runtime = fbpspec.subprocess.start info.command, {}, callback
   else if info.protocol == 'iframe'
-    parent = document.getElementById 'fixtures'
-    runner.parentElement =  parent
+    parent = document.createElement 'div'
+    document.body.appendChild parent
+    runner.parentElement = parent
     callback null
   else
     callback null


Adding non-json param aliases.

Adding non-json param aliases.

--- src/index.coffee
+++ src/index.coffee
@@ -1,7 +1,8 @@
-{Db, Server, ObjectID} = require 'mongodb'
+mongodb      = require 'mongodb'
+{Db, Server} = mongodb

 ensureObjectId = (id) ->
-  if typeof id is 'string' then new ObjectID id else id
+  if typeof id is 'string' then new mongodb.ObjectID id else id

 isFunction = (obj) ->
   toString.call(obj) is '[object Function]'
@@ -122,6 +123,14 @@

     @

+  Long: (number) -> new mongodb.Long number
+  ObjectID: (hex) -> new mongodb.ObjectID hex
+  Timestamp: () -> new mongodb.Timestamp()
+  DBRef: (collection, id) -> new mongodb.DBRef collection, id
+  Binary: (buffer) -> new mongodb.Binary buffer
+  Symbol: (string) -> new mongodb.Symbol string
+  Double: (number) -> new mongodb.Double number
+
   _normalizeArguments: (params, options, after) ->
     if isFunction params
       after   = params


Minor reformatting

Minor reformatting

--- src/index.coffee
+++ src/index.coffee
@@ -1,5 +1,4 @@

-# TODO: Support custom "404 Not Found" page.
 # TODO: Support custom "500 Internal Error" page.

 assertTypes = require "assertTypes"
@@ -44,17 +43,18 @@

 # The root request handler.
 onRequest = (req, res) ->
+  app = this
   req.timestamp = now()

   parts = req.url.split "?"
   req.path = parts[0]
   req.query = parseQuery parts[1]

-  req.app = this
+  req.app = app
   req.res = res
   setProto req, Request

-  res.app = this
+  res.app = app
   res.req = req
   setProto res, Response

@@ -64,11 +64,11 @@
     return

   # Prevent long-running requests.
-  if @_timeout > 0
-    req.setTimeout onTimeout, @_timeout
+  if app._timeout > 0
+    req.setTimeout onTimeout, app._timeout

   # Attempt to handle the request.
-  @_layer.try req, res
+  app._layer.try req, res

   # Wait for the response to finish.
   .then ->


Fix --debug CLI switch

Fix --debug CLI switch

Reverts the change in fd3c169209311a036e353bc99892f841a8bbdf0f which broke this feature

--- src/index.coffee
+++ src/index.coffee
@@ -2,12 +2,11 @@

 initSkeleton = require 'init-skeleton'
 loggy = require 'loggy'
-watch = require './watch'

 start = ->
   isDebug = arguments[1]?.debug or arguments[2]?.debug
   process.env.DEBUG = 'brunch:*' if isDebug
-  watch arguments...
+  (require './watch') arguments...

 module.exports =
   new: (skeleton, path) ->


remove empty line

remove empty line

--- src/index.coffee
+++ src/index.coffee
@@ -37,7 +37,6 @@
   @options.ltrim ?= false
   @options.rtrim ?= false
   @options.auto_parse ?= false
-
   # Counter
   @lines = 0
   # Internal usage, state related


support promo query param

support promo query param

--- src/index.coffee
+++ src/index.coffee
@@ -114,7 +114,9 @@
     if r != ''
       referrer = r
   else
-    referrer = getReferrer(queries) ? opts.order?.referrer
+    referrer = getreferrer(queries) ? opts.order?.referrer
+
+  promo = queries.promo ? ''

   items     = store.get 'items'
   cartId    = store.get 'cartId'
@@ -223,9 +225,12 @@
   if referrer? && referrer != ''
     @client.referrer.get(referrer).then((res)=>
       promoCode = res.affiliate.couponId
-      @data.set 'order.promoCode', promoCode
+      @data.set 'order.promocode', promocode
       m.trigger Events.ForceApplyPromoCode
     ).catch ->
+  else if promo != ''
+    @data.set 'order.promocode', promo
+    m.trigger Events.ForceApplyPromoCode

   ps = []
   for tag in tags


Set 'maxHeadersCount' to 50

Set 'maxHeadersCount' to 50

--- src/index.coffee
+++ src/index.coffee
@@ -23,6 +23,8 @@
     if options.secure
     then require("https").createServer ssl(), app
     else require("http").createServer app
+
+  server.maxHeadersCount = 50

   app.port = port =
     options.port or


Modified project root to export Daemon

Modified project root to export Daemon

--- src/index.coffee
+++ src/index.coffee
@@ -1 +1,5 @@
 {Daemon} = require './daemon'
+
+module.exports = {
+  Daemon
+}


A small check to run linter.

A small check to run linter.

--- src/lists.coffee
+++ src/lists.coffee
@@ -31,7 +31,7 @@
   cons(item, vectorToList(v, p + 1))

 list = (v...) ->
-  ln = v.length;
+  ln = v.length
   (nl = (a) ->
     cons(v[a], if (a < ln) then (nl(a + 1)) else nil))(0)


Fix Edge @property test

Fix Edge @property test

--- test/spec/edge.coffee
+++ test/spec/edge.coffee
@@ -43,10 +43,10 @@
                 it "should change specificed property", ->
                     testEdge = alchemy._edges["1-0"]
                     # Initial caption is "Maintains"
-                    initialCaption = testEdge._rawEdge.caption
+                    initialCaption = testEdge.properties.caption

                     testEdge.setProperty "caption", "newCaption"
-                    newCaption = testEdge._rawEdge.caption
+                    newCaption = testEdge.properties.caption

                     initialCaption.should.not.equal newCaption &&
                     newCaption.should.not.equal "Maintains"


fix(model): all console.errors are now thrown errors

--- src/model.coffee
+++ src/model.coffee
@@ -7,8 +7,7 @@
   'use strict'

   unless options.connector?
-    console.error 'No connector given for api: ' + options.api
-    return
+    throw new Error 'No connector given for api: ' + options.api

   options.connector.init options.api

@@ -70,16 +69,13 @@
         fn = window[data.model]

         if typeof fn != 'function'
-          console.error 'No model for has_one/belongs_to relation found'
-          continue
-
-        if typeof self[name + '_id'] != 'function' && name not in options.belongs_to
+          throw new Error 'No model for has_one/belongs_to relation found'
+
+        if typeof self[name + '_id'] != 'function' && name not in options.belongs_to && name + '_id' not in options.editable
           unless options.editable?
             options.editable = []

           options.editable.push name + '_id'
-          console.log self[name + 'id']
-

         if self[name]?
           Observable self, name, new fn(self[name])
@@ -148,6 +144,7 @@
     # Set editable fields
     #
     if options.editable?
+      console.log options.editable
       for index, name of options.editable
         Editable self, name, DelayedSave.apply(self, [options, self])

@@ -179,8 +176,7 @@
     #
     self.update = (params, callback) =>
       unless self.id?
-        console.error 'Trying to update nonexisting model object'
-        return false
+        throw new Error 'Trying to update nonexisting model object'

       self.api().update(self.id, params).done callback

@@ -188,8 +184,7 @@
     #
     self.destroy = (callback) =>
       unless self.id?
-        console.error 'Trying to delete nonexisting model object'
-        return false
+        throw new Error 'Trying to delete nonexisting model object'

       self.api().destroy(self.id).done callback

@@ -229,7 +224,7 @@
     return self

   ###
-  # These are the collector functions and are not bound to a specific object but to the model
+  # These are the collection functions and are not bound to a specific object but to the model
   ###

   # Get objects from API and save into specified observable or callback
@@ -241,14 +236,12 @@

     if typeof callbackOrObservable['push'] == 'undefined'
       if typeof callbackOrObservable != 'function'
-        console.log 'model.get 2nd parameter needs to be either a function or a pushable object (Array, ObservableArray).\nGiven:'
-        console.log callbackOrObservable
+        throw new Error 'Collection.get 2nd parameter needs to be either a function or a pushable object (Array, ObservableArray).\nGiven: ' + callbackOrObservable

       callback = callbackOrObservable

     if typeof params != 'object'
-      console.error params, typeof params
-      return
+      throw new Error 'Passed params is not an object: ' + typeof params

     if params? && params.id?
       connector.read(params.id, params).done callback
@@ -279,8 +272,7 @@

     if typeof callbackOrObservable['push'] == 'undefined'
       if typeof callbackOrObservable != 'function'
-        console.log 'model.create 2nd parameter needs to be either a function or a pushable object (Array, ObservableArray).\nGiven:'
-        console.log callbackOrObservable
+        throw new Error 'Collection.create 2nd parameter needs to be either a function or a pushable object (Array, ObservableArray).\nGiven: ' + callbackOrObservable

       callback = (data) =>
         # Copy object hack


Setting the 'title' property on a window as either a function or string will set the window title

--- src/views/ui/window.coffee
+++ src/views/ui/window.coffee
@@ -11,6 +11,13 @@
       _.extend {}, styles.view, extensions
     else
       styles.view
+
+  initialize: ->
+
+    if @title
+      @view.title = _.result @, 'title'
+
+    super

   events:
     close: 'destroy'


artik710.coffee: Adapt sw name for the nu PCB

Signed-off-by: Andrei Gherzan <8dc7c09356db0b1762fb140617d7375c0a5a4131@resin.io>

--- artik710.coffee
+++ artik710.coffee
@@ -1,10 +1,10 @@
 deviceTypesCommon = require '@resin.io/device-types/common'
 { networkOptions, commonImg, instructions } = deviceTypesCommon

-BOARD_SHUTDOWN_ARTIK = 'The device is performing a shutdown. Wait 30 seconds and press the power switch SW5 to the off position.'
-SET_JUMPER_SD = 'Set SW4 dip switch to position 1:off, 2:off, 3:off, 4:on.'
-SET_JUMPER_EMMC = 'Set SW4 dip switch to position 1:off, 2:off, 3:off, 4:off.'
-BOARD_POWERON_ARTIK = 'Press the power switch SW5 to the on position. Press and hold for 1 second the SW2 POWER push button.'
+BOARD_SHUTDOWN_ARTIK = 'The device is performing a shutdown. Wait 30 seconds or until the blue LED 703 is off and switch SW700 to the off position.'
+SET_JUMPER_SD = 'Set SW402 dip switch to position 1:off, 2:off, 3:off, 4:on.'
+SET_JUMPER_EMMC = 'Set SW402 dip switch to position 1:off, 2:off, 3:off, 4:off.'
+BOARD_POWERON_ARTIK = 'Switch SW700 to the on position. Press and hold for 1 second the SW400 POWER push button.'

 postProvisioningInstructions = [
 	BOARD_SHUTDOWN_ARTIK


suppress warning

suppress warning

--- views/single-tabarea.cjsx
+++ views/single-tabarea.cjsx
@@ -179,7 +179,7 @@
                <FontAwesome name='sitemap' />{__ ' Plugins'}
            }
         </NavItem>
-        <NavDropdown id='plugin-dropdown' key={-1} eventKey={-1} pullRight open={@state.dropdownOpen} onToggle={@handleToggleDropdown}>
+        <NavDropdown id='plugin-dropdown' key={-1} eventKey={-1} pullRight open={@state.dropdownOpen} onToggle={@handleToggleDropdown} title=''>
         {
           counter = 1
           plugins.map (plugin, index) =>


tests: make callback non-optional

tests: make callback non-optional

We always pass it anyway.

--- test/test-ping.coffee
+++ test/test-ping.coffee
@@ -40,7 +40,7 @@
     console.log 'ERROR', e

 flush_and_assert = (callback) ->
-  flush_assertions.push(callback) if callback
+  flush_assertions.push(callback)
   ping.kill 'SIGUSR2'

 delay 500, ->


this. => @

this. => @

--- src/point.coffee
+++ src/point.coffee
@@ -47,15 +47,15 @@
     @type Point
     ###
     add: (first, second) ->
-      this.copy().add$(first, second)
+      @copy().add$(first, second)

     add$: (first, second) ->
       if second?
-        this.x += first
-        this.y += second
+        @x += first
+        @y += second
       else
-        this.x += first.x
-        this.y += first.y
+        @x += first.x
+        @y += first.y

       this

@@ -69,15 +69,15 @@
     @type Point
     ###
     subtract: (first, second) ->
-      this.copy().subtract$(first, second)
+      @copy().subtract$(first, second)

     subtract$: (first, second) ->
       if second?
-        this.x -= first
-        this.y -= second
+        @x -= first
+        @y -= second
       else
-        this.x -= first.x
-        this.y -= first.y
+        @x -= first.x
+        @y -= first.y

       this

@@ -91,11 +91,11 @@
     @type Point
     ###
     scale: (scalar) ->
-      this.copy().scale$(scalar)
+      @copy().scale$(scalar)

     scale$: (scalar) ->
-      this.x *= scalar
-      this.y *= scalar
+      @x *= scalar
+      @y *= scalar

       this

@@ -109,11 +109,11 @@
     @type Point
     ###
     norm: (length=1.0) ->
-      this.copy().norm$(length)
+      @copy().norm$(length)

     norm$: (length=1.0) ->
       if m = this.length()
-        this.scale$(length/m)
+        @scale$(length/m)
       else
         this

@@ -126,11 +126,11 @@
     @type Point
     ###
     floor: ->
-      this.copy().floor$()
+      @copy().floor$()

     floor$: ->
-      this.x = this.x.floor()
-      this.y = this.y.floor()
+      @x = @x.floor()
+      @y = @y.floor()

       this

@@ -144,7 +144,7 @@
     @type Boolean
     ###
     equal: (other) ->
-      this.x == other.x && this.y == other.y
+      @x == other.x && @y == other.y

     ###*
     Computed the length of this point as though it were a vector from (0,0) to (x,y)
@@ -155,7 +155,7 @@
     @type Number
     ###
     length: ->
-      Math.sqrt(this.dot(this))
+      Math.sqrt(@dot(this))

     ###*
     Calculate the magnitude of this Point (Vector).
@@ -166,7 +166,7 @@
     @type Number
     ###
     magnitude: ->
-      this.length()
+      @length()

     ###*
     Returns the direction in radians of this point from the origin.
@@ -176,7 +176,7 @@
     @type Number
     ###
     direction: ->
-      Math.atan2(this.y, this.x)
+      Math.atan2(@y, @x)

     ###*
     Calculate the dot product of this point and another point (Vector).
@@ -188,7 +188,7 @@
     @type Number
     ###
     dot: (other) ->
-      this.x * other.x + this.y * other.y
+      @x * other.x + @y * other.y

     ###*
     Calculate the cross product of this point and another point (Vector).
@@ -204,7 +204,7 @@
     @type Number
     ###
     cross: (other) ->
-      this.x * other.y - other.x * this.y
+      @x * other.y - other.x * @y

     ###*
     Computed the Euclidean between this point and another point.


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/point.coffee
+++ src/point.coffee
@@ -44,10 +44,10 @@

   Point:: =
     ###*
-
+
     ###
     clamp: (n) ->
-      @copy().clamp*()
+      @copy().clamp$()

     clamp$: (n) ->
       if @magnitude() > n


Fix typo in API docs: Misspelled 'specified'

--- src/robot.coffee
+++ src/robot.coffee
@@ -271,7 +271,7 @@
       for file in Fs.readdirSync(path).sort()
         @loadFile path, file

-  # Public: Load scripts specfied in the `hubot-scripts.json` file.
+  # Public: Load scripts specified in the `hubot-scripts.json` file.
   #
   # path    - A String path to the hubot-scripts files.
   # scripts - An Array of scripts to load.
@@ -282,7 +282,7 @@
     for script in scripts
       @loadFile path, script

-  # Public: Load scripts from packages specfied in the
+  # Public: Load scripts from packages specified in the
   # `external-scripts.json` file.
   #
   # packages - An Array of packages containing hubot scripts to load.


handle slashes in regexes properly

handle slashes in regexes properly

--- src/robot.coffee
+++ src/robot.coffee
@@ -37,14 +37,19 @@
   # Returns nothing.
   respond: (regex, callback) ->
     re = regex.toString().split("/")
-    if re[1] and re[1][0] == "^"
+    re.shift()           # remove empty first item
+    modifiers = re.pop() # pop off modifiers
+
+    if re[0] and re[0][0] == "^"
       console.log "\nWARNING: Anchors don't work well with respond, perhaps you want to use 'hear'"
       console.log "WARNING: The regex in question was #{regex.toString()}\n"

+    pattern = re.join("/") # combine the pattern back again
     if @enableSlash
-      newRegex = new RegExp("^(\/|#{@name}:?)\\s*#{re[1]}", re[2])
+      newRegex = new RegExp("^(\/|#{@name}:?)\\s*#{pattern}", modifiers)
     else
-      newRegex = new RegExp("^#{@name}:?\\s*#{re[1]}", re[2])
+      newRegex = new RegExp("^#{@name}:?\\s*#{pattern}", modifiers)
+
     @listeners.push new Listener(@, newRegex, callback)

   # Public: Passes the given message to any interested Listeners.


bug fix

bug fix

--- src/stack.coffee
+++ src/stack.coffee
@@ -121,12 +121,14 @@
       @currentPage.request.abort()
       @currentPage.request = null

+    return false if @currentPage.unload() == false
+
     if opts.replace
       for page, i in @stack
+        continue if page == @currentPage
         $link = page.el.find '.link-page-behind'
         pageUrl = simple.url $link.attr('href')
-        if pageUrl.pathname == url.pathname and page != @currentPage
-          return false if @currentPage.unload() == false
+        if pageUrl.pathname == url.pathname
           page.el.nextAll('.page').remove()
           @stack = @stack.slice(0, i + 1)
           @currentPage = page
@@ -154,7 +156,6 @@
       @currentPage.load url,
         nocache: opts.nocache
     else
-      return false if @currentPage.unload() == false
       prevPage = @currentPage
       $('<a/>',
         'class': 'link-page-behind'


shorten regex

shorten regex

--- src/utils.coffee
+++ src/utils.coffee
@@ -24,7 +24,7 @@
       when 'underline'  then return doc.createElement('u')
       when 'link'
         link = doc.createElement('a')
-        value = 'https://' + value unless value.match(/http[s]{0,1}:\/\//)
+        value = 'https://' + value unless value.match(/https?:\/\//)
         link.href = value
         link.href = 'about:blank' if (link.protocol != 'http:' && link.protocol != 'https:')
         link.title = link.href


Normalize relative paths to start with './'.

--- src/utils.coffee
+++ src/utils.coffee
@@ -112,7 +112,7 @@
 # Gets path relative to basePath and normalizes it.
 exports.normalizePath = (absolutePath, basePath) ->
   if (absolutePath.indexOf basePath) != -1
-    normalizedPath = absolutePath.replace basePath, ''
+    normalizedPath = '.' + absolutePath.replace basePath, ''
   else
     start = absolutePath.indexOf 'node_modules'
     normalizedPath = absolutePath.substring start, absolutePath.length


only `npm install` on package changes

only `npm install` on package changes

also log info message when watcher is reloading for config changes

--- src/watch.coffee
+++ src/watch.coffee
@@ -190,6 +190,7 @@
   if reInstall
     helpers.install config.paths.root, reWatch
   else
+    logger.info "Reloading watcher..."
     reWatch()

 getPlugins = (packages, config) ->
@@ -303,8 +304,8 @@
     .on 'change', (path) ->
       # If file is special (config.coffee, package.json), restart Brunch.
       isConfigFile = possibleConfigFiles[path]
-      if path is config.paths.packageConfig or isConfigFile
-        reload yes
+      if isConfigFile or reInstall = path is config.paths.packageConfig
+        reload reInstall
       else
         # Otherwise, just update file list.
         onChange()