File: docs.coffee

package info (click to toggle)
coffeescript 2.7.0%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,360 kB
  • sloc: makefile: 20; xml: 9; sh: 6; javascript: 5
file content (228 lines) | stat: -rw-r--r-- 8,945 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
unless window.location.origin # Polyfill `location.origin` for IE < 11
  window.location.origin = "#{window.location.protocol}//#{window.location.hostname}"


# Initialize Google Analytics
window.GA_TRACKING_ID = 'UA-106156830-1'
window.dataLayer ?= []
window.gtag = ->
  window.dataLayer.push arguments
  return
window.gtag 'js', new Date()
window.gtag 'config', window.GA_TRACKING_ID


# Initialize the CoffeeScript docs interactions
$(document).ready ->
  CoffeeScript.patchStackTrace()

  # Format dates for the user’s locale, e.g. 'December 24, 2009' or '24 décembre 2009'
  $('time').each (index, el) ->
    date = el.dateTime or $(el).text()
    formattedDate = new Date(date).toLocaleDateString undefined, # undefined to use browser locale
      year: 'numeric'
      month: 'long'
      day: 'numeric'
    $(el).text formattedDate.toString()


  # Mobile navigation
  toggleSidebar = ->
    $('.navbar-toggler, .sidebar').toggleClass 'show'

  $('[data-toggle="offcanvas"]').click toggleSidebar

  $('[data-action="sidebar-nav"]').click (event) ->
    if $('.navbar-toggler').is(':visible')
      event.preventDefault()
      toggleSidebar()
      setTimeout ->
        window.location = event.target.href
      , 260 # Wait for the sidebar to slide away before navigating
    gtag 'event', 'sidebar_navigate',
      event_category: 'navigation'
      event_label: event.target.href.replace window.location.origin, ''

  # Initialize Scrollspy for sidebar navigation; https://getbootstrap.com/docs/4.0/components/scrollspy/
  # See also http://www.codingeverything.com/2014/02/BootstrapDocsSideBar.html and http://jsfiddle.net/KyleMit/v6zhz/
  $('.main').scrollspy
    target: '#contents'
    offset: Math.round $('main').css('padding-top').replace('px', '')

  initializeScrollspyFromHash = (hash) ->
    $("#contents a.active[href!='#{hash}']").removeClass 'show'

  $('.main').on 'activate.bs.scrollspy', (event, target) ->
    # We only want one active link in the nav
    $("#contents a.active[href!='#{target.relatedTarget}']").removeClass 'show'
    $target = $("#contents a[href='#{target.relatedTarget}']")
    return if $target.prop('href') is "#{window.location.origin}/#try"
    # Update the browser address bar on scroll, without adding to the history; clicking the sidebar links will automatically add to the history
    replaceState $target.prop('href')
    # Track this as a new pageview; we only want '/#hash', not 'https://coffeescript.org/#hash'
    gtag 'config', GA_TRACKING_ID,
      page_path: $target.prop('href').replace window.location.origin, ''


  # Initialize CodeMirror for code examples; https://codemirror.net/doc/manual.html
  # Defer this until a code example is clicked or focused, to avoid unnecessary computation/slowness
  textareas = []
  editors = []
  lastCompilationElapsedTime = 200
  $('textarea').each (index) ->
    textareas[index] = @
    $(@).data 'index', index

  initializeEditor = ($textarea) ->
    index = $textarea.data 'index'
    mode = if $textarea.hasClass('javascript-output') then 'javascript' else 'coffeescript'
    editors[index] = editor = CodeMirror.fromTextArea $textarea[0],
      mode: mode
      theme: 'twilight'
      indentUnit: 2
      tabSize: 2
      lineWrapping: on
      lineNumbers: off
      inputStyle: 'contenteditable'
      readOnly: mode isnt 'coffeescript' # Can’t use 'nocursor' if we want the JavaScript to be copyable
      viewportMargin: Infinity

    # Whenever the user edits the CoffeeScript side of a code example, update the JavaScript output
    # If the editor is Try CoffeeScript, also update the hash and save this code in localStorage
    if mode is 'coffeescript'
      pending = null
      editor.on 'change', (instance, change) ->
        clearTimeout pending
        pending = setTimeout ->
          lastCompilationStartTime = Date.now()
          try
            coffee = editor.getValue()
            if index is 0 and $('#try').hasClass('show') # If this is the editor in Try CoffeeScript and it’s still visible
              if $('#try').hasClass('show')
                # Update the hash with the current code
                link = "try:#{encodeURIComponent coffee}"
                replaceState "#{window.location.href.split('#')[0]}##{link}"
              # Save this to the user’s localStorage
              try
                if window.localStorage?
                  window.localStorage.setItem 'tryCoffeeScriptCode', coffee
              catch exception

            js = CoffeeScript.compile coffee, bare: yes, inlineMap: true
            # Inline map is added to adjust stack trace line numbers but we strip it from the displayed JS for visual clarity.
            output = js.replace /(\n\/\/# [^\n]*){2}$/, ""
            lastCompilationElapsedTime = Math.max(200, Date.now() - lastCompilationStartTime)
          catch exception
            output = "#{exception}"

          editors[index + 1].js = js
          editors[index + 1].setValue output

          gtag 'event', 'edit_code',
            event_category: 'engagement'
            event_label: $textarea.closest('[data-example]').data('example')
        , lastCompilationElapsedTime

      # Fix the code editors’ handling of tab-indented code
      editor.addKeyMap
        'Tab': (cm) ->
          if cm.somethingSelected()
            cm.indentSelection 'add'
          else if /^\t/m.test cm.getValue()
            # If any lines start with a tab, treat this as tab-indented code
            cm.execCommand 'insertTab'
          else
            cm.execCommand 'insertSoftTab'
        'Shift-Tab': (cm) ->
          cm.indentSelection 'subtract'
        'Enter': (cm) ->
          cm.options.indentWithTabs = /^\t/m.test cm.getValue()
          cm.execCommand 'newlineAndIndent'

  $('.placeholder-code').one 'mouseover', (event) ->
    $textarea = $(@).prev 'textarea'
    $(@).remove()
    initializeEditor $textarea
    # Initialize the sibling column too
    $siblingColumn = $ $textarea.parent().siblings()[0]
    $siblingColumn.children('.placeholder-code').remove()
    initializeEditor $ $siblingColumn.children('textarea')[0]

  initializeTryEditors = ->
    initializeEditor $ '#try-coffeescript-coffee'
    initializeEditor $ '#try-coffeescript-js'

  # Handle the code example buttons
  $('[data-action="run-code-example"]').click ->
    run = $(@).data 'run'
    index = $("##{$(@).data('example')}-js").data 'index'
    js = if editors[index]?
      editors[index].js
    else
      $(textareas[index]).val()
    js = "#{js}\nalert(#{unescape run});" unless run is yes
    window.eval js
    gtag 'event', 'run_code',
      event_category: 'engagement'
      event_label: $(@).closest('[data-example]').data('example')

  # Try CoffeeScript
  previousHash = null
  toggleTry = (checkLocalStorage) ->
    $('#try, #try-link').toggleClass 'show'
    if $('#try').hasClass('show')
      previousHash = window.location.hash if window.location.hash
      initializeTryEditors() if $('#try .CodeMirror').length is 0
      if checkLocalStorage and window.localStorage?
        try
          coffee = window.localStorage.getItem 'tryCoffeeScriptCode'
          if coffee?
            editors[0].setValue coffee
          else
            replaceState '#try'
        catch exception
          replaceState '#try'
      else
        replaceState '#try'
    else
      if previousHash then replaceState(previousHash) else clearHash()
  closeTry = ->
    $('#try, #try-link').removeClass 'show'
    if previousHash then replaceState(previousHash) else clearHash()

  $('[data-toggle="try"]').click (event) ->
    event.preventDefault()
    toggleTry yes
  $('[data-close="try"]').click closeTry

  $('[data-action="scroll-to-top"]').click (event) ->
    return if $('#try').hasClass('show')
    $('.main')[0].scrollTop = 0
    setTimeout clearHash, 10

  clearHash = ->
    window.history.replaceState {}, document.title, window.location.pathname

  replaceState = (newURL) ->
    newURL = "#{window.location.pathname}#{newURL}" if newURL?.indexOf('#') is 0
    window.history.replaceState {}, document.title, (newURL or '')

  $(window).on 'hashchange', ->
    # Get rid of dangling # in the address bar
    clearHash() if window.location.hash is ''

  # Configure the initial state
  if window.location.hash?
    if window.location.hash is '#try'
      toggleTry yes
    else if window.location.hash.indexOf('#try') is 0
      initializeTryEditors() if $('#try .CodeMirror').length is 0
      editors[0].setValue decodeURIComponent window.location.hash[5..]
      toggleTry no
    else if window.location.hash is ''
      clearHash()
    else
      initializeScrollspyFromHash window.location.hash
      if window.location.hash.length > 1
        # Initializing the code editors might’ve thrown off our vertical scroll position
        document.getElementById(window.location.hash.slice(1).replace(/try:.*/, '')).scrollIntoView()