From b06d7f9628c3a3e5ac77d1635cf4062028d6a0d9 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 15 Mar 2013 16:30:28 +0100 Subject: [PATCH 01/15] Tabs on the sidebar, the beginning based on @svenfuchs work --- .../scripts/app/templates/layouts/sidebar.hbs | 20 ++++++-- assets/scripts/app/views/sidebar.coffee | 18 ++++++- assets/styles/right/lists.sass | 48 +++++++++++++++++-- 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/assets/scripts/app/templates/layouts/sidebar.hbs b/assets/scripts/app/templates/layouts/sidebar.hbs index 9383426f..3921f4dd 100644 --- a/assets/scripts/app/templates/layouts/sidebar.hbs +++ b/assets/scripts/app/templates/layouts/sidebar.hbs @@ -9,9 +9,23 @@ {{view view.DecksView}} -{{view view.WorkersView}} -{{view view.RunningJobsView}} -{{view view.QueuesView}} + + + +
+ {{outlet pane}} +
+ {{view view.LinksView}}
diff --git a/assets/scripts/app/views/sidebar.coffee b/assets/scripts/app/views/sidebar.coffee index 782171f8..47bbdd7b 100644 --- a/assets/scripts/app/views/sidebar.coffee +++ b/assets/scripts/app/views/sidebar.coffee @@ -2,6 +2,22 @@ SidebarView: Travis.View.extend templateName: 'layouts/sidebar' + activate: (name) -> + @set('activeTab', name) + @connectOutlet 'pane', @["#{name.capitalize()}View"].create(controller: @get('controller')) + + classQueues: (-> + 'active' if @get('activeTab') == 'queues' + ).property('activeTab') + + classWorkers: (-> + 'active' if @get('activeTab') == 'workers' + ).property('activeTab') + + classJobs: (-> + 'active' if @get('activeTab') == 'jobs' + ).property('activeTab') + DecksView: Em.View.extend templateName: "sponsors/decks" init: -> @@ -26,7 +42,7 @@ @_super.apply this, arguments @set 'controller', @get('controller').container.lookup('controller:queues') - RunningJobsView: Em.View.extend + JobsView: Em.View.extend templateName: 'jobs/running' elementId: 'running-jobs' init: -> diff --git a/assets/styles/right/lists.sass b/assets/styles/right/lists.sass index 1d8fe8b6..e2eb78f8 100644 --- a/assets/styles/right/lists.sass +++ b/assets/styles/right/lists.sass @@ -1,12 +1,51 @@ @import "_mixins/all" #right - #queues - margin-top: 0 + .tabs + margin-top: 28px + height: 25px + border-bottom-color: $color-border-light + + li + display: inline-block + height: 24px + margin-right: 3px + background-color: $color-bg-right + border: 1px solid $color-bg-right + border-bottom-color: $color-border-light + white-space: nowrap + cursor: pointer + @include border-top-radius(4px) + font-size: 10px + + &:hover + background-color: $color-bg-tab-hover + border-color: $color-border-light + border-bottom-color: $color-bg-tab-active + + .active + background-color: $color-bg-tab-active + border-color: $color-border-light + border-bottom-color: $color-bg-tab-active + + h5 + margin: 0 + font-size: $font-size-small + font-weight: normal + line-height: 26px + + a + display: block + padding: 0 10px + + .pane + position: relative #toggle-workers + position: absolute + top: -30px + right: 5px display: inline-block - float: right width: 10px height: 10px cursor: pointer @@ -17,6 +56,9 @@ #workers li ul display: none + #queues + margin-top: 0 + #workers li, #queues ul li overflow: hidden From aedddd8afe975b59828ca4e72280edd51a2d4345 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 15 Mar 2013 19:22:24 +0100 Subject: [PATCH 02/15] Display only jobs and workers in tabs --- assets/scripts/app/controllers/sidebar.coffee | 3 +++ assets/scripts/app/templates/jobs/running.hbs | 2 -- assets/scripts/app/templates/layouts/sidebar.hbs | 7 ++----- assets/scripts/app/templates/workers/list.hbs | 5 +---- assets/scripts/app/views/sidebar.coffee | 5 +++++ assets/styles/right/lists.sass | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/assets/scripts/app/controllers/sidebar.coffee b/assets/scripts/app/controllers/sidebar.coffee index 42bfd638..e691cd6f 100644 --- a/assets/scripts/app/controllers/sidebar.coffee +++ b/assets/scripts/app/controllers/sidebar.coffee @@ -1,5 +1,8 @@ Travis.reopen SidebarController: Em.ArrayController.extend + needs: ['runningJobs'] + jobsBinding: 'controllers.runningJobs' + init: -> @_super.apply this, arguments @tickables = [] diff --git a/assets/scripts/app/templates/jobs/running.hbs b/assets/scripts/app/templates/jobs/running.hbs index 44f4e396..6be98a9a 100644 --- a/assets/scripts/app/templates/jobs/running.hbs +++ b/assets/scripts/app/templates/jobs/running.hbs @@ -1,5 +1,3 @@ -

Running Jobs ({{view.jobs.length}})

-
    {{#each group in view.groups}} {{view view.GroupView groupBinding="group"}} diff --git a/assets/scripts/app/templates/layouts/sidebar.hbs b/assets/scripts/app/templates/layouts/sidebar.hbs index 3921f4dd..4b11b8fa 100644 --- a/assets/scripts/app/templates/layouts/sidebar.hbs +++ b/assets/scripts/app/templates/layouts/sidebar.hbs @@ -11,11 +11,8 @@ {{view view.DecksView}}
      -
    • -
      {{t layouts.application.queues}}
      -
    • -
      {{t layouts.application.jobs}}
      +
      {{t layouts.application.jobs}} ({{jobs.length}})
    • {{t layouts.application.workers}}
      @@ -25,7 +22,7 @@
      {{outlet pane}}
      - +{{view view.QueuesView}} {{view view.LinksView}}
      diff --git a/assets/scripts/app/templates/workers/list.hbs b/assets/scripts/app/templates/workers/list.hbs index af00a44b..c9b777e6 100644 --- a/assets/scripts/app/templates/workers/list.hbs +++ b/assets/scripts/app/templates/workers/list.hbs @@ -1,8 +1,5 @@ {{#view Travis.WorkersView}} -

      - {{t workers}} - -

      +
        {{#each group in controller.groups}} {{#view Travis.WorkersListView}} diff --git a/assets/scripts/app/views/sidebar.coffee b/assets/scripts/app/views/sidebar.coffee index 47bbdd7b..b9401d5b 100644 --- a/assets/scripts/app/views/sidebar.coffee +++ b/assets/scripts/app/views/sidebar.coffee @@ -2,6 +2,11 @@ SidebarView: Travis.View.extend templateName: 'layouts/sidebar' + didInsertElement: -> + @_super.apply this, arguments + + @activate('jobs') + activate: (name) -> @set('activeTab', name) @connectOutlet 'pane', @["#{name.capitalize()}View"].create(controller: @get('controller')) diff --git a/assets/styles/right/lists.sass b/assets/styles/right/lists.sass index e2eb78f8..b74cd3a8 100644 --- a/assets/styles/right/lists.sass +++ b/assets/styles/right/lists.sass @@ -9,7 +9,7 @@ li display: inline-block height: 24px - margin-right: 3px + margin-right: 5px background-color: $color-bg-right border: 1px solid $color-bg-right border-bottom-color: $color-border-light From 894f321a8f718b0af4119149dc219fe43547c49d Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Fri, 22 Mar 2013 02:14:00 +0100 Subject: [PATCH 03/15] some style tweaks to the sidebar tabs /cc @drogus --- assets/scripts/app/templates/layouts/sidebar.hbs | 2 +- assets/styles/right.sass | 1 + assets/styles/right/sponsors.sass | 1 + assets/styles/tabs.sass | 10 ++++++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/assets/scripts/app/templates/layouts/sidebar.hbs b/assets/scripts/app/templates/layouts/sidebar.hbs index 4b11b8fa..5a4ffa18 100644 --- a/assets/scripts/app/templates/layouts/sidebar.hbs +++ b/assets/scripts/app/templates/layouts/sidebar.hbs @@ -12,7 +12,7 @@
        • -
          {{t layouts.application.jobs}} ({{jobs.length}})
          +
          {{t layouts.application.running}} ({{jobs.length}})
        • {{t layouts.application.workers}}
          diff --git a/assets/styles/right.sass b/assets/styles/right.sass index 34eb7169..8150aae6 100644 --- a/assets/styles/right.sass +++ b/assets/styles/right.sass @@ -11,6 +11,7 @@ .box margin-top: 25px + margin-left: -3px padding: 15px border: 1px solid $color-border-normal background-color: $color-bg-sidebar-box diff --git a/assets/styles/right/sponsors.sass b/assets/styles/right/sponsors.sass index 60327a6c..a4b05d49 100644 --- a/assets/styles/right/sponsors.sass +++ b/assets/styles/right/sponsors.sass @@ -4,6 +4,7 @@ .sponsors &.top height: 140px + margin-left: -3px li overflow: hidden diff --git a/assets/styles/tabs.sass b/assets/styles/tabs.sass index b50f2716..a0b779d6 100644 --- a/assets/styles/tabs.sass +++ b/assets/styles/tabs.sass @@ -61,3 +61,13 @@ #main .tab margin: 30px 0 0 12px + +#right + .tabs + margin-left: -3px + + h5 + font-weight: bold + .active + background-color: $color-bg-right + border-bottom-color: $color-bg-right From 8f891168d7cc1bfc2f696c03f2677ea73611587b Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Fri, 22 Mar 2013 02:32:27 +0100 Subject: [PATCH 04/15] un-bold the non-active tab in the sidebar --- assets/styles/tabs.sass | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/styles/tabs.sass b/assets/styles/tabs.sass index a0b779d6..19baa134 100644 --- a/assets/styles/tabs.sass +++ b/assets/styles/tabs.sass @@ -66,8 +66,8 @@ .tabs margin-left: -3px - h5 - font-weight: bold .active background-color: $color-bg-right border-bottom-color: $color-bg-right + h5 + font-weight: bold From 7996358f013b9376cb4780c5a9689d97a06ba8d1 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 2 Apr 2013 20:17:24 +0200 Subject: [PATCH 05/15] Fix fetching log in firefox when Location header is unavailable --- assets/scripts/app/models/log.coffee | 2 +- assets/scripts/spec/unit/log_request_spec.coffee | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 assets/scripts/spec/unit/log_request_spec.coffee diff --git a/assets/scripts/app/models/log.coffee b/assets/scripts/app/models/log.coffee index 125cdec9..f24711d5 100644 --- a/assets/scripts/app/models/log.coffee +++ b/assets/scripts/app/models/log.coffee @@ -64,7 +64,7 @@ Travis.Log.Request = Em.Object.extend endpoint = Travis.config.api_endpoint staging = if endpoint.match(/-staging/) then '-staging' else '' host = endpoint.replace(/^https?:\/\//, '').split('.').slice(-2).join('.') - "https://s3.amazonaws.com/archive#{staging}.#{host}#{path}/jobs/#{@id}/log.txt" + "https://s3.amazonaws.com/archive#{staging}.#{host}/jobs/#{@get('id')}/log.txt" isJson: (xhr, body) -> # Firefox can't see the Content-Type header on the xhr response due to the wrong diff --git a/assets/scripts/spec/unit/log_request_spec.coffee b/assets/scripts/spec/unit/log_request_spec.coffee new file mode 100644 index 00000000..3ec57d18 --- /dev/null +++ b/assets/scripts/spec/unit/log_request_spec.coffee @@ -0,0 +1,6 @@ +describe 'Travis.Log.Request', -> + it 'constructs s3 url for log', -> + Travis.config.api_endpoint = 'api.travis-ci.org' + request = Travis.Log.Request.create(id: 10) + s3Url = "https://s3.amazonaws.com/archive.travis-ci.org/jobs/10/log.txt" + expect( request.s3Url() ).toEqual(s3Url) From 2f6e8082aca007c46f22d98593da155e9f02ef60 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 3 Apr 2013 13:27:52 +0200 Subject: [PATCH 06/15] Show pull request title also in job view --- assets/scripts/app/templates/builds/show.hbs | 2 +- assets/scripts/app/templates/jobs/show.hbs | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/assets/scripts/app/templates/builds/show.hbs b/assets/scripts/app/templates/builds/show.hbs index 64ab8d8d..5dc0751b 100644 --- a/assets/scripts/app/templates/builds/show.hbs +++ b/assets/scripts/app/templates/builds/show.hbs @@ -26,7 +26,7 @@
          {{t builds.commit}}
          {{formatCommit build.commit}}
          {{#if build.pullRequest}} -
          {{t builds.pullRequest}}
          +
          {{t builds.pull_request}}
          #{{build.pullRequestNumber}} {{build.pullRequestTitle}}
          {{else}} {{#if commit.compareUrl}} diff --git a/assets/scripts/app/templates/jobs/show.hbs b/assets/scripts/app/templates/jobs/show.hbs index 1d7a9989..92f4066d 100644 --- a/assets/scripts/app/templates/jobs/show.hbs +++ b/assets/scripts/app/templates/jobs/show.hbs @@ -23,9 +23,14 @@
          {{t jobs.commit}}
          {{formatCommit commit}}
          - {{#if commit.compareUrl}} -
          {{t jobs.compare}}
          -
          {{pathFrom commit.compareUrl}}
          + {{#if job.build.pullRequest}} +
          {{t builds.pull_request}}
          +
          #{{job.build.pullRequestNumber}} {{job.build.pullRequestTitle}}
          + {{else}} + {{#if commit.compareUrl}} +
          {{t jobs.compare}}
          +
          {{pathFrom commit.compareUrl}}
          + {{/if}} {{/if}} {{#if commit.authorName}}
          {{t jobs.author}}
          From cf23f81c40d1268398c2ab939742119023f966aa Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 4 Apr 2013 17:18:41 +0200 Subject: [PATCH 07/15] Typo in tools view: hasPermissions -> hasPermission --- assets/scripts/app/views/repo/show.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/scripts/app/views/repo/show.coffee b/assets/scripts/app/views/repo/show.coffee index 0c0e317d..95209a74 100644 --- a/assets/scripts/app/views/repo/show.coffee +++ b/assets/scripts/app/views/repo/show.coffee @@ -129,7 +129,7 @@ Travis.reopen canRequeueBuild: (-> @get('displayRequeueBuild') && @get('hasPermission') - ).property('displayRequireBuild', 'hasPermissions') + ).property('displayRequireBuild', 'hasPermission') displayRequeueJob: (-> @get('isJobTab') && @get('job.isFinished') @@ -137,7 +137,7 @@ Travis.reopen canRequeueJob: (-> @get('displayRequeueJob') && @get('hasPermission') - ).property('displayRequeueJob', 'hasPermissions') + ).property('displayRequeueJob', 'hasPermission') showDownloadLog: (-> @get('jobIdForLog') From 39d0202d7ac5b821f46f3eaeb802dfcce5ca89e7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 5 Apr 2013 18:09:00 +0200 Subject: [PATCH 08/15] Fix specs, add styling for firefox --- assets/scripts/app/views/application.coffee | 2 +- assets/scripts/app/views/repo/show.coffee | 3 +-- assets/scripts/app/views/sidebar.coffee | 1 + assets/scripts/spec/event_spec.coffee | 10 ++++++++-- assets/scripts/spec/support/conditions.coffee | 1 + assets/styles/right.sass | 1 + 6 files changed, 13 insertions(+), 5 deletions(-) diff --git a/assets/scripts/app/views/application.coffee b/assets/scripts/app/views/application.coffee index 54f18c30..45d414e0 100644 --- a/assets/scripts/app/views/application.coffee +++ b/assets/scripts/app/views/application.coffee @@ -7,7 +7,7 @@ Travis.reopen @rerender() ).observes('templateName') - click: -> + click: (event) -> # TODO: this solves the case of closing menus and popups, # but I would like to rewrite it later, not sure how # yet, but this does not seem optimal diff --git a/assets/scripts/app/views/repo/show.coffee b/assets/scripts/app/views/repo/show.coffee index 0c0e317d..db7ae25e 100644 --- a/assets/scripts/app/views/repo/show.coffee +++ b/assets/scripts/app/views/repo/show.coffee @@ -64,10 +64,9 @@ Travis.reopen currentUserBinding: 'controller.currentUser' closeMenu: -> - console.log 'closeMenu' $('.menu').removeClass('display') - menu: -> + menu: (event) -> @popupCloseAll() $('#tools .menu').toggleClass('display') event.stopPropagation() diff --git a/assets/scripts/app/views/sidebar.coffee b/assets/scripts/app/views/sidebar.coffee index b9401d5b..35103343 100644 --- a/assets/scripts/app/views/sidebar.coffee +++ b/assets/scripts/app/views/sidebar.coffee @@ -8,6 +8,7 @@ @activate('jobs') activate: (name) -> + return if @get('activeTab') == name @set('activeTab', name) @connectOutlet 'pane', @["#{name.capitalize()}View"].create(controller: @get('controller')) diff --git a/assets/scripts/spec/event_spec.coffee b/assets/scripts/spec/event_spec.coffee index ddde0844..f867f868 100644 --- a/assets/scripts/spec/event_spec.coffee +++ b/assets/scripts/spec/event_spec.coffee @@ -121,7 +121,10 @@ describe 'events', -> describe 'an event adding a worker', -> beforeEach -> app '' - waitFor workersRendered + waitFor sidebarTabsRendered + runs -> + $('#right #tab_workers a').trigger('click') + waitFor workersRendered it 'adds a worker to the workers list', -> payload = @@ -155,7 +158,10 @@ describe 'events', -> describe 'an event updating a worker', -> beforeEach -> app '/travis-ci/travis-core' - waitFor workersRendered + waitFor sidebarTabsRendered + runs -> + $('#right #tab_workers a').trigger('click') + waitFor workersRendered it 'does not update repository if it\'s already in the store', -> payload = diff --git a/assets/scripts/spec/support/conditions.coffee b/assets/scripts/spec/support/conditions.coffee index 67a60462..934cada6 100644 --- a/assets/scripts/spec/support/conditions.coffee +++ b/assets/scripts/spec/support/conditions.coffee @@ -12,3 +12,4 @@ @queuesRendered = notEmpty('#queue_linux li') @workersRendered = notEmpty('.worker') +@sidebarTabsRendered = notEmpty('#right #tab_workers a') diff --git a/assets/styles/right.sass b/assets/styles/right.sass index 8150aae6..4d40b06d 100644 --- a/assets/styles/right.sass +++ b/assets/styles/right.sass @@ -57,5 +57,6 @@ white-space: nowrap text-overflow: ellipsis display: inline-block + display: -moz-inline-stack .group a cursor: pointer From d414c47833ffb404691f4f497f9d41db9120d826 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 5 Apr 2013 19:25:30 +0200 Subject: [PATCH 09/15] Don't render links if slug is missing --- assets/scripts/app/templates/jobs/running/group.hbs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/assets/scripts/app/templates/jobs/running/group.hbs b/assets/scripts/app/templates/jobs/running/group.hbs index f7c1b793..ffe27567 100644 --- a/assets/scripts/app/templates/jobs/running/group.hbs +++ b/assets/scripts/app/templates/jobs/running/group.hbs @@ -5,9 +5,11 @@
            {{#each job in sortedJobs}}
          • - {{#linkTo "job" job.repoData job}} - #{{job.number}} - {{/linkTo}} + {{#if job.repoData.slug}} + {{#linkTo "job" job.repoData job}} + #{{job.number}} + {{/linkTo}} + {{/if}}
          • {{/each}}
          From 8a69df012695102b1a8f2c7ae05592b2a0791cdb Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 5 Apr 2013 19:42:53 +0200 Subject: [PATCH 10/15] For some reason passing event breaks on chrome --- assets/scripts/app/views/repo/show.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/scripts/app/views/repo/show.coffee b/assets/scripts/app/views/repo/show.coffee index 8d911947..b0eec1a6 100644 --- a/assets/scripts/app/views/repo/show.coffee +++ b/assets/scripts/app/views/repo/show.coffee @@ -66,7 +66,7 @@ Travis.reopen closeMenu: -> $('.menu').removeClass('display') - menu: (event) -> + menu: -> @popupCloseAll() $('#tools .menu').toggleClass('display') event.stopPropagation() From c7561ee13eff407340cb9f015860685ca39e60ef Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sat, 6 Apr 2013 01:48:32 +0200 Subject: [PATCH 11/15] Properly display matrix keys when build does not have all keys When additional items are included into matrix via 'matrix.include' key in .travis.yml they may contain config keys, which are not available on build. For example build can contain only 'rvm' key, but we may add the following include: matrix: include: - rvm: '2.0.0' env: 'FOO=bar' In such case, we need to take into account also keys from additional job, not only from the build. (closes #172) --- assets/scripts/app/helpers/helpers.coffee | 3 +++ assets/scripts/app/models/branch.coffee | 2 +- assets/scripts/app/models/build.coffee | 15 ++++++++++++--- assets/scripts/app/models/job.coffee | 10 +++++----- assets/scripts/spec/unit/build_spec.coffee | 14 ++++++++++++++ assets/scripts/spec/unit/job_spec.coffee | 17 +++++++++++++++++ 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/assets/scripts/app/helpers/helpers.coffee b/assets/scripts/app/helpers/helpers.coffee index a0f28ec5..1268ff15 100644 --- a/assets/scripts/app/helpers/helpers.coffee +++ b/assets/scripts/app/helpers/helpers.coffee @@ -91,3 +91,6 @@ require 'config/emoij' _escape: (text) -> text.replace(/&/g, '&').replace(//g, '>' + configKeys: (config) -> + return [] unless config + $.intersect($.keys(config), Travis.CONFIG_KEYS) diff --git a/assets/scripts/app/models/branch.coffee b/assets/scripts/app/models/branch.coffee index 4b7ce750..3d45d52d 100644 --- a/assets/scripts/app/models/branch.coffee +++ b/assets/scripts/app/models/branch.coffee @@ -1,6 +1,6 @@ require 'travis/model' -@Travis.Branch = Travis.Model.extend Travis.Helpers, +@Travis.Branch = Travis.Model.extend repoId: DS.attr('number', key: 'repository_id') commitId: DS.attr('number') state: DS.attr('string') diff --git a/assets/scripts/app/models/build.coffee b/assets/scripts/app/models/build.coffee index ca3bb292..9906e770 100644 --- a/assets/scripts/app/models/build.coffee +++ b/assets/scripts/app/models/build.coffee @@ -45,12 +45,21 @@ require 'travis/model' @get('jobs').filter (data) -> data.get('allowFailure') ).property('jobs.@each.allowFailure') + rawConfigKeys: (-> + keys = Travis.Helpers.configKeys(@get('config')) + + @get('jobs').forEach (job) -> + Travis.Helpers.configKeys(job.get('config')).forEach (key) -> + keys.pushObject key unless keys.contains key + + keys + ).property('config', 'jobs.@each.config') + configKeys: (-> - return [] unless config = @get('config') - keys = $.intersect($.keys(config), Travis.CONFIG_KEYS) + keys = @get('rawConfigKeys') headers = (I18n.t(key) for key in ['build.job', 'build.duration', 'build.finished_at']) $.map(headers.concat(keys), (key) -> return $.camelize(key)) - ).property('config') + ).property('rawConfigKeys.length') canCancel: (-> @get('state') == 'created' # TODO diff --git a/assets/scripts/app/models/job.coffee b/assets/scripts/app/models/job.coffee index e54a717c..30251213 100644 --- a/assets/scripts/app/models/job.coffee +++ b/assets/scripts/app/models/job.coffee @@ -61,14 +61,14 @@ require 'travis/model' ).property('log.workerName') configValues: (-> - config = @get('config') - buildConfig = @get('build.config') - if config && buildConfig - keys = $.intersect($.keys(buildConfig), Travis.CONFIG_KEYS) + config = @get('config') + keys = @get('build.rawConfigKeys') + + if config && keys keys.map (key) -> config[key] else [] - ).property('config') + ).property('config', 'build.rawConfigKeys.length') canCancel: (-> @get('state') == 'created' || @get('state') == 'queued' # TODO diff --git a/assets/scripts/spec/unit/build_spec.coffee b/assets/scripts/spec/unit/build_spec.coffee index f7374224..10d3fd9f 100644 --- a/assets/scripts/spec/unit/build_spec.coffee +++ b/assets/scripts/spec/unit/build_spec.coffee @@ -30,3 +30,17 @@ describe 'Travis.Build', -> waits 50 runs -> expect( record.get('incomplete') ).toBeFalsy() + + describe 'configKeys', -> + it 'takes into account all the jobs when getting config keys', -> + buildConfig = { rvm: ['1.9.3', '2.0.0'] } + store.load Travis.Build, { id: '1', job_ids: ['1', '2', '3'], config: buildConfig }, { id: '1' } + + store.load Travis.Job, { id: '1', config: { rvm: '1.9.3', env: 'FOO=foo' } }, { id: '1' } + store.load Travis.Job, { id: '2', config: { rvm: '2.0.0', gemfile: 'Gemfile.1' } }, { id: '2' } + store.load Travis.Job, { id: '3', config: { rvm: '1.9.3', jdk: 'OpenJDK' } }, { id: '3' } + + build = store.find(Travis.Build, '1') + + expect( build.get('rawConfigKeys') ).toEqual( ['rvm', 'env', 'gemfile', 'jdk' ] ) + expect( build.get('configKeys') ).toEqual( [ 'Job', 'Duration', 'Finished', 'Rvm', 'Env', 'Gemfile', 'Jdk' ] ) diff --git a/assets/scripts/spec/unit/job_spec.coffee b/assets/scripts/spec/unit/job_spec.coffee index 42efff80..26fb35a9 100644 --- a/assets/scripts/spec/unit/job_spec.coffee +++ b/assets/scripts/spec/unit/job_spec.coffee @@ -8,6 +8,23 @@ describe 'Travis.Job', -> afterEach -> store.destroy() + describe 'configKeys', -> + it 'takes into account the keys of other jobs', -> + buildConfig = { rvm: ['1.9.3', '2.0.0'] } + store.load Travis.Build, { id: '1', job_ids: ['1', '2', '3'], config: buildConfig }, { id: '1' } + + store.load Travis.Job, { id: '1', config: { rvm: '1.9.3', env: 'FOO=foo' }, build_id: '1' }, { id: '1' } + store.load Travis.Job, { id: '2', config: { rvm: '2.0.0', gemfile: 'Gemfile.1' }, build_id: '1' }, { id: '2' } + store.load Travis.Job, { id: '3', config: { rvm: '1.9.3', jdk: 'OpenJDK' }, build_id: '1' }, { id: '3' } + + job1 = store.find(Travis.Job, '1') + job2 = store.find(Travis.Job, '2') + job3 = store.find(Travis.Job, '3') + + expect( job1.get('configValues') ).toEqual( [ '1.9.3', 'FOO=foo', undefined, undefined ] ) + expect( job2.get('configValues') ).toEqual( [ '2.0.0', undefined, 'Gemfile.1', undefined ] ) + expect( job3.get('configValues') ).toEqual( [ '1.9.3', undefined, undefined, 'OpenJDK' ] ) + describe 'incomplete attributes', -> beforeEach -> store.loadIncomplete Travis.Job, { id: 1, state: 'started' } From bbd37e6e15595fb4e0dd963a2fdfed3ed487ea81 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sun, 7 Apr 2013 19:35:39 +0200 Subject: [PATCH 12/15] Don't try to upload build to S3 for pull requests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7c9864bc..83fefcb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,7 +20,7 @@ before_script: - "bundle exec rakep" - "phantomjs --version" after_script: - - "test $TEST_SUITE = \"ruby\" && travis-artifacts upload --target-path assets/$TRAVIS_BRANCH --path public/scripts:scripts --path public/styles:styles || true" + - "test $TEST_SUITE = \"ruby\" && test $TRAVIS_PULL_REQUEST = \"false\" && travis-artifacts upload --target-path assets/$TRAVIS_BRANCH --path public/scripts:scripts --path public/styles:styles || true" notifications: irc: "irc.freenode.org#travis" From dce72c8b204eacfd7223a6396b40c58852cd08e7 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Sun, 7 Apr 2013 23:58:33 +0200 Subject: [PATCH 13/15] Update log.js --- assets/scripts/vendor/log.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/scripts/vendor/log.js b/assets/scripts/vendor/log.js index 68fb7be1..1de18e93 100644 --- a/assets/scripts/vendor/log.js +++ b/assets/scripts/vendor/log.js @@ -1 +1 @@ -minispade.register('log', "(function() {(function() {\n\n this.Log = function() {\n this.listeners = [];\n this.renderer = new Log.Renderer;\n this.children = new Log.Nodes(this);\n this.parts = {};\n this.folds = new Log.Folds;\n return this;\n };\n\n Log.extend = function(one, other) {\n var name;\n for (name in other) {\n one[name] = other[name];\n }\n return one;\n };\n\n Log.extend(Log, {\n DEBUG: true,\n SLICE: 500,\n TIMEOUT: 25,\n FOLD: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(options) {\n var listener, log, _i, _len, _ref;\n options || (options = {});\n log = new Log();\n if (options.limit) {\n log.listeners.push(log.limit = new Log.Limit(options.limit));\n }\n _ref = options.listeners || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n listener = _ref[_i];\n log.listeners.push(listener);\n }\n return log;\n }\n });\nminispade.require('log/nodes');\n\n Log.prototype = Log.extend(new Log.Node, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return Log.Part.create(this, num, string);\n }\n },\n insert: function(data, pos) {\n this.trigger('insert', data, pos);\n return this.renderer.insert(data, pos);\n },\n remove: function(node) {\n this.trigger('remove', node);\n return this.renderer.remove(node);\n },\n hide: function(node) {\n this.trigger('hide', node);\n return this.renderer.hide(node);\n },\n trigger: function() {\n var args, ix, listener, _i, _len, _ref, _results;\n args = [this].concat(Array.prototype.slice.apply(arguments));\n _ref = this.listeners;\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n listener = _ref[ix];\n _results.push(listener.notify.apply(listener, args));\n }\n return _results;\n }\n });\n\n Log.Listener = function() {};\n\n Log.extend(Log.Listener.prototype, {\n notify: function(log, event) {\n if (this[event]) {\n return this[event].apply(this, [log].concat(Array.prototype.slice.call(arguments, 2)));\n }\n }\n });\nminispade.require('log/folds');\nminispade.require('log/deansi');\nminispade.require('log/limit');\nminispade.require('log/renderer');\n\n}).call(this);\n\n})();\n//@ sourceURL=log");minispade.register('log.old/buffer', "(function() {(function() {\n\n Log.Buffer = function(log, options) {\n this.start = 0;\n this.log = log;\n this.parts = [];\n this.options = $.extend({\n interval: 100,\n timeout: 500\n }, options || {});\n this.schedule();\n return this;\n };\n\n $.extend(Log.Buffer.prototype, {\n set: function(num, string) {\n return this.parts[num] = {\n string: string,\n time: (new Date).getTime()\n };\n },\n flush: function() {\n var num, part, _i, _len, _ref;\n _ref = this.parts;\n for (num = _i = 0, _len = _ref.length; _i < _len; num = ++_i) {\n part = _ref[num];\n if (!this.parts.hasOwnProperty(num)) {\n continue;\n }\n if (!part) {\n break;\n }\n delete this.parts[num];\n this.log.set(num, part.string);\n }\n return this.schedule();\n },\n schedule: function() {\n var _this = this;\n return setTimeout((function() {\n return _this.flush();\n }), this.options.interval);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/buffer");minispade.register('log.old/engine/chunks', "(function() {(function() {\n\n Log.Chunks = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Chunks.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Chunks.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Chunks.Part = function(engine, num, string) {\n var chunk, ix, line, type;\n this.engine = engine;\n this.num = num;\n this.chunks = (function() {\n var _i, _len, _ref, _results;\n _ref = string.split(/^/m);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n chunk = _ref[ix];\n line = chunk[chunk.length - 1].match(/\\r|\\n/);\n type = line ? 'Line' : 'Chunk';\n _results.push(new Log.Chunks[type](this, ix, chunk));\n }\n return _results;\n }).call(this);\n return this;\n };\n\n $.extend(Log.Chunks.Part.prototype, {\n insert: function() {\n var chunk, _i, _len, _ref, _results;\n _ref = this.chunks;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n chunk = _ref[_i];\n _results.push(chunk.insert());\n }\n return _results;\n },\n prev: function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.engine.parts[num -= 1];\n }\n return prev;\n },\n next: function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.engine.parts.length)) {\n next = this.engine.parts[num += 1];\n }\n return next;\n },\n trigger: function() {\n return this.engine.trigger.apply(this.engine, arguments);\n }\n });\n\n Log.Chunks.Chunk = function(part, num, string) {\n this.part = part;\n this.num = num;\n this.string = string;\n this.id = \"\" + (part != null ? part.num : void 0) + \"-\" + num;\n this.isFold = (string != null ? string.indexOf('fold') : void 0) !== -1;\n if (string) {\n this.nodes = this.parse();\n }\n return this;\n };\n\n $.extend(Log.Chunks.Chunk.prototype, {\n parse: function() {\n return [\n {\n type: 'span',\n id: \"\" + this.id + \"-0\",\n text: this.string\n }\n ];\n },\n insert: function() {\n var next, prev;\n if ((next = this.next()) && next.isLine) {\n return this.trigger('insert', this.nodes, {\n before: next.nodes[0].nodes[0].id\n });\n } else if (next) {\n return this.trigger('insert', this.nodes, {\n before: next.nodes[0].id\n });\n } else if ((prev = this.prev()) && !prev.isLine) {\n return this.trigger('insert', this.nodes, {\n after: prev.nodes[prev.nodes.length - 1].id\n });\n } else {\n return this.trigger('insert', [\n {\n type: 'paragraph',\n id: this.id,\n nodes: this.nodes\n }\n ], {\n before: void 0\n });\n }\n },\n remove: function() {\n var node, _i, _len, _ref, _results;\n _ref = this.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n this.trigger('remove', this.id);\n if (node.nodes) {\n _results.push((function() {\n var _j, _len1, _ref1, _results1;\n _ref1 = node.nodes;\n _results1 = [];\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n node = _ref1[_j];\n _results1.push(this.trigger('remove', node.id));\n }\n return _results1;\n }).call(this));\n } else {\n _results.push(void 0);\n }\n }\n return _results;\n },\n reinsert: function() {\n this.remove();\n return this.insert();\n },\n prevLine: function() {\n var prev;\n prev = this.prev();\n while (prev && !prev.isLine) {\n prev = prev.prev();\n }\n return prev;\n },\n nextLine: function() {\n var next;\n next = this.next();\n while (next && !next.isLine) {\n next = next.next();\n }\n return next;\n },\n prev: function() {\n var chunk, _ref;\n chunk = this.part.chunks[this.num - 1];\n return chunk || ((_ref = this.part.prev()) != null ? _ref.chunks.slice(-1)[0] : void 0);\n },\n next: function() {\n var chunk, _ref;\n chunk = this.part.chunks[this.num + 1];\n return chunk || ((_ref = this.part.next()) != null ? _ref.chunks[0] : void 0);\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Chunks.Line = function(part, num, string) {\n Log.Chunks.Chunk.call(this, part, num, string.slice(0, string.length - 1));\n this.isLine = true;\n return this;\n };\n\n Log.Chunks.Line.prototype = $.extend(new Log.Chunks.Chunk, {\n parse: function() {\n return [\n {\n type: 'paragraph',\n id: this.id,\n nodes: [\n {\n type: 'span',\n id: \"\" + this.id + \"-0\",\n text: this.string\n }\n ]\n }\n ];\n },\n insert: function() {\n var next, prev;\n if ((prev = this.prev()) && !prev.isLine) {\n this.trigger('insert', this.nodes[0].nodes, {\n after: prev.nodes[0].id\n });\n document.getElementById(this.nodes[0].nodes[0].id).parentNode.setAttribute('id', this.id);\n if (this.isLine && (next = this.next())) {\n return next.reinsert();\n }\n } else if (prev) {\n return this.trigger('insert', this.nodes, {\n after: prev.id\n });\n } else if (next = this.nextLine()) {\n return this.trigger('insert', this.nodes, {\n before: next.id\n });\n } else {\n return this.trigger('insert', this.nodes, {\n before: void 0\n });\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/chunks");minispade.register('log.old/engine/dom', "(function() {(function() {\n\n Log.Dom = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Dom.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Dom.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Dom.Part = function(engine, num, string) {\n this.engine = engine;\n this.num = num;\n this.string = string.replace(/\\r\\n/gm, '\\n');\n this.nodes = new Log.Dom.Nodes(this);\n return this;\n };\n\n $.extend(Log.Dom.Part.prototype, {\n SLICE: 500,\n insert: function() {\n var ix, lines, next, slices,\n _this = this;\n lines = this.string.split(/^/gm) || [];\n slices = ((function() {\n var _results;\n _results = [];\n while (lines.length > 0) {\n _results.push(lines.splice(0, this.SLICE));\n }\n return _results;\n }).call(this));\n ix = -1;\n next = function() {\n _this.insertSlice(slices.shift(), ix += 1);\n if (slices.length !== 0) {\n return setTimeout(next, 50);\n }\n };\n return next();\n },\n insertSlice: function(lines, start) {\n var ix, line, node, _i, _len, _ref, _ref1, _results;\n _ref = lines || [];\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n if ((_ref1 = this.engine.log.limit) != null ? _ref1.limited : void 0) {\n break;\n }\n node = Log.Dom.Node.create(this, start * this.SLICE + ix, line);\n _results.push(this.nodes.insert(node));\n }\n return _results;\n },\n remove: function() {\n return delete this.engine.parts[this.num];\n },\n trigger: function() {\n return this.engine.trigger.apply(this.engine, arguments);\n }\n });\n\n Log.Dom.Part.prototype.__defineGetter__('prev', function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.engine.parts[num -= 1];\n }\n return prev;\n });\n\n Log.Dom.Part.prototype.__defineGetter__('next', function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.engine.parts.length)) {\n next = this.engine.parts[num += 1];\n }\n return next;\n });\n\n Log.Dom.Nodes = function(part) {\n this.part = part;\n this.nodes = [];\n return this;\n };\n\n $.extend(Log.Dom.Nodes.prototype, {\n at: function(ix) {\n return this.nodes[ix];\n },\n insert: function(node) {\n this.nodes[node.num] = node;\n return node.insert();\n },\n remove: function(node) {\n this.nodes.splice(node.num, 1);\n if (this.nodes.length === 0) {\n return this.part.remove();\n }\n }\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('length', function() {\n return this.nodes.length;\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('first', function() {\n return this.nodes[0];\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('last', function() {\n return this.nodes[this.nodes.length - 1];\n });\n\n Log.Dom.Node = function() {};\n\n $.extend(Log.Dom.Node, {\n FOLDS_PATTERN: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(part, num, string) {\n var fold;\n if (fold = string.match(this.FOLDS_PATTERN)) {\n return new Log.Dom.Fold(part, num, fold[1], fold[2]);\n } else {\n return new Log.Dom.Paragraph(part, num, string);\n }\n },\n reinsert: function(nodes) {\n var node, _i, _j, _len, _len1;\n console.log(\"reinsert: \" + (nodes.map(function(node) {\n return node.id;\n }).join(', ')));\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n node.remove();\n }\n for (_j = 0, _len1 = nodes.length; _j < _len1; _j++) {\n node = nodes[_j];\n node.part.nodes.insert(node);\n }\n return console.log(document.firstChild.innerHTML.replace(/<\\/p>/gm, '

          \\n') + '\\n');\n }\n });\n\n Log.Dom.Node.prototype.__defineGetter__('prev', function() {\n var num, prev, _ref;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.part.nodes.at(num -= 1);\n }\n return prev || ((_ref = this.part.prev) != null ? _ref.nodes.last : void 0);\n });\n\n Log.Dom.Node.prototype.__defineGetter__('next', function() {\n var next, num, _ref;\n num = this.num;\n while (!(next || num >= this.part.nodes.length)) {\n next = this.part.nodes.at(num += 1);\n }\n return next || ((_ref = this.part.next) != null ? _ref.nodes.first : void 0);\n });\n\n Log.Dom.Fold = function(part, num, event, name) {\n this.part = part;\n this.ends = true;\n this.fold = true;\n this.num = num;\n this.id = \"fold-\" + event + \"-\" + name;\n this.data = {\n type: 'fold',\n id: this.id,\n event: event,\n name: name\n };\n return this;\n };\n\n Log.Dom.Fold.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n return fail;\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Dom.Paragraph = function(part, num, string) {\n var span, _ref;\n this.part = part;\n this.num = num;\n this.ends = !!((_ref = string[string.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.spans = new Log.Dom.Spans(this, string.replace(/\\n$/, ''));\n this.data = {\n type: 'paragraph',\n num: this.part.num,\n hidden: this.hidden,\n nodes: (function() {\n var _i, _len, _ref1, _results;\n _ref1 = this.spans.content;\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n span = _ref1[_i];\n _results.push(span.data);\n }\n return _results;\n }).call(this)\n };\n return this;\n };\n\n Log.Dom.Paragraph.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n var next, prev, span, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;\n if ((prev = this.prev) && !prev.ends && !prev.fold) {\n if (Log.DEBUG) {\n console.log(\"P.1 - move \" + this.id + \"'s spans into prev\");\n }\n _ref = this.spans.content;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n prev.spans.append(span);\n }\n return this.part.nodes.remove(this);\n } else if ((next = this.next) && !this.ends && !next.fold) {\n if (Log.DEBUG) {\n console.log(\"P.2 - move \" + this.id + \"'s spans into next\");\n }\n _ref1 = this.spans.reverse();\n _results = [];\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n span = _ref1[_j];\n _results.push(next.prepend(span));\n }\n return _results;\n } else if ((prev != null ? prev.fold : void 0) && (prev != null ? (_ref2 = prev.element.getAttribute('class')) != null ? _ref2.match(' fold') : void 0 : void 0)) {\n if (Log.DEBUG) {\n console.log(\"P.3 - append \" + this.id + \" to fold \" + prev.id);\n }\n return this.element = this.trigger('insert', this.data, {\n after: prev.element.firstChild\n });\n } else if (prev) {\n if (Log.DEBUG) {\n console.log(\"P.4 - insert \" + this.id + \" after the parentNode of the last node of prev, id \" + prev.id);\n }\n return this.element = this.trigger('insert', this.data, {\n after: prev.element\n });\n } else if (next) {\n if (Log.DEBUG) {\n console.log(\"P.5 - insert \" + this.id + \" before the parentNode of the first node of next, id \" + next.id);\n }\n return this.element = this.trigger('insert', this.data, {\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"P.6 - insert \" + this.id + \" at the beginning of #log\");\n }\n return this.element = this.trigger('insert', this.data);\n }\n },\n remove: function() {\n var element, span, _i, _len, _ref;\n element = this.element;\n _ref = this.spans;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n this.trigger('remove', span.element);\n }\n if (!(element.childNodes.length > 1)) {\n this.trigger('remove', element);\n }\n return this.part.nodes.remove(this);\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('id', function() {\n return \"\" + this.part.num + \"-\" + this.num;\n });\n\n Log.Dom.Paragraph.prototype.__defineSetter__('element', function(element) {\n var child, span, _i, _len, _ref, _results;\n child = element.firstChild;\n _ref = this.spans.content;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n _results.push(span.element = child = child.nextSibling);\n }\n return _results;\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('element', function() {\n return this.spans.first.element.parentNode;\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('tail', function() {\n var next, parent, tail, _ref;\n parent = this.element.parentNode;\n next = this;\n tail = [];\n while ((next = next.next) && !next.fold && ((_ref = next.element) != null ? _ref.parentNode : void 0) === parent) {\n tail.push(next);\n }\n return tail;\n });\n\n Log.Dom.Spans = function(parent, string) {\n this.parent = parent;\n this.content = this.parse(parent, string);\n return this;\n };\n\n $.extend(Log.Dom.Spans.prototype, {\n parse: function(parent, string) {\n var ix, span, _i, _len, _ref, _results;\n _ref = Log.Deansi.apply(string);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n span = _ref[ix];\n _results.push(new Log.Dom.Span(parent, ix, span));\n }\n return _results;\n },\n at: function(ix) {\n return this.content[ix];\n },\n indexOf: function(span) {\n return this.content.indexOf(span);\n },\n append: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.push(span);\n return span.insert();\n },\n prepend: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.unshift(span);\n return span.insert();\n },\n reverse: function() {\n return this.content.reverse();\n },\n remove: function(span) {\n return this.content.splice(this.content.indexOf(span), 1);\n }\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('last', function() {\n return this.content[this.length - 1];\n });\n\n Log.Dom.Span = function(parent, num, data) {\n this.parent = parent;\n this.num = num;\n this.id = \"\" + parent.id + \"-\" + num;\n this.data = $.extend(data, {\n id: this.id\n });\n if (data.text.match(/\\r/)) {\n this.hidden = true;\n }\n this.data.text = data.text.replace(/^.*\\r/gm, '');\n if (this.hidden) {\n this.data[\"class\"] = ['hidden'];\n }\n return this;\n };\n\n $.extend(Log.Dom.Span.prototype, {\n insert: function() {\n var next, prev;\n if (prev = this.prev) {\n if (Log.DEBUG) {\n console.log(\"S.1 - insert \" + this.id + \" after prev \" + prev.id);\n }\n return this.insertAt({\n after: prev.element\n });\n } else if (next = this.next) {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" before next \" + next.id);\n }\n return this.insertAt({\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" into parent \" + this.parent.id);\n }\n return this.insertAt({\n into: this.parent.element\n });\n }\n },\n insertAt: function(pos) {\n var span, _i, _len, _ref, _results;\n this.element = this.trigger('insert', this.data, pos);\n if (this.hidden) {\n _ref = this.head;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n _results.push(span.hide());\n }\n return _results;\n } else {\n if (this.tail.some(function(span) {\n return span.hidden;\n })) {\n return this.hide();\n }\n }\n },\n hide: function() {\n if (!this.hidden) {\n this.trigger('hide', this.id);\n }\n return this.hidden = true;\n },\n siblings: function(direction) {\n var siblings, span, _ref;\n siblings = [];\n span = this;\n while ((span = span[direction]) && ((_ref = span.element) != null ? _ref.parentNode : void 0) === this.element.parentNode) {\n siblings.unshift(span);\n }\n return siblings;\n },\n trigger: function() {\n return this.parent.trigger.apply(this.parent, arguments);\n }\n });\n\n Log.Dom.Span.prototype.__defineGetter__('head', function() {\n return this.siblings('prev');\n });\n\n Log.Dom.Span.prototype.__defineGetter__('tail', function() {\n return this.siblings('next');\n });\n\n Log.Dom.Span.prototype.__defineGetter__('prev', function() {\n var span, _ref, _ref1;\n span = this.parent.spans.at(this.parent.spans.indexOf(this) - 1);\n return span || ((_ref = this.parent.prev) != null ? (_ref1 = _ref.spans) != null ? _ref1.last : void 0 : void 0);\n });\n\n Log.Dom.Span.prototype.__defineGetter__('next', function() {\n var span, _ref, _ref1;\n span = this.parent.spans.at(this.parent.spans.indexOf(this) + 1);\n return span || ((_ref = this.parent.next) != null ? (_ref1 = _ref.spans) != null ? _ref1.first : void 0 : void 0);\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/dom");minispade.register('log.old/engine/dom2', "(function() {(function() {\n\n Log.Dom = function(log) {\n this.log = log;\n this.parts = [];\n this.nodes = new Log.Dom.Nodes(this);\n return this;\n };\n\n $.extend(Log.Dom.prototype, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return this.insert(num, string);\n }\n },\n SLICE: 500,\n insert: function(num, string) {\n var ix, lines, next, slices,\n _this = this;\n lines = string.split(/^/gm) || [];\n slices = ((function() {\n var _results;\n _results = [];\n while (lines.length > 0) {\n _results.push(lines.splice(0, this.SLICE));\n }\n return _results;\n }).call(this));\n ix = -1;\n next = function() {\n _this.insertSlice(num, slices.shift(), ix += 1);\n if (slices.length !== 0) {\n return setTimeout(next, 50);\n }\n };\n return next();\n },\n insertSlice: function(num, lines, start) {\n var ix, line, _i, _len, _ref, _ref1, _results;\n _ref = lines || [];\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n break;\n }\n _results.push(this.nodes.insert(Log.Dom.Node.create(this, [num, start * this.SLICE + ix], line)));\n }\n return _results;\n }\n });\n\n Log.Dom.Nodes = function(parent) {\n this.parent = parent;\n this.content = [];\n return this;\n };\n\n $.extend(Log.Dom.Nodes.prototype, {\n at: function(ix) {\n return this.content[ix];\n },\n insert: function(node) {\n return this.content[node.num] = node;\n },\n remove: function(node) {\n return this.content.splice(this.content.indexOf(node), 1);\n }\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('length', function() {\n return this.content.length;\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('last', function() {\n return this.content[this.content.length - 1];\n });\n\n Log.Dom.Node = function() {};\n\n $.extend(Log.Dom.Node, {\n FOLDS_PATTERN: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(parent, ids, string) {\n var fold;\n if (fold = string.match(this.FOLDS_PATTERN)) {\n return new Log.Dom.Fold(parent, ids, fold[1], fold[2]);\n } else {\n return new Log.Dom.Paragraph(parent, ids, string);\n }\n }\n });\n\n Log.Dom.Node.prototype.__defineGetter__('prev', function() {\n var num, prev, _ref;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.parent.nodes.at(num -= 1);\n }\n return prev || ((_ref = this.parent.prev) != null ? _ref.nodes.last : void 0);\n });\n\n Log.Dom.Node.prototype.__defineGetter__('next', function() {\n var next, num, _ref;\n num = this.num;\n while (!(next || num >= this.parent.nodes.length)) {\n next = this.parent.nodes.at(num += 1);\n }\n return next || ((_ref = this.parent.next) != null ? _ref.nodes.first : void 0);\n });\n\n Log.Dom.Paragraph = function(parent, ids, string) {\n var _ref;\n this.parent = parent;\n this.ids = ids;\n this.id = ids.join('-');\n this.ends = !!((_ref = string[string.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.spans = new Log.Dom.Spans(this, ids, string.replace(/\\n$/, ''));\n return this;\n };\n\n Log.Dom.Paragraph.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n var next, prev,\n _this = this;\n if ((prev = this.prev) && !prev.ends && !prev.fold) {\n if (Log.DEBUG) {\n console.log(\"P.1 - move \" + this.id + \"'s spans into prev (\" + prev.id + \")\");\n }\n this.spans.content.slice().forEach(function(span) {\n return prev.spans.insert(span);\n });\n return this.remove();\n } else if ((next = this.next) && !this.ends && !next.fold) {\n if (Log.DEBUG) {\n console.log(\"P.2 - move next's (\" + next.id + \") spans into \" + this.id);\n }\n this.next.spans.content.slice().forEach(function(span) {\n return _this.spans.insert(span);\n });\n return next.remove();\n }\n },\n remove: function() {\n return this.parent.nodes.remove(this);\n }\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('id', function() {\n return \"\" + this.parent.num + \"-\" + this.num;\n });\n\n Log.Dom.Spans = function(parent, ids, string) {\n this.parent = parent;\n this.content = this.parse(parent, ids, string);\n return this;\n };\n\n $.extend(Log.Dom.Spans.prototype, {\n parse: function(parent, ids, string) {\n var ix, span, _i, _len, _ref, _results;\n _ref = Log.Deansi.apply(string);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n span = _ref[ix];\n _results.push(new Log.Dom.Span(parent, ids.concat([ix]), span));\n }\n return _results;\n },\n at: function(ix) {\n return this.content[ix];\n },\n indexOf: function(span) {\n return this.content.indexOf(span);\n },\n insert: function(span) {\n var head, ix, prev;\n console.log('insert', span.id);\n span.parent.spans.remove(span);\n span.parent = this.parent;\n head = this.content.filter(function(s) {\n return s.id < span.id;\n });\n if (prev = head[head.length - 1]) {\n ix = this.content.indexOf(prev) + 1;\n }\n return this.content.splice(ix || 0, 0, span);\n },\n prepend: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.unshift(span);\n return span.insert();\n },\n remove: function(span) {\n return this.content.splice(this.content.indexof(span), 1);\n }\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('last', function() {\n return this.content[this.content.length - 1];\n });\n\n Log.Dom.Span = function(parent, ids, data) {\n this.parent = parent;\n this.ids = ids;\n this.id = ids.join('-');\n this.data = $.extend(data, {\n id: this.id\n });\n if (data.text.match(/\\r/)) {\n this.hidden = true;\n }\n this.data.text = data.text.replace(/^.*\\r/gm, '');\n if (this.hidden) {\n this.data[\"class\"] = ['hidden'];\n }\n return this;\n };\n\n $.extend(Log.Dom.Span.prototype, {\n insert: function() {\n var next, prev;\n if (prev = this.prev) {\n if (Log.DEBUG) {\n console.log(\"S.1 - insert \" + this.id + \" after prev \" + prev.id);\n }\n return this.insertAt({\n after: prev.element\n });\n } else if (next = this.next) {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" before next \" + next.id);\n }\n return this.insertAt({\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" into parent \" + this.parent.id);\n }\n return this.insertAt({\n into: this.parent.element\n });\n }\n },\n insertAt: function(pos) {\n return this.element = this.trigger('insert', this.data, pos);\n }\n });\n\n Log.Dom.Span.prototype.__defineGetter__('prev', function() {\n var span, _ref, _ref1;\n console.log(this.num);\n span = this.parent.spans.at(this.num - 1);\n return span || ((_ref = this.parent.prev) != null ? (_ref1 = _ref.spans) != null ? _ref1.last : void 0 : void 0);\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/dom2");minispade.register('log.old/engine/live', "(function() {(function() {\n\n Log.Live = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Live.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Live.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Live.Part = function(log, num, string) {\n var ix, line;\n this.log = log;\n this.num = num;\n this.lines = (function() {\n var _i, _len, _ref, _results;\n _ref = string.split(/^/m);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n _results.push(new Log.Live.Line(this, ix, line));\n }\n return _results;\n }).call(this);\n return this;\n };\n\n $.extend(Log.Live.Part.prototype, {\n insert: function() {\n return new Log.Live.Context(this.log, this).insert();\n },\n head: function() {\n var head, line;\n head = [];\n line = this.lines[0];\n while ((line = line != null ? line.prev() : void 0) && !line.isNewline()) {\n head.unshift(line);\n }\n return head;\n },\n tail: function() {\n var line, tail;\n tail = [];\n line = this.lines[this.lines.length - 1];\n while (line = line != null ? line.next() : void 0) {\n tail.push(line);\n if (line != null ? line.isNewline() : void 0) {\n break;\n }\n }\n return tail;\n },\n prev: function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.log.parts[num -= 1];\n }\n return prev;\n },\n next: function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.log.parts.length)) {\n next = this.log.parts[num += 1];\n }\n return next;\n }\n });\n\n Log.Live.Line = function(part, num, string) {\n this.part = part;\n this.num = num;\n this.id = \"\" + part.num + \"-\" + num;\n this.string = string;\n return this;\n };\n\n $.extend(Log.Live.Line.prototype, {\n prev: function() {\n var line, _ref;\n line = this.part.lines[this.num - 1];\n return line || ((_ref = this.part.prev()) != null ? _ref.lines.slice(-1)[0] : void 0);\n },\n next: function() {\n var line, _ref;\n line = this.part.lines[this.num + 1];\n return line || ((_ref = this.part.next()) != null ? _ref.lines[0] : void 0);\n },\n isNewline: function() {\n return this.string[this.string.length - 1] === \"\\n\";\n },\n isFold: function() {\n return this.string.indexOf('fold') !== -1;\n },\n clone: function() {\n return new Log.Live.Line(this.part, this.num, this.string);\n }\n });\n\n Log.Live.Context = function(log, part) {\n this.log = log;\n this.part = part;\n this.head = part.head();\n this.tail = part.tail();\n this.lines = this.join(this.head.concat(part.lines).concat(this.tail));\n return this;\n };\n\n $.extend(Log.Live.Context.prototype, {\n insert: function() {\n var ids;\n ids = this.head.concat(this.tail).map(function(line) {\n return line.id;\n });\n if (ids.length !== 0) {\n this.log.trigger('remove', ids);\n }\n return this.log.trigger('insert', this.after(), this.nodes());\n },\n nodes: function() {\n var _this = this;\n return this.lines.map(function(line) {\n var fold, string;\n string = line.string;\n if (fold = _this.defold(string)) {\n return $.extend(fold, {\n id: line.id\n });\n } else {\n return {\n id: line.id,\n nodes: _this.deansi(string)\n };\n }\n });\n },\n join: function(all) {\n var line, lines;\n lines = [];\n while (line = all.pop()) {\n if (lines.length === 0 || line.isNewline()) {\n lines.unshift(line.clone());\n } else {\n lines[0].string = line.string + lines[0].string;\n }\n }\n return lines;\n },\n after: function() {\n var line, _ref;\n line = (_ref = this.part.lines[0]) != null ? _ref.prev() : void 0;\n while (line && !line.isNewline() && !line.isFold()) {\n line = line.prev();\n }\n return line != null ? line.id : void 0;\n },\n defold: function(string) {\n var matches;\n if (matches = string.match(/fold:(start|end):([\\w_\\-\\.]+)/)) {\n return {\n type: 'fold',\n event: matches[1],\n name: matches[2]\n };\n }\n },\n deansi: function(string) {\n return Log.Deansi.apply(string);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/live");minispade.register('log.old/folds', "(function() {(function() {\n\n Log.Folds = function() {\n this.folds = {};\n return this;\n };\n\n Log.Folds.prototype = $.extend(new Log.Listener, {\n insert: function(log, data, pos) {\n var fold, _base, _name;\n if (data.type === 'fold') {\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data);\n }\n return true;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n $.extend(Log.Folds.Fold.prototype, {\n receive: function(data) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate();\n }\n },\n activate: function() {\n var node, _i, _len, _ref;\n console.log(\"F - activate \" + this.start);\n console.log(document.firstChild.innerHTML.replace(/

          rcv \" + num + \" \" + (JSON.stringify(string)) + \"\");\n },\n insert: function(log, after, datas) {\n return this.log(\"ins \" + (datas.map(function(data) {\n return data.id;\n }).join(', ')) + \", after: \" + (after || '?') + \", \" + (JSON.stringify(datas)));\n },\n remove: function(log, id) {\n return this.log(\"rem \" + id);\n },\n log: function(line) {\n return $('#events').append(\"\" + line + \"\\n\");\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/instrument");minispade.register('log.old/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = $.extend(new Log.Listener, {\n count: 0,\n insert: function(log, line, pos) {\n if (line.type === 'paragraph' && !line.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Log.Limit.prototype.__defineGetter__('limited', function() {\n return this.count >= this.max_lines;\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/limit");minispade.register('log.old/renderer/inner_html', "(function() {(function() {\n\n Log.InnerHtmlRenderer = function() {\n this.frag = document.createDocumentFragment();\n this.div = document.createElement('div');\n return this;\n };\n\n Log.InnerHtmlRenderer.prototype = $.extend(new Log.Listener, {\n remove: function(log, ids) {\n var id, node, _i, _len, _ref, _results;\n _results = [];\n for (_i = 0, _len = ids.length; _i < _len; _i++) {\n id = ids[_i];\n node = document.getElementById(id);\n if (node && !((_ref = node.getAttribute('class')) != null ? _ref.match(/fold/) : void 0)) {\n _results.push(node.parentNode.removeChild(node));\n } else {\n _results.push(void 0);\n }\n }\n return _results;\n },\n insert: function(log, after, nodes) {\n var html;\n log = document.getElementById('log');\n html = this.render(nodes);\n if (log.childNodes.length === 0) {\n return log.innerHTML = html;\n } else if (after) {\n after = document.getElementById(after);\n return this.insertAfter(this.fragmentFrom(html), after);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(this.fragmentFrom(html), log.firstChild);\n }\n },\n render: function(nodes) {\n var node;\n return ((function() {\n var _i, _len, _results;\n _results = [];\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n _results.push(this.renderNode(node));\n }\n return _results;\n }).call(this)).join('');\n },\n renderNode: function(node) {\n var type;\n node.type || (node.type = 'paragraph');\n type = node.type[0].toUpperCase() + node.type.slice(1);\n return this[\"render\" + type](node) || '';\n },\n renderParagraph: function(node) {\n var html, style;\n if (node.hidden) {\n style = ' style=\"display:none\"';\n }\n html = \"

          \";\n html += ((function() {\n var _i, _len, _ref, _results;\n _ref = node.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n _results.push(this.renderNode(node));\n }\n return _results;\n }).call(this)).join('');\n return html + '

          ';\n },\n renderFold: function(node) {\n if (!document.getElementById(node.id)) {\n return \"
          \";\n }\n },\n renderSpan: function(node) {\n return \"\" + (this.clean(node.text)) + \"\";\n },\n renderText: function(node) {\n return this.clean(node.text);\n },\n clean: function(text) {\n return text.replace(/\\n/gm, '');\n },\n fragmentFrom: function(html) {\n var div, frag, node;\n frag = this.frag.cloneNode();\n div = this.div.cloneNode();\n div.innerHTML = html;\n while (node = div.firstChild) {\n frag.appendChild(node);\n }\n return frag;\n },\n insertAfter: function(node, after) {\n if (after.nextSibling) {\n return after.parentNode.insertBefore(node, after.nextSibling);\n } else {\n return after.parentNode.appendChild(node);\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/renderer/inner_html");minispade.register('log.old/renderer/jquery', "(function() {(function() {\n\n Log.JqueryRenderer = function() {};\n\n Log.JqueryRenderer.prototype = $.extend(new Log.Listener, {\n remove: function(log, ids) {\n var id, _i, _len, _results;\n _results = [];\n for (_i = 0, _len = ids.length; _i < _len; _i++) {\n id = ids[_i];\n _results.push($(\"#log #\" + id).remove());\n }\n return _results;\n },\n insert: function(log, after, datas) {\n var html,\n _this = this;\n html = datas.map(function(data) {\n return _this.render(data);\n });\n return after && $(\"#log #\" + after).after(html) || $('#log').prepend(html);\n },\n render: function(data) {\n var node, nodes, text;\n nodes = (function() {\n var _i, _len, _ref, _results;\n _ref = data.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n text = node.text.replace(/\\n/gm, '');\n if (node.type === 'span') {\n text = \"\" + text + \"\";\n }\n _results.push(\"

          \" + text + \"

          \");\n }\n return _results;\n }).call(this);\n return nodes.join(\"\\n\");\n },\n style: function(data) {\n return data.hidden && 'display: none;' || '';\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/renderer/jquery");minispade.register('log/deansi', "(function() {(function() {\n\n Log.Deansi = {\n CLEAR_ANSI: /(\\e|\\033)\\[K|(\\e|\\033)\\[K|(\\e|\\033)\\[\\d+G|(\\e|\\033)\\(B|(\\e|\\033)M|(\\e|\\033)\\[\\?25(l|h)/gm,\n apply: function(string) {\n var nodes,\n _this = this;\n if (!string) {\n return [];\n }\n string = string.replace(this.CLEAR_ANSI, '');\n nodes = ansiparse(string).map(function(part) {\n return _this.node(part);\n });\n if (nodes.length === 0) {\n nodes.push(this.node({\n text: ''\n }));\n }\n return nodes;\n },\n node: function(part) {\n var classes, node;\n node = {\n type: 'span',\n text: part.text\n };\n if (classes = this.classes(part)) {\n node[\"class\"] = classes;\n }\n return node;\n },\n classes: function(part) {\n var result;\n result = [];\n result = result.concat(this.colors(part));\n if (result.length > 0) {\n return result;\n }\n },\n colors: function(part) {\n var colors;\n colors = [];\n if (part.foreground) {\n colors.push(part.foreground);\n }\n if (part.background) {\n colors.push(\"bg-\" + part.background);\n }\n if (part.bold) {\n colors.push('bold');\n }\n if (part.italic) {\n colors.push('italic');\n }\n return colors;\n },\n hidden: function(part) {\n if (part.text.match(/\\r/)) {\n part.text = part.text.replace(/^.*\\r/gm, '');\n return true;\n }\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=log/deansi");minispade.register('log/folds', "(function() {(function() {\n\n Log.Folds = function() {\n this.folds = {};\n return this;\n };\n\n Log.extend(Log.Folds.prototype, {\n add: function(data) {\n var fold, _base, _name;\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data);\n return fold.active;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n Log.extend(Log.Folds.Fold.prototype, {\n receive: function(data) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate();\n }\n },\n activate: function() {\n var node, _i, _len, _ref;\n if (Log.DEBUG) {\n console.log(\"F - activate \" + this.start);\n }\n _ref = this.nodes;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n this.fold.appendChild(node);\n }\n this.fold.setAttribute('class', this.classes());\n return this.active = true;\n },\n classes: function() {\n var classes;\n classes = this.fold.getAttribute('class').split(' ');\n classes.push('fold');\n if (this.fold.childNodes.length > 2) {\n classes.push('active');\n }\n return classes.join(' ');\n }\n });\n\n Log.Folds.Fold.prototype.__defineGetter__('fold', function() {\n return this._fold || (this._fold = document.getElementById(this.start));\n });\n\n Log.Folds.Fold.prototype.__defineGetter__('nodes', function() {\n var node, nodes;\n node = this.fold;\n nodes = [];\n while ((node = node.nextSibling) && node.id !== this.end) {\n nodes.push(node);\n }\n return nodes;\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/folds");minispade.register('log/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = Log.extend(new Log.Listener, {\n count: 0,\n insert: function(log, node, pos) {\n if (node.type === 'paragraph' && !node.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Log.Limit.prototype.__defineGetter__('limited', function() {\n return this.count >= this.max_lines;\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/limit");minispade.register('log/nodes', "(function() {(function() {\n\n Log.Node = function(id, num) {\n this.id = id;\n this.num = num;\n this.key = Log.Node.key(this.id);\n this.children = new Log.Nodes(this);\n return this;\n };\n\n Log.extend(Log.Node, {\n key: function(id) {\n if (id) {\n return id.split('-').map(function(i) {\n return '000000'.concat(i).slice(-6);\n }).join('');\n }\n }\n });\n\n Log.extend(Log.Node.prototype, {\n addChild: function(node) {\n return this.children.add(node);\n },\n remove: function() {\n this.log.remove(this.element);\n return this.parent.children.remove(this);\n }\n });\n\n Log.Node.prototype.__defineGetter__('log', function() {\n var _ref;\n return this._log || (this._log = ((_ref = this.parent) != null ? _ref.log : void 0) || this.parent);\n });\n\n Log.Node.prototype.__defineGetter__('firstChild', function() {\n return this.children.first;\n });\n\n Log.Node.prototype.__defineGetter__('lastChild', function() {\n return this.children.last;\n });\n\n Log.Nodes = function(parent) {\n if (parent) {\n this.parent = parent;\n }\n this.items = [];\n this.index = {};\n return this;\n };\n\n Log.extend(Log.Nodes.prototype, {\n add: function(item) {\n var ix, next, prev, _ref, _ref1;\n ix = this.position(item) || 0;\n this.items.splice(ix, 0, item);\n if (this.parent) {\n item.parent = this.parent;\n }\n prev = function(item) {\n while (item && !item.children.last) {\n item = item.prev;\n }\n return item != null ? item.children.last : void 0;\n };\n next = function(item) {\n while (item && !item.children.first) {\n item = item.next;\n }\n return item != null ? item.children.first : void 0;\n };\n if (item.prev = this.items[ix - 1] || prev((_ref = this.parent) != null ? _ref.prev : void 0)) {\n item.prev.next = item;\n }\n if (item.next = this.items[ix + 1] || next((_ref1 = this.parent) != null ? _ref1.next : void 0)) {\n item.next.prev = item;\n }\n return item;\n },\n remove: function(item) {\n this.items.splice(this.items.indexOf(item), 1);\n if (item.next) {\n item.next.prev = item.prev;\n }\n if (item.prev) {\n item.prev.next = item.next;\n }\n if (this.items.length === 0) {\n return this.parent.remove();\n }\n },\n position: function(item) {\n var ix, _i, _ref;\n for (ix = _i = _ref = this.items.length - 1; _i >= 0; ix = _i += -1) {\n if (this.items[ix].key < item.key) {\n return ix + 1;\n }\n }\n },\n indexOf: function() {\n return this.items.indexOf.apply(this.items, arguments);\n },\n slice: function() {\n return this.items.slice.apply(this.items, arguments);\n },\n each: function(func) {\n return this.items.slice().forEach(func);\n },\n map: function(func) {\n return this.items.map(func);\n }\n });\n\n Log.Nodes.prototype.__defineGetter__('first', function() {\n return this.items[0];\n });\n\n Log.Nodes.prototype.__defineGetter__('last', function() {\n return this.items[this.length - 1];\n });\n\n Log.Nodes.prototype.__defineGetter__('length', function() {\n return this.items.length;\n });\n\n Log.Part = function(id, num, string) {\n Log.Node.apply(this, arguments);\n this.string = string || '';\n this.string = this.string.replace(/\\033\\[1000D/gm, '\\r');\n this.string = this.string.replace(/\\r+\\n/gm, '\\n');\n this.strings = this.string.split(/^/gm) || [];\n this.slices = ((function() {\n var _results;\n _results = [];\n while (this.strings.length > 0) {\n _results.push(this.strings.splice(0, Log.SLICE));\n }\n return _results;\n }).call(this));\n return this;\n };\n\n Log.extend(Log.Part, {\n create: function(log, num, string) {\n var part;\n part = new Log.Part(num.toString(), num, string);\n log.addChild(part);\n return part.process(0, -1);\n }\n });\n\n Log.Part.prototype = Log.extend(new Log.Node, {\n remove: function() {},\n process: function(slice, num) {\n var node, span, spans, string, _i, _j, _len, _len1, _ref, _ref1, _ref2,\n _this = this;\n _ref = this.slices[slice] || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n string = _ref[_i];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n return;\n }\n spans = [];\n _ref2 = Log.Deansi.apply(string);\n for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {\n node = _ref2[_j];\n span = Log.Span.create(this, \"\" + this.id + \"-\" + (num += 1), num, node.text, node[\"class\"]);\n span.render();\n spans.push(span);\n }\n if (spans[0].line.cr) {\n spans[0].line.clear();\n }\n }\n if (!(slice >= this.slices.length - 1)) {\n return setTimeout((function() {\n return _this.process(slice + 1, num);\n }), Log.TIMEOUT);\n }\n }\n });\n\n Log.Span = function(id, num, text, classes) {\n var fold, _ref;\n Log.Node.apply(this, arguments);\n if (fold = text.match(Log.FOLD)) {\n this.fold = true;\n this.event = fold[1];\n this.text = this.name = fold[2];\n } else {\n this.text = text.replace(/.*\\r/gm, '').replace(/\\n$/, '');\n this.nl = !!((_ref = text[text.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.cr = !!text.match(/\\r/);\n this[\"class\"] = this.cr && ['clears'] || classes;\n }\n return this;\n };\n\n Log.extend(Log.Span, {\n create: function(parent, id, num, text, classes) {\n var span;\n span = new Log.Span(id, num, text, classes);\n parent.addChild(span);\n return span;\n },\n render: function(parent, id, num, text, classes) {\n var span;\n span = this.create(parent, id, num, text, classes);\n return span.render();\n }\n });\n\n Log.Span.prototype = Log.extend(new Log.Node, {\n render: function() {\n var tail;\n if (!this.fold && this.prev && !this.prev.fold && !this.prev.nl) {\n if (Log.DEBUG) {\n console.log(\"S.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n this.log.insert(this.data, {\n after: this.prev.element\n });\n this.line = this.prev.line;\n } else if (!this.fold && this.next && !this.next.fold) {\n if (Log.DEBUG) {\n console.log(\"S.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n this.log.insert(this.data, {\n before: this.next.element\n });\n this.line = this.next.line;\n } else {\n this.line = Log.Line.create(this.log, [this]);\n this.line.render();\n }\n if (this.nl && (tail = this.tail).length > 0) {\n return this.split(tail);\n }\n },\n remove: function() {\n Log.Node.prototype.remove.apply(this);\n if (this.line) {\n return this.line.remove(this);\n }\n },\n split: function(spans) {\n var line, span, _i, _len;\n if (Log.DEBUG) {\n console.log(\"S.3 split [\" + (spans.map(function(span) {\n return span.id;\n }).join(', ')) + \"]\");\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n this.log.remove(span.element);\n }\n line = Log.Line.create(this.log, spans);\n line.render();\n if (line.cr) {\n return line.clear();\n }\n },\n clear: function() {\n if (this.prev && this.isSibling(this.prev) && this.isSequence(this.prev)) {\n this.prev.clear();\n return this.prev.remove();\n }\n },\n isSequence: function(other) {\n return this.parent.num - other.parent.num === this.log.children.indexOf(this.parent) - this.log.children.indexOf(other.parent);\n },\n isSibling: function(other) {\n var _ref, _ref1;\n return ((_ref = this.element) != null ? _ref.parentNode : void 0) === ((_ref1 = other.element) != null ? _ref1.parentNode : void 0);\n },\n siblings: function(type) {\n var siblings, span;\n siblings = [];\n while ((span = (span || this)[type]) && this.isSibling(span)) {\n siblings.push(span);\n }\n return siblings;\n }\n });\n\n Log.Span.prototype.__defineSetter__('line', function(line) {\n if (this.line) {\n this.line.remove(this);\n }\n this._line = line;\n return this.line.add(this);\n });\n\n Log.Span.prototype.__defineGetter__('data', function() {\n return {\n id: this.id,\n type: 'span',\n text: this.text,\n \"class\": this[\"class\"]\n };\n });\n\n Log.Span.prototype.__defineGetter__('line', function() {\n return this._line;\n });\n\n Log.Span.prototype.__defineGetter__('element', function() {\n return document.getElementById(this.id);\n });\n\n Log.Span.prototype.__defineGetter__('head', function() {\n return this.siblings('prev').reverse();\n });\n\n Log.Span.prototype.__defineGetter__('tail', function() {\n return this.siblings('next');\n });\n\n Log.Line = function(log) {\n this.log = log;\n this.spans = [];\n return this;\n };\n\n Log.extend(Log.Line, {\n create: function(log, spans) {\n var line, span, _i, _len;\n if ((span = spans[0]) && span.fold) {\n line = new Log.Fold(log, span.event, span.name);\n } else {\n line = new Log.Line(log);\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n span.line = line;\n }\n return line;\n }\n });\n\n Log.extend(Log.Line.prototype, {\n add: function(span) {\n var ix;\n if (span.cr) {\n this.cr = true;\n }\n if (this.spans.indexOf(span) > -1) {\n\n } else if ((ix = this.spans.indexOf(span.prev)) > -1) {\n return this.spans.splice(ix + 1, 0, span);\n } else if ((ix = this.spans.indexOf(span.next)) > -1) {\n return this.spans.splice(ix, 0, span);\n } else {\n return this.spans.push(span);\n }\n },\n remove: function(span) {\n var ix;\n if ((ix = this.spans.indexOf(span)) > -1) {\n return this.spans.splice(ix, 1);\n }\n },\n render: function() {\n var fold;\n if ((fold = this.prev) && fold.event === 'start' && fold.active) {\n if (Log.DEBUG) {\n console.log(\"L.0 insert \" + this.id + \" into fold \" + fold.id);\n }\n fold = this.log.folds.folds[fold.name].fold;\n return this.element = this.log.insert(this.data, {\n into: fold\n });\n } else if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"L.1 insert \" + this.spans[0].id + \" after prev \" + this.prev.id);\n }\n return this.element = this.log.insert(this.data, {\n after: this.prev.element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"L.2 insert \" + this.spans[0].id + \" before next \" + this.next.id);\n }\n return this.element = this.log.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"L.3 insert \" + this.spans[0].id + \" into #log\");\n }\n return this.element = this.log.insert(this.data);\n }\n },\n clear: function() {\n var cr, _i, _len, _ref, _results;\n _ref = this.crs;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n cr = _ref[_i];\n _results.push(cr.clear());\n }\n return _results;\n }\n });\n\n Log.Line.prototype.__defineGetter__('id', function() {\n var _ref;\n return (_ref = this.spans[0]) != null ? _ref.id : void 0;\n });\n\n Log.Line.prototype.__defineGetter__('data', function() {\n return {\n type: 'paragraph',\n nodes: this.nodes\n };\n });\n\n Log.Line.prototype.__defineGetter__('nodes', function() {\n return this.spans.map(function(span) {\n return span.data;\n });\n });\n\n Log.Line.prototype.__defineGetter__('prev', function() {\n var _ref;\n return (_ref = this.spans[0].prev) != null ? _ref.line : void 0;\n });\n\n Log.Line.prototype.__defineGetter__('next', function() {\n var _ref;\n return (_ref = this.spans[this.spans.length - 1].next) != null ? _ref.line : void 0;\n });\n\n Log.Line.prototype.__defineGetter__('crs', function() {\n return this.spans.filter(function(span) {\n return span.cr;\n });\n });\n\n Log.Fold = function(log, event, name) {\n Log.Line.apply(this, arguments);\n this.fold = true;\n this.event = event;\n this.name = name;\n return this;\n };\n\n Log.Fold.prototype = Log.extend(new Log.Line, {\n render: function() {\n var element, _ref;\n if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"F.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n element = this.prev.element || this.prev.element.parentNode;\n this.element = this.log.insert(this.data, {\n after: element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"F.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n element = this.next.element || this.next.element.parentNode;\n this.element = this.log.insert(this.data, {\n before: element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"F.3 insert \" + this.id);\n }\n this.element = this.log.insert(this.data);\n }\n if (this.span.next && ((_ref = this.span.prev) != null ? _ref.isSibling(this.span.next) : void 0)) {\n this.span.prev.split([this.span.next].concat(this.span.next.tail));\n }\n return this.active = this.log.folds.add(this.data);\n }\n });\n\n Log.Fold.prototype.__defineGetter__('id', function() {\n return \"fold-\" + this.event + \"-\" + this.name;\n });\n\n Log.Fold.prototype.__defineGetter__('span', function() {\n return this.spans[0];\n });\n\n Log.Fold.prototype.__defineGetter__('data', function() {\n return {\n type: 'fold',\n id: this.id,\n event: this.event,\n name: this.name\n };\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/nodes");minispade.register('log/renderer', "(function() {(function() {\n\n Log.Renderer = function() {\n this.frag = document.createDocumentFragment();\n this.para = this.createParagraph();\n this.span = this.createSpan();\n this.text = document.createTextNode('');\n this.fold = this.createFold();\n return this;\n };\n\n Log.extend(Log.Renderer.prototype, {\n insert: function(data, pos) {\n var after, before, into, node;\n node = this.render(data);\n if (into = pos != null ? pos.into : void 0) {\n if (typeof into === 'String') {\n into = document.getElementById(pos != null ? pos.into : void 0);\n }\n this.appendTo(node, into);\n } else if (after = pos != null ? pos.after : void 0) {\n if (typeof after === 'String') {\n after = document.getElementById(pos);\n }\n this.insertAfter(node, after);\n } else if (before = pos != null ? pos.before : void 0) {\n if (typeof before === 'String') {\n before = document.getElementById(pos != null ? pos.before : void 0);\n }\n this.insertBefore(node, before);\n } else {\n this.insertBefore(node);\n }\n return node;\n },\n hide: function(node) {\n node.setAttribute('class', this.addClass(node.getAttribute('class'), 'hidden'));\n return node;\n },\n remove: function(node) {\n if (node) {\n node.parentNode.removeChild(node);\n }\n return node;\n },\n render: function(data) {\n var frag, node, type, _i, _len;\n if (data instanceof Array) {\n frag = this.frag.cloneNode(true);\n for (_i = 0, _len = data.length; _i < _len; _i++) {\n node = data[_i];\n node = this.render(node);\n if (node) {\n frag.appendChild(node);\n }\n }\n return frag;\n } else {\n data.type || (data.type = 'paragraph');\n type = data.type[0].toUpperCase() + data.type.slice(1);\n return this[\"render\" + type](data);\n }\n },\n renderParagraph: function(data) {\n var node, para, type, _i, _len, _ref;\n para = this.para.cloneNode(true);\n if (data.id) {\n para.setAttribute('id', data.id);\n }\n if (data.hidden) {\n para.setAttribute('style', 'display: none;');\n }\n _ref = data.nodes || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n type = node.type[0].toUpperCase() + node.type.slice(1);\n node = this[\"render\" + type](node);\n para.appendChild(node);\n }\n return para;\n },\n renderFold: function(data) {\n var fold;\n fold = this.fold.cloneNode(true);\n fold.setAttribute('id', data.id || (\"fold-\" + data.event + \"-\" + data.name));\n fold.setAttribute('class', \"fold-\" + data.event);\n if (data.event === 'start') {\n fold.lastChild.lastChild.nodeValue = data.name;\n } else {\n fold.removeChild(fold.lastChild);\n }\n return fold;\n },\n renderSpan: function(data) {\n var span;\n span = this.span.cloneNode(true);\n if (data.id) {\n span.setAttribute('id', data.id);\n }\n if (data[\"class\"]) {\n span.setAttribute('class', data[\"class\"]);\n }\n span.lastChild.nodeValue = data.text;\n return span;\n },\n renderText: function(data) {\n var text;\n text = this.text.cloneNode(true);\n text.nodeValue = data.text;\n return text;\n },\n createParagraph: function() {\n var para;\n para = document.createElement('p');\n para.appendChild(document.createElement('a'));\n return para;\n },\n createFold: function() {\n var fold;\n fold = document.createElement('div');\n fold.appendChild(this.createSpan());\n fold.lastChild.setAttribute('class', 'fold-name');\n return fold;\n },\n createSpan: function() {\n var span;\n span = document.createElement('span');\n span.appendChild(document.createTextNode(''));\n return span;\n },\n insertBefore: function(node, other) {\n var log;\n if (other) {\n return other.parentNode.insertBefore(node, other);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(node, log.firstChild);\n }\n },\n insertAfter: function(node, other) {\n if (other.nextSibling) {\n return this.insertBefore(node, other.nextSibling);\n } else {\n return this.appendTo(node, other.parentNode);\n }\n },\n appendTo: function(node, other) {\n return other.appendChild(node);\n },\n addClass: function(classes, string) {\n if (classes != null ? classes.indexOf(string) : void 0) {\n return;\n }\n if (classes) {\n return \"\" + classes + \" \" + string;\n } else {\n return string;\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/renderer"); \ No newline at end of file +minispade.register('log', "(function() {(function() {\n\n this.Log = function() {\n this.listeners = [];\n this.renderer = new Log.Renderer;\n this.children = new Log.Nodes(this);\n this.parts = {};\n this.folds = new Log.Folds;\n return this;\n };\n\n Log.extend = function(one, other) {\n var name;\n for (name in other) {\n one[name] = other[name];\n }\n return one;\n };\n\n Log.extend(Log, {\n DEBUG: true,\n SLICE: 500,\n TIMEOUT: 25,\n FOLD: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(options) {\n var listener, log, _i, _len, _ref;\n options || (options = {});\n log = new Log();\n if (options.limit) {\n log.listeners.push(log.limit = new Log.Limit(options.limit));\n }\n _ref = options.listeners || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n listener = _ref[_i];\n log.listeners.push(listener);\n }\n return log;\n }\n });\nminispade.require('log/nodes');\n\n Log.prototype = Log.extend(new Log.Node, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return Log.Part.create(this, num, string);\n }\n },\n insert: function(data, pos) {\n this.trigger('insert', data, pos);\n return this.renderer.insert(data, pos);\n },\n remove: function(node) {\n this.trigger('remove', node);\n return this.renderer.remove(node);\n },\n hide: function(node) {\n this.trigger('hide', node);\n return this.renderer.hide(node);\n },\n trigger: function() {\n var args, ix, listener, _i, _len, _ref, _results;\n args = [this].concat(Array.prototype.slice.apply(arguments));\n _ref = this.listeners;\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n listener = _ref[ix];\n _results.push(listener.notify.apply(listener, args));\n }\n return _results;\n }\n });\n\n Log.Listener = function() {};\n\n Log.extend(Log.Listener.prototype, {\n notify: function(log, event) {\n if (this[event]) {\n return this[event].apply(this, [log].concat(Array.prototype.slice.call(arguments, 2)));\n }\n }\n });\nminispade.require('log/folds');\nminispade.require('log/deansi');\nminispade.require('log/limit');\nminispade.require('log/renderer');\n\n}).call(this);\n\n})();\n//@ sourceURL=log");minispade.register('log.old/buffer', "(function() {(function() {\n\n Log.Buffer = function(log, options) {\n this.start = 0;\n this.log = log;\n this.parts = [];\n this.options = $.extend({\n interval: 100,\n timeout: 500\n }, options || {});\n this.schedule();\n return this;\n };\n\n $.extend(Log.Buffer.prototype, {\n set: function(num, string) {\n return this.parts[num] = {\n string: string,\n time: (new Date).getTime()\n };\n },\n flush: function() {\n var num, part, _i, _len, _ref;\n _ref = this.parts;\n for (num = _i = 0, _len = _ref.length; _i < _len; num = ++_i) {\n part = _ref[num];\n if (!this.parts.hasOwnProperty(num)) {\n continue;\n }\n if (!part) {\n break;\n }\n delete this.parts[num];\n this.log.set(num, part.string);\n }\n return this.schedule();\n },\n schedule: function() {\n var _this = this;\n return setTimeout((function() {\n return _this.flush();\n }), this.options.interval);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/buffer");minispade.register('log.old/engine/chunks', "(function() {(function() {\n\n Log.Chunks = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Chunks.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Chunks.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Chunks.Part = function(engine, num, string) {\n var chunk, ix, line, type;\n this.engine = engine;\n this.num = num;\n this.chunks = (function() {\n var _i, _len, _ref, _results;\n _ref = string.split(/^/m);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n chunk = _ref[ix];\n line = chunk[chunk.length - 1].match(/\\r|\\n/);\n type = line ? 'Line' : 'Chunk';\n _results.push(new Log.Chunks[type](this, ix, chunk));\n }\n return _results;\n }).call(this);\n return this;\n };\n\n $.extend(Log.Chunks.Part.prototype, {\n insert: function() {\n var chunk, _i, _len, _ref, _results;\n _ref = this.chunks;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n chunk = _ref[_i];\n _results.push(chunk.insert());\n }\n return _results;\n },\n prev: function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.engine.parts[num -= 1];\n }\n return prev;\n },\n next: function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.engine.parts.length)) {\n next = this.engine.parts[num += 1];\n }\n return next;\n },\n trigger: function() {\n return this.engine.trigger.apply(this.engine, arguments);\n }\n });\n\n Log.Chunks.Chunk = function(part, num, string) {\n this.part = part;\n this.num = num;\n this.string = string;\n this.id = \"\" + (part != null ? part.num : void 0) + \"-\" + num;\n this.isFold = (string != null ? string.indexOf('fold') : void 0) !== -1;\n if (string) {\n this.nodes = this.parse();\n }\n return this;\n };\n\n $.extend(Log.Chunks.Chunk.prototype, {\n parse: function() {\n return [\n {\n type: 'span',\n id: \"\" + this.id + \"-0\",\n text: this.string\n }\n ];\n },\n insert: function() {\n var next, prev;\n if ((next = this.next()) && next.isLine) {\n return this.trigger('insert', this.nodes, {\n before: next.nodes[0].nodes[0].id\n });\n } else if (next) {\n return this.trigger('insert', this.nodes, {\n before: next.nodes[0].id\n });\n } else if ((prev = this.prev()) && !prev.isLine) {\n return this.trigger('insert', this.nodes, {\n after: prev.nodes[prev.nodes.length - 1].id\n });\n } else {\n return this.trigger('insert', [\n {\n type: 'paragraph',\n id: this.id,\n nodes: this.nodes\n }\n ], {\n before: void 0\n });\n }\n },\n remove: function() {\n var node, _i, _len, _ref, _results;\n _ref = this.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n this.trigger('remove', this.id);\n if (node.nodes) {\n _results.push((function() {\n var _j, _len1, _ref1, _results1;\n _ref1 = node.nodes;\n _results1 = [];\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n node = _ref1[_j];\n _results1.push(this.trigger('remove', node.id));\n }\n return _results1;\n }).call(this));\n } else {\n _results.push(void 0);\n }\n }\n return _results;\n },\n reinsert: function() {\n this.remove();\n return this.insert();\n },\n prevLine: function() {\n var prev;\n prev = this.prev();\n while (prev && !prev.isLine) {\n prev = prev.prev();\n }\n return prev;\n },\n nextLine: function() {\n var next;\n next = this.next();\n while (next && !next.isLine) {\n next = next.next();\n }\n return next;\n },\n prev: function() {\n var chunk, _ref;\n chunk = this.part.chunks[this.num - 1];\n return chunk || ((_ref = this.part.prev()) != null ? _ref.chunks.slice(-1)[0] : void 0);\n },\n next: function() {\n var chunk, _ref;\n chunk = this.part.chunks[this.num + 1];\n return chunk || ((_ref = this.part.next()) != null ? _ref.chunks[0] : void 0);\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Chunks.Line = function(part, num, string) {\n Log.Chunks.Chunk.call(this, part, num, string.slice(0, string.length - 1));\n this.isLine = true;\n return this;\n };\n\n Log.Chunks.Line.prototype = $.extend(new Log.Chunks.Chunk, {\n parse: function() {\n return [\n {\n type: 'paragraph',\n id: this.id,\n nodes: [\n {\n type: 'span',\n id: \"\" + this.id + \"-0\",\n text: this.string\n }\n ]\n }\n ];\n },\n insert: function() {\n var next, prev;\n if ((prev = this.prev()) && !prev.isLine) {\n this.trigger('insert', this.nodes[0].nodes, {\n after: prev.nodes[0].id\n });\n document.getElementById(this.nodes[0].nodes[0].id).parentNode.setAttribute('id', this.id);\n if (this.isLine && (next = this.next())) {\n return next.reinsert();\n }\n } else if (prev) {\n return this.trigger('insert', this.nodes, {\n after: prev.id\n });\n } else if (next = this.nextLine()) {\n return this.trigger('insert', this.nodes, {\n before: next.id\n });\n } else {\n return this.trigger('insert', this.nodes, {\n before: void 0\n });\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/chunks");minispade.register('log.old/engine/dom', "(function() {(function() {\n\n Log.Dom = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Dom.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Dom.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Dom.Part = function(engine, num, string) {\n this.engine = engine;\n this.num = num;\n this.string = string.replace(/\\r\\n/gm, '\\n');\n this.nodes = new Log.Dom.Nodes(this);\n return this;\n };\n\n $.extend(Log.Dom.Part.prototype, {\n SLICE: 500,\n insert: function() {\n var ix, lines, next, slices,\n _this = this;\n lines = this.string.split(/^/gm) || [];\n slices = ((function() {\n var _results;\n _results = [];\n while (lines.length > 0) {\n _results.push(lines.splice(0, this.SLICE));\n }\n return _results;\n }).call(this));\n ix = -1;\n next = function() {\n _this.insertSlice(slices.shift(), ix += 1);\n if (slices.length !== 0) {\n return setTimeout(next, 50);\n }\n };\n return next();\n },\n insertSlice: function(lines, start) {\n var ix, line, node, _i, _len, _ref, _ref1, _results;\n _ref = lines || [];\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n if ((_ref1 = this.engine.log.limit) != null ? _ref1.limited : void 0) {\n break;\n }\n node = Log.Dom.Node.create(this, start * this.SLICE + ix, line);\n _results.push(this.nodes.insert(node));\n }\n return _results;\n },\n remove: function() {\n return delete this.engine.parts[this.num];\n },\n trigger: function() {\n return this.engine.trigger.apply(this.engine, arguments);\n }\n });\n\n Log.Dom.Part.prototype.__defineGetter__('prev', function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.engine.parts[num -= 1];\n }\n return prev;\n });\n\n Log.Dom.Part.prototype.__defineGetter__('next', function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.engine.parts.length)) {\n next = this.engine.parts[num += 1];\n }\n return next;\n });\n\n Log.Dom.Nodes = function(part) {\n this.part = part;\n this.nodes = [];\n return this;\n };\n\n $.extend(Log.Dom.Nodes.prototype, {\n at: function(ix) {\n return this.nodes[ix];\n },\n insert: function(node) {\n this.nodes[node.num] = node;\n return node.insert();\n },\n remove: function(node) {\n this.nodes.splice(node.num, 1);\n if (this.nodes.length === 0) {\n return this.part.remove();\n }\n }\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('length', function() {\n return this.nodes.length;\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('first', function() {\n return this.nodes[0];\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('last', function() {\n return this.nodes[this.nodes.length - 1];\n });\n\n Log.Dom.Node = function() {};\n\n $.extend(Log.Dom.Node, {\n FOLDS_PATTERN: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(part, num, string) {\n var fold;\n if (fold = string.match(this.FOLDS_PATTERN)) {\n return new Log.Dom.Fold(part, num, fold[1], fold[2]);\n } else {\n return new Log.Dom.Paragraph(part, num, string);\n }\n },\n reinsert: function(nodes) {\n var node, _i, _j, _len, _len1;\n console.log(\"reinsert: \" + (nodes.map(function(node) {\n return node.id;\n }).join(', ')));\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n node.remove();\n }\n for (_j = 0, _len1 = nodes.length; _j < _len1; _j++) {\n node = nodes[_j];\n node.part.nodes.insert(node);\n }\n return console.log(document.firstChild.innerHTML.replace(/<\\/p>/gm, '

          \\n') + '\\n');\n }\n });\n\n Log.Dom.Node.prototype.__defineGetter__('prev', function() {\n var num, prev, _ref;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.part.nodes.at(num -= 1);\n }\n return prev || ((_ref = this.part.prev) != null ? _ref.nodes.last : void 0);\n });\n\n Log.Dom.Node.prototype.__defineGetter__('next', function() {\n var next, num, _ref;\n num = this.num;\n while (!(next || num >= this.part.nodes.length)) {\n next = this.part.nodes.at(num += 1);\n }\n return next || ((_ref = this.part.next) != null ? _ref.nodes.first : void 0);\n });\n\n Log.Dom.Fold = function(part, num, event, name) {\n this.part = part;\n this.ends = true;\n this.fold = true;\n this.num = num;\n this.id = \"fold-\" + event + \"-\" + name;\n this.data = {\n type: 'fold',\n id: this.id,\n event: event,\n name: name\n };\n return this;\n };\n\n Log.Dom.Fold.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n return fail;\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Dom.Paragraph = function(part, num, string) {\n var span, _ref;\n this.part = part;\n this.num = num;\n this.ends = !!((_ref = string[string.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.spans = new Log.Dom.Spans(this, string.replace(/\\n$/, ''));\n this.data = {\n type: 'paragraph',\n num: this.part.num,\n hidden: this.hidden,\n nodes: (function() {\n var _i, _len, _ref1, _results;\n _ref1 = this.spans.content;\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n span = _ref1[_i];\n _results.push(span.data);\n }\n return _results;\n }).call(this)\n };\n return this;\n };\n\n Log.Dom.Paragraph.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n var next, prev, span, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;\n if ((prev = this.prev) && !prev.ends && !prev.fold) {\n if (Log.DEBUG) {\n console.log(\"P.1 - move \" + this.id + \"'s spans into prev\");\n }\n _ref = this.spans.content;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n prev.spans.append(span);\n }\n return this.part.nodes.remove(this);\n } else if ((next = this.next) && !this.ends && !next.fold) {\n if (Log.DEBUG) {\n console.log(\"P.2 - move \" + this.id + \"'s spans into next\");\n }\n _ref1 = this.spans.reverse();\n _results = [];\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n span = _ref1[_j];\n _results.push(next.prepend(span));\n }\n return _results;\n } else if ((prev != null ? prev.fold : void 0) && (prev != null ? (_ref2 = prev.element.getAttribute('class')) != null ? _ref2.match(' fold') : void 0 : void 0)) {\n if (Log.DEBUG) {\n console.log(\"P.3 - append \" + this.id + \" to fold \" + prev.id);\n }\n return this.element = this.trigger('insert', this.data, {\n after: prev.element.firstChild\n });\n } else if (prev) {\n if (Log.DEBUG) {\n console.log(\"P.4 - insert \" + this.id + \" after the parentNode of the last node of prev, id \" + prev.id);\n }\n return this.element = this.trigger('insert', this.data, {\n after: prev.element\n });\n } else if (next) {\n if (Log.DEBUG) {\n console.log(\"P.5 - insert \" + this.id + \" before the parentNode of the first node of next, id \" + next.id);\n }\n return this.element = this.trigger('insert', this.data, {\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"P.6 - insert \" + this.id + \" at the beginning of #log\");\n }\n return this.element = this.trigger('insert', this.data);\n }\n },\n remove: function() {\n var element, span, _i, _len, _ref;\n element = this.element;\n _ref = this.spans;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n this.trigger('remove', span.element);\n }\n if (!(element.childNodes.length > 1)) {\n this.trigger('remove', element);\n }\n return this.part.nodes.remove(this);\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('id', function() {\n return \"\" + this.part.num + \"-\" + this.num;\n });\n\n Log.Dom.Paragraph.prototype.__defineSetter__('element', function(element) {\n var child, span, _i, _len, _ref, _results;\n child = element.firstChild;\n _ref = this.spans.content;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n _results.push(span.element = child = child.nextSibling);\n }\n return _results;\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('element', function() {\n return this.spans.first.element.parentNode;\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('tail', function() {\n var next, parent, tail, _ref;\n parent = this.element.parentNode;\n next = this;\n tail = [];\n while ((next = next.next) && !next.fold && ((_ref = next.element) != null ? _ref.parentNode : void 0) === parent) {\n tail.push(next);\n }\n return tail;\n });\n\n Log.Dom.Spans = function(parent, string) {\n this.parent = parent;\n this.content = this.parse(parent, string);\n return this;\n };\n\n $.extend(Log.Dom.Spans.prototype, {\n parse: function(parent, string) {\n var ix, span, _i, _len, _ref, _results;\n _ref = Log.Deansi.apply(string);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n span = _ref[ix];\n _results.push(new Log.Dom.Span(parent, ix, span));\n }\n return _results;\n },\n at: function(ix) {\n return this.content[ix];\n },\n indexOf: function(span) {\n return this.content.indexOf(span);\n },\n append: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.push(span);\n return span.insert();\n },\n prepend: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.unshift(span);\n return span.insert();\n },\n reverse: function() {\n return this.content.reverse();\n },\n remove: function(span) {\n return this.content.splice(this.content.indexOf(span), 1);\n }\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('last', function() {\n return this.content[this.length - 1];\n });\n\n Log.Dom.Span = function(parent, num, data) {\n this.parent = parent;\n this.num = num;\n this.id = \"\" + parent.id + \"-\" + num;\n this.data = $.extend(data, {\n id: this.id\n });\n if (data.text.match(/\\r/)) {\n this.hidden = true;\n }\n this.data.text = data.text.replace(/^.*\\r/gm, '');\n if (this.hidden) {\n this.data[\"class\"] = ['hidden'];\n }\n return this;\n };\n\n $.extend(Log.Dom.Span.prototype, {\n insert: function() {\n var next, prev;\n if (prev = this.prev) {\n if (Log.DEBUG) {\n console.log(\"S.1 - insert \" + this.id + \" after prev \" + prev.id);\n }\n return this.insertAt({\n after: prev.element\n });\n } else if (next = this.next) {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" before next \" + next.id);\n }\n return this.insertAt({\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" into parent \" + this.parent.id);\n }\n return this.insertAt({\n into: this.parent.element\n });\n }\n },\n insertAt: function(pos) {\n var span, _i, _len, _ref, _results;\n this.element = this.trigger('insert', this.data, pos);\n if (this.hidden) {\n _ref = this.head;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n _results.push(span.hide());\n }\n return _results;\n } else {\n if (this.tail.some(function(span) {\n return span.hidden;\n })) {\n return this.hide();\n }\n }\n },\n hide: function() {\n if (!this.hidden) {\n this.trigger('hide', this.id);\n }\n return this.hidden = true;\n },\n siblings: function(direction) {\n var siblings, span, _ref;\n siblings = [];\n span = this;\n while ((span = span[direction]) && ((_ref = span.element) != null ? _ref.parentNode : void 0) === this.element.parentNode) {\n siblings.unshift(span);\n }\n return siblings;\n },\n trigger: function() {\n return this.parent.trigger.apply(this.parent, arguments);\n }\n });\n\n Log.Dom.Span.prototype.__defineGetter__('head', function() {\n return this.siblings('prev');\n });\n\n Log.Dom.Span.prototype.__defineGetter__('tail', function() {\n return this.siblings('next');\n });\n\n Log.Dom.Span.prototype.__defineGetter__('prev', function() {\n var span, _ref, _ref1;\n span = this.parent.spans.at(this.parent.spans.indexOf(this) - 1);\n return span || ((_ref = this.parent.prev) != null ? (_ref1 = _ref.spans) != null ? _ref1.last : void 0 : void 0);\n });\n\n Log.Dom.Span.prototype.__defineGetter__('next', function() {\n var span, _ref, _ref1;\n span = this.parent.spans.at(this.parent.spans.indexOf(this) + 1);\n return span || ((_ref = this.parent.next) != null ? (_ref1 = _ref.spans) != null ? _ref1.first : void 0 : void 0);\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/dom");minispade.register('log.old/engine/dom2', "(function() {(function() {\n\n Log.Dom = function(log) {\n this.log = log;\n this.parts = [];\n this.nodes = new Log.Dom.Nodes(this);\n return this;\n };\n\n $.extend(Log.Dom.prototype, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return this.insert(num, string);\n }\n },\n SLICE: 500,\n insert: function(num, string) {\n var ix, lines, next, slices,\n _this = this;\n lines = string.split(/^/gm) || [];\n slices = ((function() {\n var _results;\n _results = [];\n while (lines.length > 0) {\n _results.push(lines.splice(0, this.SLICE));\n }\n return _results;\n }).call(this));\n ix = -1;\n next = function() {\n _this.insertSlice(num, slices.shift(), ix += 1);\n if (slices.length !== 0) {\n return setTimeout(next, 50);\n }\n };\n return next();\n },\n insertSlice: function(num, lines, start) {\n var ix, line, _i, _len, _ref, _ref1, _results;\n _ref = lines || [];\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n break;\n }\n _results.push(this.nodes.insert(Log.Dom.Node.create(this, [num, start * this.SLICE + ix], line)));\n }\n return _results;\n }\n });\n\n Log.Dom.Nodes = function(parent) {\n this.parent = parent;\n this.content = [];\n return this;\n };\n\n $.extend(Log.Dom.Nodes.prototype, {\n at: function(ix) {\n return this.content[ix];\n },\n insert: function(node) {\n return this.content[node.num] = node;\n },\n remove: function(node) {\n return this.content.splice(this.content.indexOf(node), 1);\n }\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('length', function() {\n return this.content.length;\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('last', function() {\n return this.content[this.content.length - 1];\n });\n\n Log.Dom.Node = function() {};\n\n $.extend(Log.Dom.Node, {\n FOLDS_PATTERN: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(parent, ids, string) {\n var fold;\n if (fold = string.match(this.FOLDS_PATTERN)) {\n return new Log.Dom.Fold(parent, ids, fold[1], fold[2]);\n } else {\n return new Log.Dom.Paragraph(parent, ids, string);\n }\n }\n });\n\n Log.Dom.Node.prototype.__defineGetter__('prev', function() {\n var num, prev, _ref;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.parent.nodes.at(num -= 1);\n }\n return prev || ((_ref = this.parent.prev) != null ? _ref.nodes.last : void 0);\n });\n\n Log.Dom.Node.prototype.__defineGetter__('next', function() {\n var next, num, _ref;\n num = this.num;\n while (!(next || num >= this.parent.nodes.length)) {\n next = this.parent.nodes.at(num += 1);\n }\n return next || ((_ref = this.parent.next) != null ? _ref.nodes.first : void 0);\n });\n\n Log.Dom.Paragraph = function(parent, ids, string) {\n var _ref;\n this.parent = parent;\n this.ids = ids;\n this.id = ids.join('-');\n this.ends = !!((_ref = string[string.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.spans = new Log.Dom.Spans(this, ids, string.replace(/\\n$/, ''));\n return this;\n };\n\n Log.Dom.Paragraph.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n var next, prev,\n _this = this;\n if ((prev = this.prev) && !prev.ends && !prev.fold) {\n if (Log.DEBUG) {\n console.log(\"P.1 - move \" + this.id + \"'s spans into prev (\" + prev.id + \")\");\n }\n this.spans.content.slice().forEach(function(span) {\n return prev.spans.insert(span);\n });\n return this.remove();\n } else if ((next = this.next) && !this.ends && !next.fold) {\n if (Log.DEBUG) {\n console.log(\"P.2 - move next's (\" + next.id + \") spans into \" + this.id);\n }\n this.next.spans.content.slice().forEach(function(span) {\n return _this.spans.insert(span);\n });\n return next.remove();\n }\n },\n remove: function() {\n return this.parent.nodes.remove(this);\n }\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('id', function() {\n return \"\" + this.parent.num + \"-\" + this.num;\n });\n\n Log.Dom.Spans = function(parent, ids, string) {\n this.parent = parent;\n this.content = this.parse(parent, ids, string);\n return this;\n };\n\n $.extend(Log.Dom.Spans.prototype, {\n parse: function(parent, ids, string) {\n var ix, span, _i, _len, _ref, _results;\n _ref = Log.Deansi.apply(string);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n span = _ref[ix];\n _results.push(new Log.Dom.Span(parent, ids.concat([ix]), span));\n }\n return _results;\n },\n at: function(ix) {\n return this.content[ix];\n },\n indexOf: function(span) {\n return this.content.indexOf(span);\n },\n insert: function(span) {\n var head, ix, prev;\n console.log('insert', span.id);\n span.parent.spans.remove(span);\n span.parent = this.parent;\n head = this.content.filter(function(s) {\n return s.id < span.id;\n });\n if (prev = head[head.length - 1]) {\n ix = this.content.indexOf(prev) + 1;\n }\n return this.content.splice(ix || 0, 0, span);\n },\n prepend: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.unshift(span);\n return span.insert();\n },\n remove: function(span) {\n return this.content.splice(this.content.indexof(span), 1);\n }\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('last', function() {\n return this.content[this.content.length - 1];\n });\n\n Log.Dom.Span = function(parent, ids, data) {\n this.parent = parent;\n this.ids = ids;\n this.id = ids.join('-');\n this.data = $.extend(data, {\n id: this.id\n });\n if (data.text.match(/\\r/)) {\n this.hidden = true;\n }\n this.data.text = data.text.replace(/^.*\\r/gm, '');\n if (this.hidden) {\n this.data[\"class\"] = ['hidden'];\n }\n return this;\n };\n\n $.extend(Log.Dom.Span.prototype, {\n insert: function() {\n var next, prev;\n if (prev = this.prev) {\n if (Log.DEBUG) {\n console.log(\"S.1 - insert \" + this.id + \" after prev \" + prev.id);\n }\n return this.insertAt({\n after: prev.element\n });\n } else if (next = this.next) {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" before next \" + next.id);\n }\n return this.insertAt({\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" into parent \" + this.parent.id);\n }\n return this.insertAt({\n into: this.parent.element\n });\n }\n },\n insertAt: function(pos) {\n return this.element = this.trigger('insert', this.data, pos);\n }\n });\n\n Log.Dom.Span.prototype.__defineGetter__('prev', function() {\n var span, _ref, _ref1;\n console.log(this.num);\n span = this.parent.spans.at(this.num - 1);\n return span || ((_ref = this.parent.prev) != null ? (_ref1 = _ref.spans) != null ? _ref1.last : void 0 : void 0);\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/dom2");minispade.register('log.old/engine/live', "(function() {(function() {\n\n Log.Live = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Live.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Live.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Live.Part = function(log, num, string) {\n var ix, line;\n this.log = log;\n this.num = num;\n this.lines = (function() {\n var _i, _len, _ref, _results;\n _ref = string.split(/^/m);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n _results.push(new Log.Live.Line(this, ix, line));\n }\n return _results;\n }).call(this);\n return this;\n };\n\n $.extend(Log.Live.Part.prototype, {\n insert: function() {\n return new Log.Live.Context(this.log, this).insert();\n },\n head: function() {\n var head, line;\n head = [];\n line = this.lines[0];\n while ((line = line != null ? line.prev() : void 0) && !line.isNewline()) {\n head.unshift(line);\n }\n return head;\n },\n tail: function() {\n var line, tail;\n tail = [];\n line = this.lines[this.lines.length - 1];\n while (line = line != null ? line.next() : void 0) {\n tail.push(line);\n if (line != null ? line.isNewline() : void 0) {\n break;\n }\n }\n return tail;\n },\n prev: function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.log.parts[num -= 1];\n }\n return prev;\n },\n next: function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.log.parts.length)) {\n next = this.log.parts[num += 1];\n }\n return next;\n }\n });\n\n Log.Live.Line = function(part, num, string) {\n this.part = part;\n this.num = num;\n this.id = \"\" + part.num + \"-\" + num;\n this.string = string;\n return this;\n };\n\n $.extend(Log.Live.Line.prototype, {\n prev: function() {\n var line, _ref;\n line = this.part.lines[this.num - 1];\n return line || ((_ref = this.part.prev()) != null ? _ref.lines.slice(-1)[0] : void 0);\n },\n next: function() {\n var line, _ref;\n line = this.part.lines[this.num + 1];\n return line || ((_ref = this.part.next()) != null ? _ref.lines[0] : void 0);\n },\n isNewline: function() {\n return this.string[this.string.length - 1] === \"\\n\";\n },\n isFold: function() {\n return this.string.indexOf('fold') !== -1;\n },\n clone: function() {\n return new Log.Live.Line(this.part, this.num, this.string);\n }\n });\n\n Log.Live.Context = function(log, part) {\n this.log = log;\n this.part = part;\n this.head = part.head();\n this.tail = part.tail();\n this.lines = this.join(this.head.concat(part.lines).concat(this.tail));\n return this;\n };\n\n $.extend(Log.Live.Context.prototype, {\n insert: function() {\n var ids;\n ids = this.head.concat(this.tail).map(function(line) {\n return line.id;\n });\n if (ids.length !== 0) {\n this.log.trigger('remove', ids);\n }\n return this.log.trigger('insert', this.after(), this.nodes());\n },\n nodes: function() {\n var _this = this;\n return this.lines.map(function(line) {\n var fold, string;\n string = line.string;\n if (fold = _this.defold(string)) {\n return $.extend(fold, {\n id: line.id\n });\n } else {\n return {\n id: line.id,\n nodes: _this.deansi(string)\n };\n }\n });\n },\n join: function(all) {\n var line, lines;\n lines = [];\n while (line = all.pop()) {\n if (lines.length === 0 || line.isNewline()) {\n lines.unshift(line.clone());\n } else {\n lines[0].string = line.string + lines[0].string;\n }\n }\n return lines;\n },\n after: function() {\n var line, _ref;\n line = (_ref = this.part.lines[0]) != null ? _ref.prev() : void 0;\n while (line && !line.isNewline() && !line.isFold()) {\n line = line.prev();\n }\n return line != null ? line.id : void 0;\n },\n defold: function(string) {\n var matches;\n if (matches = string.match(/fold:(start|end):([\\w_\\-\\.]+)/)) {\n return {\n type: 'fold',\n event: matches[1],\n name: matches[2]\n };\n }\n },\n deansi: function(string) {\n return Log.Deansi.apply(string);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/live");minispade.register('log.old/folds', "(function() {(function() {\n\n Log.Folds = function() {\n this.folds = {};\n return this;\n };\n\n Log.Folds.prototype = $.extend(new Log.Listener, {\n insert: function(log, data, pos) {\n var fold, _base, _name;\n if (data.type === 'fold') {\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data);\n }\n return true;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n $.extend(Log.Folds.Fold.prototype, {\n receive: function(data) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate();\n }\n },\n activate: function() {\n var node, _i, _len, _ref;\n console.log(\"F - activate \" + this.start);\n console.log(document.firstChild.innerHTML.replace(/

          rcv \" + num + \" \" + (JSON.stringify(string)) + \"\");\n },\n insert: function(log, after, datas) {\n return this.log(\"ins \" + (datas.map(function(data) {\n return data.id;\n }).join(', ')) + \", after: \" + (after || '?') + \", \" + (JSON.stringify(datas)));\n },\n remove: function(log, id) {\n return this.log(\"rem \" + id);\n },\n log: function(line) {\n return $('#events').append(\"\" + line + \"\\n\");\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/instrument");minispade.register('log.old/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = $.extend(new Log.Listener, {\n count: 0,\n insert: function(log, line, pos) {\n if (line.type === 'paragraph' && !line.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Log.Limit.prototype.__defineGetter__('limited', function() {\n return this.count >= this.max_lines;\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/limit");minispade.register('log.old/renderer/inner_html', "(function() {(function() {\n\n Log.InnerHtmlRenderer = function() {\n this.frag = document.createDocumentFragment();\n this.div = document.createElement('div');\n return this;\n };\n\n Log.InnerHtmlRenderer.prototype = $.extend(new Log.Listener, {\n remove: function(log, ids) {\n var id, node, _i, _len, _ref, _results;\n _results = [];\n for (_i = 0, _len = ids.length; _i < _len; _i++) {\n id = ids[_i];\n node = document.getElementById(id);\n if (node && !((_ref = node.getAttribute('class')) != null ? _ref.match(/fold/) : void 0)) {\n _results.push(node.parentNode.removeChild(node));\n } else {\n _results.push(void 0);\n }\n }\n return _results;\n },\n insert: function(log, after, nodes) {\n var html;\n log = document.getElementById('log');\n html = this.render(nodes);\n if (log.childNodes.length === 0) {\n return log.innerHTML = html;\n } else if (after) {\n after = document.getElementById(after);\n return this.insertAfter(this.fragmentFrom(html), after);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(this.fragmentFrom(html), log.firstChild);\n }\n },\n render: function(nodes) {\n var node;\n return ((function() {\n var _i, _len, _results;\n _results = [];\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n _results.push(this.renderNode(node));\n }\n return _results;\n }).call(this)).join('');\n },\n renderNode: function(node) {\n var type;\n node.type || (node.type = 'paragraph');\n type = node.type[0].toUpperCase() + node.type.slice(1);\n return this[\"render\" + type](node) || '';\n },\n renderParagraph: function(node) {\n var html, style;\n if (node.hidden) {\n style = ' style=\"display:none\"';\n }\n html = \"

          \";\n html += ((function() {\n var _i, _len, _ref, _results;\n _ref = node.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n _results.push(this.renderNode(node));\n }\n return _results;\n }).call(this)).join('');\n return html + '

          ';\n },\n renderFold: function(node) {\n if (!document.getElementById(node.id)) {\n return \"
          \";\n }\n },\n renderSpan: function(node) {\n return \"\" + (this.clean(node.text)) + \"\";\n },\n renderText: function(node) {\n return this.clean(node.text);\n },\n clean: function(text) {\n return text.replace(/\\n/gm, '');\n },\n fragmentFrom: function(html) {\n var div, frag, node;\n frag = this.frag.cloneNode();\n div = this.div.cloneNode();\n div.innerHTML = html;\n while (node = div.firstChild) {\n frag.appendChild(node);\n }\n return frag;\n },\n insertAfter: function(node, after) {\n if (after.nextSibling) {\n return after.parentNode.insertBefore(node, after.nextSibling);\n } else {\n return after.parentNode.appendChild(node);\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/renderer/inner_html");minispade.register('log.old/renderer/jquery', "(function() {(function() {\n\n Log.JqueryRenderer = function() {};\n\n Log.JqueryRenderer.prototype = $.extend(new Log.Listener, {\n remove: function(log, ids) {\n var id, _i, _len, _results;\n _results = [];\n for (_i = 0, _len = ids.length; _i < _len; _i++) {\n id = ids[_i];\n _results.push($(\"#log #\" + id).remove());\n }\n return _results;\n },\n insert: function(log, after, datas) {\n var html,\n _this = this;\n html = datas.map(function(data) {\n return _this.render(data);\n });\n return after && $(\"#log #\" + after).after(html) || $('#log').prepend(html);\n },\n render: function(data) {\n var node, nodes, text;\n nodes = (function() {\n var _i, _len, _ref, _results;\n _ref = data.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n text = node.text.replace(/\\n/gm, '');\n if (node.type === 'span') {\n text = \"\" + text + \"\";\n }\n _results.push(\"

          \" + text + \"

          \");\n }\n return _results;\n }).call(this);\n return nodes.join(\"\\n\");\n },\n style: function(data) {\n return data.hidden && 'display: none;' || '';\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/renderer/jquery");minispade.register('log/deansi', "(function() {(function() {\n\n Log.Deansi = {\n CLEAR_ANSI: /(\\e|\\033)\\[K|(\\e|\\033)\\[K|(\\e|\\033)\\[\\d+G|(\\e|\\033)\\(B|(\\e|\\033)M|(\\e|\\033)\\[\\?25(l|h)/gm,\n apply: function(string) {\n var nodes,\n _this = this;\n if (!string) {\n return [];\n }\n string = string.replace(this.CLEAR_ANSI, '');\n nodes = ansiparse(string).map(function(part) {\n return _this.node(part);\n });\n if (nodes.length === 0) {\n nodes.push(this.node({\n text: ''\n }));\n }\n return nodes;\n },\n node: function(part) {\n var classes, node;\n node = {\n type: 'span',\n text: part.text\n };\n if (classes = this.classes(part)) {\n node[\"class\"] = classes.join(' ');\n }\n return node;\n },\n classes: function(part) {\n var result;\n result = [];\n result = result.concat(this.colors(part));\n if (result.length > 0) {\n return result;\n }\n },\n colors: function(part) {\n var colors;\n colors = [];\n if (part.foreground) {\n colors.push(part.foreground);\n }\n if (part.background) {\n colors.push(\"bg-\" + part.background);\n }\n if (part.bold) {\n colors.push('bold');\n }\n if (part.italic) {\n colors.push('italic');\n }\n return colors;\n },\n hidden: function(part) {\n if (part.text.match(/\\r/)) {\n part.text = part.text.replace(/^.*\\r/gm, '');\n return true;\n }\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=log/deansi");minispade.register('log/folds', "(function() {(function() {\n\n Log.Folds = function() {\n this.folds = {};\n return this;\n };\n\n Log.extend(Log.Folds.prototype, {\n add: function(data) {\n var fold, _base, _name;\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data);\n return fold.active;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n Log.extend(Log.Folds.Fold.prototype, {\n receive: function(data) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate();\n }\n },\n activate: function() {\n var node, _i, _len, _ref;\n if (Log.DEBUG) {\n console.log(\"F - activate \" + this.start);\n }\n _ref = this.nodes;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n this.fold.appendChild(node);\n }\n this.fold.setAttribute('class', this.classes());\n return this.active = true;\n },\n classes: function() {\n var classes;\n classes = this.fold.getAttribute('class').split(' ');\n classes.push('fold');\n if (this.fold.childNodes.length > 2) {\n classes.push('active');\n }\n return classes.join(' ');\n }\n });\n\n Log.Folds.Fold.prototype.__defineGetter__('fold', function() {\n return this._fold || (this._fold = document.getElementById(this.start));\n });\n\n Log.Folds.Fold.prototype.__defineGetter__('nodes', function() {\n var node, nodes;\n node = this.fold;\n nodes = [];\n while ((node = node.nextSibling) && node.id !== this.end) {\n nodes.push(node);\n }\n return nodes;\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/folds");minispade.register('log/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = Log.extend(new Log.Listener, {\n count: 0,\n insert: function(log, node, pos) {\n if (node.type === 'paragraph' && !node.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Log.Limit.prototype.__defineGetter__('limited', function() {\n return this.count >= this.max_lines;\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/limit");minispade.register('log/nodes', "(function() {(function() {\n\n Log.Node = function(id, num) {\n this.id = id;\n this.num = num;\n this.key = Log.Node.key(this.id);\n this.children = new Log.Nodes(this);\n return this;\n };\n\n Log.extend(Log.Node, {\n key: function(id) {\n if (id) {\n return id.split('-').map(function(i) {\n return '000000'.concat(i).slice(-6);\n }).join('');\n }\n }\n });\n\n Log.extend(Log.Node.prototype, {\n addChild: function(node) {\n return this.children.add(node);\n },\n remove: function() {\n this.log.remove(this.element);\n return this.parent.children.remove(this);\n }\n });\n\n Log.Node.prototype.__defineGetter__('log', function() {\n var _ref;\n return this._log || (this._log = ((_ref = this.parent) != null ? _ref.log : void 0) || this.parent);\n });\n\n Log.Node.prototype.__defineGetter__('firstChild', function() {\n return this.children.first;\n });\n\n Log.Node.prototype.__defineGetter__('lastChild', function() {\n return this.children.last;\n });\n\n Log.Nodes = function(parent) {\n if (parent) {\n this.parent = parent;\n }\n this.items = [];\n this.index = {};\n return this;\n };\n\n Log.extend(Log.Nodes.prototype, {\n add: function(item) {\n var ix, next, prev, _ref, _ref1;\n ix = this.position(item) || 0;\n this.items.splice(ix, 0, item);\n if (this.parent) {\n item.parent = this.parent;\n }\n prev = function(item) {\n while (item && !item.children.last) {\n item = item.prev;\n }\n return item != null ? item.children.last : void 0;\n };\n next = function(item) {\n while (item && !item.children.first) {\n item = item.next;\n }\n return item != null ? item.children.first : void 0;\n };\n if (item.prev = this.items[ix - 1] || prev((_ref = this.parent) != null ? _ref.prev : void 0)) {\n item.prev.next = item;\n }\n if (item.next = this.items[ix + 1] || next((_ref1 = this.parent) != null ? _ref1.next : void 0)) {\n item.next.prev = item;\n }\n return item;\n },\n remove: function(item) {\n this.items.splice(this.items.indexOf(item), 1);\n if (item.next) {\n item.next.prev = item.prev;\n }\n if (item.prev) {\n item.prev.next = item.next;\n }\n if (this.items.length === 0) {\n return this.parent.remove();\n }\n },\n position: function(item) {\n var ix, _i, _ref;\n for (ix = _i = _ref = this.items.length - 1; _i >= 0; ix = _i += -1) {\n if (this.items[ix].key < item.key) {\n return ix + 1;\n }\n }\n },\n indexOf: function() {\n return this.items.indexOf.apply(this.items, arguments);\n },\n slice: function() {\n return this.items.slice.apply(this.items, arguments);\n },\n each: function(func) {\n return this.items.slice().forEach(func);\n },\n map: function(func) {\n return this.items.map(func);\n }\n });\n\n Log.Nodes.prototype.__defineGetter__('first', function() {\n return this.items[0];\n });\n\n Log.Nodes.prototype.__defineGetter__('last', function() {\n return this.items[this.length - 1];\n });\n\n Log.Nodes.prototype.__defineGetter__('length', function() {\n return this.items.length;\n });\n\n Log.Part = function(id, num, string) {\n Log.Node.apply(this, arguments);\n this.string = string || '';\n this.string = this.string.replace(/\\033\\[1000D/gm, '\\r');\n this.string = this.string.replace(/\\r+\\n/gm, '\\n');\n this.strings = this.string.split(/^/gm) || [];\n this.slices = ((function() {\n var _results;\n _results = [];\n while (this.strings.length > 0) {\n _results.push(this.strings.splice(0, Log.SLICE));\n }\n return _results;\n }).call(this));\n return this;\n };\n\n Log.extend(Log.Part, {\n create: function(log, num, string) {\n var part;\n part = new Log.Part(num.toString(), num, string);\n log.addChild(part);\n return part.process(0, -1);\n }\n });\n\n Log.Part.prototype = Log.extend(new Log.Node, {\n remove: function() {},\n process: function(slice, num) {\n var node, span, spans, string, _i, _j, _len, _len1, _ref, _ref1, _ref2,\n _this = this;\n _ref = this.slices[slice] || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n string = _ref[_i];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n return;\n }\n spans = [];\n _ref2 = Log.Deansi.apply(string);\n for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {\n node = _ref2[_j];\n span = Log.Span.create(this, \"\" + this.id + \"-\" + (num += 1), num, node.text, node[\"class\"]);\n span.render();\n spans.push(span);\n }\n if (spans[0].line.cr) {\n spans[0].line.clear();\n }\n }\n if (!(slice >= this.slices.length - 1)) {\n return setTimeout((function() {\n return _this.process(slice + 1, num);\n }), Log.TIMEOUT);\n }\n }\n });\n\n Log.Span = function(id, num, text, classes) {\n var fold, _ref;\n Log.Node.apply(this, arguments);\n if (fold = text.match(Log.FOLD)) {\n this.fold = true;\n this.event = fold[1];\n this.text = this.name = fold[2];\n } else {\n this.text = text.replace(/.*\\r/gm, '').replace(/\\n$/, '');\n this.nl = !!((_ref = text[text.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.cr = !!text.match(/\\r/);\n this[\"class\"] = this.cr && ['clears'] || classes;\n }\n return this;\n };\n\n Log.extend(Log.Span, {\n create: function(parent, id, num, text, classes) {\n var span;\n span = new Log.Span(id, num, text, classes);\n parent.addChild(span);\n return span;\n },\n render: function(parent, id, num, text, classes) {\n var span;\n span = this.create(parent, id, num, text, classes);\n return span.render();\n }\n });\n\n Log.Span.prototype = Log.extend(new Log.Node, {\n render: function() {\n var tail;\n if (!this.fold && this.prev && !this.prev.fold && !this.prev.nl) {\n if (Log.DEBUG) {\n console.log(\"S.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n this.log.insert(this.data, {\n after: this.prev.element\n });\n this.line = this.prev.line;\n } else if (!this.fold && this.next && !this.next.fold) {\n if (Log.DEBUG) {\n console.log(\"S.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n this.log.insert(this.data, {\n before: this.next.element\n });\n this.line = this.next.line;\n } else {\n this.line = Log.Line.create(this.log, [this]);\n this.line.render();\n }\n if (this.nl && (tail = this.tail).length > 0) {\n return this.split(tail);\n }\n },\n remove: function() {\n Log.Node.prototype.remove.apply(this);\n if (this.line) {\n return this.line.remove(this);\n }\n },\n split: function(spans) {\n var line, span, _i, _len;\n if (Log.DEBUG) {\n console.log(\"S.3 split [\" + (spans.map(function(span) {\n return span.id;\n }).join(', ')) + \"]\");\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n this.log.remove(span.element);\n }\n line = Log.Line.create(this.log, spans);\n line.render();\n if (line.cr) {\n return line.clear();\n }\n },\n clear: function() {\n if (this.prev && this.isSibling(this.prev) && this.isSequence(this.prev)) {\n this.prev.clear();\n return this.prev.remove();\n }\n },\n isSequence: function(other) {\n return this.parent.num - other.parent.num === this.log.children.indexOf(this.parent) - this.log.children.indexOf(other.parent);\n },\n isSibling: function(other) {\n var _ref, _ref1;\n return ((_ref = this.element) != null ? _ref.parentNode : void 0) === ((_ref1 = other.element) != null ? _ref1.parentNode : void 0);\n },\n siblings: function(type) {\n var siblings, span;\n siblings = [];\n while ((span = (span || this)[type]) && this.isSibling(span)) {\n siblings.push(span);\n }\n return siblings;\n }\n });\n\n Log.Span.prototype.__defineSetter__('line', function(line) {\n if (this.line) {\n this.line.remove(this);\n }\n this._line = line;\n return this.line.add(this);\n });\n\n Log.Span.prototype.__defineGetter__('data', function() {\n return {\n id: this.id,\n type: 'span',\n text: this.text,\n \"class\": this[\"class\"]\n };\n });\n\n Log.Span.prototype.__defineGetter__('line', function() {\n return this._line;\n });\n\n Log.Span.prototype.__defineGetter__('element', function() {\n return document.getElementById(this.id);\n });\n\n Log.Span.prototype.__defineGetter__('head', function() {\n return this.siblings('prev').reverse();\n });\n\n Log.Span.prototype.__defineGetter__('tail', function() {\n return this.siblings('next');\n });\n\n Log.Line = function(log) {\n this.log = log;\n this.spans = [];\n return this;\n };\n\n Log.extend(Log.Line, {\n create: function(log, spans) {\n var line, span, _i, _len;\n if ((span = spans[0]) && span.fold) {\n line = new Log.Fold(log, span.event, span.name);\n } else {\n line = new Log.Line(log);\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n span.line = line;\n }\n return line;\n }\n });\n\n Log.extend(Log.Line.prototype, {\n add: function(span) {\n var ix;\n if (span.cr) {\n this.cr = true;\n }\n if (this.spans.indexOf(span) > -1) {\n\n } else if ((ix = this.spans.indexOf(span.prev)) > -1) {\n return this.spans.splice(ix + 1, 0, span);\n } else if ((ix = this.spans.indexOf(span.next)) > -1) {\n return this.spans.splice(ix, 0, span);\n } else {\n return this.spans.push(span);\n }\n },\n remove: function(span) {\n var ix;\n if ((ix = this.spans.indexOf(span)) > -1) {\n return this.spans.splice(ix, 1);\n }\n },\n render: function() {\n var fold;\n if ((fold = this.prev) && fold.event === 'start' && fold.active) {\n if (Log.DEBUG) {\n console.log(\"L.0 insert \" + this.id + \" into fold \" + fold.id);\n }\n fold = this.log.folds.folds[fold.name].fold;\n return this.element = this.log.insert(this.data, {\n into: fold\n });\n } else if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"L.1 insert \" + this.spans[0].id + \" after prev \" + this.prev.id);\n }\n return this.element = this.log.insert(this.data, {\n after: this.prev.element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"L.2 insert \" + this.spans[0].id + \" before next \" + this.next.id);\n }\n return this.element = this.log.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"L.3 insert \" + this.spans[0].id + \" into #log\");\n }\n return this.element = this.log.insert(this.data);\n }\n },\n clear: function() {\n var cr, _i, _len, _ref, _results;\n _ref = this.crs;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n cr = _ref[_i];\n _results.push(cr.clear());\n }\n return _results;\n }\n });\n\n Log.Line.prototype.__defineGetter__('id', function() {\n var _ref;\n return (_ref = this.spans[0]) != null ? _ref.id : void 0;\n });\n\n Log.Line.prototype.__defineGetter__('data', function() {\n return {\n type: 'paragraph',\n nodes: this.nodes\n };\n });\n\n Log.Line.prototype.__defineGetter__('nodes', function() {\n return this.spans.map(function(span) {\n return span.data;\n });\n });\n\n Log.Line.prototype.__defineGetter__('prev', function() {\n var _ref;\n return (_ref = this.spans[0].prev) != null ? _ref.line : void 0;\n });\n\n Log.Line.prototype.__defineGetter__('next', function() {\n var _ref;\n return (_ref = this.spans[this.spans.length - 1].next) != null ? _ref.line : void 0;\n });\n\n Log.Line.prototype.__defineGetter__('crs', function() {\n return this.spans.filter(function(span) {\n return span.cr;\n });\n });\n\n Log.Fold = function(log, event, name) {\n Log.Line.apply(this, arguments);\n this.fold = true;\n this.event = event;\n this.name = name;\n return this;\n };\n\n Log.Fold.prototype = Log.extend(new Log.Line, {\n render: function() {\n var element, _ref;\n if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"F.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n element = this.prev.element || this.prev.element.parentNode;\n this.element = this.log.insert(this.data, {\n after: element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"F.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n element = this.next.element || this.next.element.parentNode;\n this.element = this.log.insert(this.data, {\n before: element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"F.3 insert \" + this.id);\n }\n this.element = this.log.insert(this.data);\n }\n if (this.span.next && ((_ref = this.span.prev) != null ? _ref.isSibling(this.span.next) : void 0)) {\n this.span.prev.split([this.span.next].concat(this.span.next.tail));\n }\n return this.active = this.log.folds.add(this.data);\n }\n });\n\n Log.Fold.prototype.__defineGetter__('id', function() {\n return \"fold-\" + this.event + \"-\" + this.name;\n });\n\n Log.Fold.prototype.__defineGetter__('span', function() {\n return this.spans[0];\n });\n\n Log.Fold.prototype.__defineGetter__('data', function() {\n return {\n type: 'fold',\n id: this.id,\n event: this.event,\n name: this.name\n };\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/nodes");minispade.register('log/renderer', "(function() {(function() {\n\n Log.Renderer = function() {\n this.frag = document.createDocumentFragment();\n this.para = this.createParagraph();\n this.span = this.createSpan();\n this.text = document.createTextNode('');\n this.fold = this.createFold();\n return this;\n };\n\n Log.extend(Log.Renderer.prototype, {\n insert: function(data, pos) {\n var after, before, into, node;\n node = this.render(data);\n if (into = pos != null ? pos.into : void 0) {\n if (typeof into === 'String') {\n into = document.getElementById(pos != null ? pos.into : void 0);\n }\n this.appendTo(node, into);\n } else if (after = pos != null ? pos.after : void 0) {\n if (typeof after === 'String') {\n after = document.getElementById(pos);\n }\n this.insertAfter(node, after);\n } else if (before = pos != null ? pos.before : void 0) {\n if (typeof before === 'String') {\n before = document.getElementById(pos != null ? pos.before : void 0);\n }\n this.insertBefore(node, before);\n } else {\n this.insertBefore(node);\n }\n return node;\n },\n hide: function(node) {\n node.setAttribute('class', this.addClass(node.getAttribute('class'), 'hidden'));\n return node;\n },\n remove: function(node) {\n if (node) {\n node.parentNode.removeChild(node);\n }\n return node;\n },\n render: function(data) {\n var frag, node, type, _i, _len;\n if (data instanceof Array) {\n frag = this.frag.cloneNode(true);\n for (_i = 0, _len = data.length; _i < _len; _i++) {\n node = data[_i];\n node = this.render(node);\n if (node) {\n frag.appendChild(node);\n }\n }\n return frag;\n } else {\n data.type || (data.type = 'paragraph');\n type = data.type[0].toUpperCase() + data.type.slice(1);\n return this[\"render\" + type](data);\n }\n },\n renderParagraph: function(data) {\n var node, para, type, _i, _len, _ref;\n para = this.para.cloneNode(true);\n if (data.id) {\n para.setAttribute('id', data.id);\n }\n if (data.hidden) {\n para.setAttribute('style', 'display: none;');\n }\n _ref = data.nodes || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n type = node.type[0].toUpperCase() + node.type.slice(1);\n node = this[\"render\" + type](node);\n para.appendChild(node);\n }\n return para;\n },\n renderFold: function(data) {\n var fold;\n fold = this.fold.cloneNode(true);\n fold.setAttribute('id', data.id || (\"fold-\" + data.event + \"-\" + data.name));\n fold.setAttribute('class', \"fold-\" + data.event);\n if (data.event === 'start') {\n fold.lastChild.lastChild.nodeValue = data.name;\n } else {\n fold.removeChild(fold.lastChild);\n }\n return fold;\n },\n renderSpan: function(data) {\n var span;\n span = this.span.cloneNode(true);\n if (data.id) {\n span.setAttribute('id', data.id);\n }\n if (data[\"class\"]) {\n span.setAttribute('class', data[\"class\"]);\n }\n span.lastChild.nodeValue = data.text;\n return span;\n },\n renderText: function(data) {\n var text;\n text = this.text.cloneNode(true);\n text.nodeValue = data.text;\n return text;\n },\n createParagraph: function() {\n var para;\n para = document.createElement('p');\n para.appendChild(document.createElement('a'));\n return para;\n },\n createFold: function() {\n var fold;\n fold = document.createElement('div');\n fold.appendChild(this.createSpan());\n fold.lastChild.setAttribute('class', 'fold-name');\n return fold;\n },\n createSpan: function() {\n var span;\n span = document.createElement('span');\n span.appendChild(document.createTextNode(''));\n return span;\n },\n insertBefore: function(node, other) {\n var log;\n if (other) {\n return other.parentNode.insertBefore(node, other);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(node, log.firstChild);\n }\n },\n insertAfter: function(node, other) {\n if (other.nextSibling) {\n return this.insertBefore(node, other.nextSibling);\n } else {\n return this.appendTo(node, other.parentNode);\n }\n },\n appendTo: function(node, other) {\n return other.appendChild(node);\n },\n addClass: function(classes, string) {\n if (classes != null ? classes.indexOf(string) : void 0) {\n return;\n }\n if (classes) {\n return \"\" + classes + \" \" + string;\n } else {\n return string;\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/renderer"); \ No newline at end of file From 31f25ed4f85b59203b53f3dd5aab00f4028aedd3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 8 Apr 2013 00:25:03 +0200 Subject: [PATCH 14/15] Move WorkersView and JobsView to Travis namespace That way those views can be overriden easily --- assets/scripts/app/views/sidebar.coffee | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/assets/scripts/app/views/sidebar.coffee b/assets/scripts/app/views/sidebar.coffee index 35103343..fd8d28b4 100644 --- a/assets/scripts/app/views/sidebar.coffee +++ b/assets/scripts/app/views/sidebar.coffee @@ -1,4 +1,20 @@ @Travis.reopen + WorkersView: Em.View.extend + templateName: 'workers/list' + init: -> + @_super.apply this, arguments + @set 'controller', @get('controller').container.lookup('controller:workers') + + JobsView: Em.View.extend + templateName: 'jobs/running' + elementId: 'running-jobs' + init: -> + @_super.apply this, arguments + @set 'controller', @get('controller').container.lookup('controller:runningJobs') + + groupsBinding: 'controller.sortedGroups' + jobsBinding: 'controller' + SidebarView: Travis.View.extend templateName: 'layouts/sidebar' @@ -10,7 +26,7 @@ activate: (name) -> return if @get('activeTab') == name @set('activeTab', name) - @connectOutlet 'pane', @["#{name.capitalize()}View"].create(controller: @get('controller')) + @connectOutlet 'pane', Travis["#{name.capitalize()}View"].create(controller: @get('controller')) classQueues: (-> 'active' if @get('activeTab') == 'queues' @@ -36,28 +52,12 @@ @_super.apply this, arguments @set 'controller', @get('controller').container.lookup('controller:links') - WorkersView: Em.View.extend - templateName: 'workers/list' - init: -> - @_super.apply this, arguments - @set 'controller', @get('controller').container.lookup('controller:workers') - QueuesView: Em.View.extend templateName: 'queues/list' init: -> @_super.apply this, arguments @set 'controller', @get('controller').container.lookup('controller:queues') - JobsView: Em.View.extend - templateName: 'jobs/running' - elementId: 'running-jobs' - init: -> - @_super.apply this, arguments - @set 'controller', @get('controller').container.lookup('controller:runningJobs') - - groupsBinding: 'controller.sortedGroups' - jobsBinding: 'controller' - GroupView: Em.View.extend templateName: 'jobs/running/group' tagName: 'li' From 11988099791a81250c8eb1ccd0cf31a828c714a2 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 8 Apr 2013 00:36:19 +0200 Subject: [PATCH 15/15] Move WorkersView and JobsView to Travis.SidebarView namespace Travis.JobsView already exists, so I need to put those views in some other namespace, but so that they're available without instantiating SidebarView --- assets/scripts/app/views/sidebar.coffee | 36 +++++++++++++------------ 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/assets/scripts/app/views/sidebar.coffee b/assets/scripts/app/views/sidebar.coffee index fd8d28b4..0c345fa1 100644 --- a/assets/scripts/app/views/sidebar.coffee +++ b/assets/scripts/app/views/sidebar.coffee @@ -1,20 +1,4 @@ @Travis.reopen - WorkersView: Em.View.extend - templateName: 'workers/list' - init: -> - @_super.apply this, arguments - @set 'controller', @get('controller').container.lookup('controller:workers') - - JobsView: Em.View.extend - templateName: 'jobs/running' - elementId: 'running-jobs' - init: -> - @_super.apply this, arguments - @set 'controller', @get('controller').container.lookup('controller:runningJobs') - - groupsBinding: 'controller.sortedGroups' - jobsBinding: 'controller' - SidebarView: Travis.View.extend templateName: 'layouts/sidebar' @@ -24,9 +8,10 @@ @activate('jobs') activate: (name) -> + console.log return if @get('activeTab') == name @set('activeTab', name) - @connectOutlet 'pane', Travis["#{name.capitalize()}View"].create(controller: @get('controller')) + @connectOutlet 'pane', Travis.SidebarView["#{name.capitalize()}View"].create(controller: @get('controller')) classQueues: (-> 'active' if @get('activeTab') == 'queues' @@ -96,3 +81,20 @@ QueueItemView: Travis.View.extend tagName: 'li' + +Travis.SidebarView.reopenClass + WorkersView: Em.View.extend + templateName: 'workers/list' + init: -> + @_super.apply this, arguments + @set 'controller', @get('controller').container.lookup('controller:workers') + + JobsView: Em.View.extend + templateName: 'jobs/running' + elementId: 'running-jobs' + init: -> + @_super.apply this, arguments + @set 'controller', @get('controller').container.lookup('controller:runningJobs') + + groupsBinding: 'controller.sortedGroups' + jobsBinding: 'controller'