<commit_before>'use babel'

import { CompositeDisposable, Directory } from 'atom'
// import { isListItem, wrapText } from './functions'

CSON = require('season')
fs = require('fs')
GrammarCompiler = require('./GrammarCompiler')
path = require('path')

module.exports = {
  config: {
    addListItems: {
      title: 'Add new list-items',
      description: 'Automatically add a new list-item after the current (non-empty) one when pressing ENTER',
      type: 'boolean',
      default: true
    },

    autoIncrementListItems: {
        title: 'Increment Ordered List Items',
        description: 'Automatically increment a new list-item after the current(non-empty) one when pressing ENTER',
        type: 'boolean',
        default: false
    },

    disableLanguageGfm: {
      title: 'Disable language-gfm',
      description: 'Disable the default `language-gfm` package as this package is intended as its replacement',
      type: 'boolean',
      default: true
    },

    emphasisShortcuts: {
      title: 'Emphasis shortcuts',
      description: 'Enables keybindings `_` for emphasis, `*` for strong emphasis, and `~` for strike-through on selected text; emphasizing an already emphasized selection will de-emphasize it',
      type: 'boolean',
      default: true
    },

    indentListItems: {
      title: 'Indent list-items',
      description: 'Automatically in- and outdent list-items by pressing `TAB` and `SHIFT+TAB`',
      type: 'boolean',
      default: true
    },

    linkShortcuts: {
      title: 'Link shortcuts',
      description: 'Enables keybindings `@` for converting the selected text to a link and `!` for converting the selected text to an image',
      type: 'boolean',
      default: true
    },

    removeEmptyListItems: {
      title: 'Remove empty list-items',
      description: 'Remove the automatically created empty list-items when left empty, leaving an empty line',
      type: 'boolean',
      default: true
    }
  },

  subscriptions: null,

  activate (state) {
    this.subscriptions = new CompositeDisposable()
    this.addCommands()

    /*
    Unless you are an advanced user, there is no need to have both this package
    and the one it replaces (language-gfm) enabled.

    If you are an advanced user, you can easily re-enable language-gfm again.
    */
    if (atom.config.get('language-markdown.disableLanguageGfm')) {
      if (!atom.packages.isPackageDisabled('language-gfm')) {
        atom.packages.disablePackage('language-gfm')
      }
    }

    /*
    I forgot why this action is created inline in activate() and not as a
    separate method, but there was a good reason for it.
    */
    this.subscriptions.add(atom.workspace.observeTextEditors(editor => {
      editor.onDidInsertText(event => {
        const grammar = editor.getGrammar()

        if (grammar.name !== 'Markdown') return
        if (!atom.config.get('language-markdown.addListItems')) return
        if (event.text !== '\n') return

        /*
        At this point, it is rather tedious (as far as I know) to get to the
        tokenized version of {previousLine}. That is the reason why {tokens} a
        little further down is tokenized. But at this stage, we do need to know
        if {previousLine} was in fact Markdown, or from a different perspective,
        not a piece of embedded code. The reason for that is that the tokenized
        line below is tokenized without any context, so is Markdown by default.
        Therefore we determine if our current position is part of embedded code
        or not.
        */

        const previousRowNumber = event.range.start.row
        const previousRowRange = editor.buffer.rangeForRow(previousRowNumber)
        if (this.isEmbeddedCode(editor, previousRowRange)) return

        const previousLine = editor.getTextInRange(previousRowRange)
        let { tokens } = grammar.tokenizeLine(previousLine)
        tokens.reverse()
        for (const token of tokens) {
          let isPunctuation = false
          let isListItem = false
          let typeOfList

          const scopes = token.scopes.reverse()
          for (const scope of scopes) {
            const classes = scope.split('.')

            /*
            A list-item is valid when a punctuation class is immediately
            followed by a non-empty list-item class.
            */
            if (classes.includes('punctuation')) {
              isPunctuation = true
            } else if (isPunctuation && classes.includes('list')) {
              if (!classes.includes('empty')) {
                isListItem = true
                typeOfList = 'unordered'
                if (classes.includes('ordered')) {
                  typeOfList = 'ordered'
                }
                if (classes.includes('definition')) {
                  typeOfList = 'definition'
                }
                break
              } else {
                isListItem = false
                isPunctuation = false
                if (atom.config.get('language-markdown.removeEmptyListItems')) {
                  editor.setTextInBufferRange(previousRowRange, '')
                }
              }
            } else {
              isPunctuation = false
            }
          }

          if (isListItem && typeOfList !== 'definition') {
            let text = token.value
            if (typeOfList === 'ordered') {
              const length = text.length
              const punctuation = text.match(/[^\d]+/)
              var value = parseInt(text)
              if (atom.config.get('language-markdown.autoIncrementListItems')) {
                  value = value + 1
              }
              text = value + punctuation
              if (text.length < length) {
                for (let j = 0; j < text.length - length + 1; j++) {
                  text = '0' + text
                }
              }
            } else {
              text = text.replace('x', ' ')
            }
            editor.insertText(text + '')
            break
          }
        }
      })
    }))
  },

  addCommands () {
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:indent-list-item', (event) => this.indentListItem(event)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:outdent-list-item', (event) => this.outdentListItem(event)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:emphasis', (event) => this.emphasizeSelection(event, '_')))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:strong-emphasis', (event) => this.emphasizeSelection(event, '**')))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:strike-through', (event) => this.emphasizeSelection(event, '~~')))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:link', (event) => this.linkSelection(event)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:image', (event) => this.linkSelection(event, true)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:toggle-task', (event) => this.toggleTask(event)))

    if (atom.inDevMode()) {
      this.subscriptions.add(atom.commands.add('atom-workspace', 'markdown:compile-grammar-and-reload', () => this.compileGrammar()))
    }
  },

  indentListItem (event) {
    const { editor, position } = this._getEditorAndPosition(event)
    const indentListItems = atom.config.get('language-markdown.indentListItems')
    if (indentListItems && this.isListItem(editor, position)) {
      editor.indentSelectedRows(position.row)
      return
    }
    event.abortKeyBinding()
  },

  outdentListItem (event) {
    const { editor, position } = this._getEditorAndPosition(event)
    const indentListItems = atom.config.get('language-markdown.indentListItems')
    if (indentListItems && this.isListItem(editor, position)) {
      editor.outdentSelectedRows(position.row)
      return
    }
    event.abortKeyBinding()
  },

  emphasizeSelection (event, token) {
    let didSomeWrapping = false
    if (atom.config.get('language-markdown.emphasisShortcuts')) {
      const editor = atom.workspace.getActiveTextEditor()
      if (!editor) return

      const ranges = this.getSelectedBufferRangesReversed(editor)
      for (const range of ranges) {
        const text = editor.getTextInBufferRange(range)
        /*
        Skip texts that contain a line-break, or are empty.
        Multi-line emphasis is not supported 'anyway'.

        If afterwards not a single selection has been wrapped, cancel the event
        and insert the character as normal.

        If two cursors were found, but only one of them was a selection, and the
        other a normal cursor, then the normal cursor is ignored, and the single
        selection will be wrapped.
        */
        if (text.length !== 0 && text.indexOf('\n') === -1) {
          const wrappedText = this.wrapText(text, token)
          editor.setTextInBufferRange(range, wrappedText)
          didSomeWrapping = true
        }
      }
    }
    if (!didSomeWrapping) {
      event.abortKeyBinding()
    }
    return
  },

  // TODO: Doesn't place the cursor at the right position afterwards
  linkSelection (event, isImage = false) {
    let didSomeWrapping = false

    if (!atom.config.get('language-markdown.linkShortcuts')) {
      event.abortKeyBinding()
      return
    }

    const editor = atom.workspace.getActiveTextEditor()
    if (!editor) return

    const ranges = this.getSelectedBufferRangesReversed(editor)
    const cursorOffsets = []
    for (const range of ranges) {
      const text = editor.getTextInBufferRange(range)
      // See {emphasizeSelection}
      if (text.length !== 0 && text.indexOf('\n') === -1) {
        const imageToken = isImage ? '!' : ''
        if (text.match(/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/)) {
          const newText = `${imageToken}[](${text})`
          editor.setTextInBufferRange(range, newText)
          cursorOffsets.push(text.length + 3)
        } else {
          const newText = `${imageToken}[${text}]()`
          editor.setTextInBufferRange(range, newText)
          cursorOffsets.push(1)
        }
        didSomeWrapping = true
      }
    }

    if (didSomeWrapping) {
      /*
      Cursors aren't separate entities, but rather simple {Point}s, ie,
      positions in the buffer. There is no way of updating a cursor. Instead,
      we clear all cursors, and then re-create them from where our current
      selections are.

      After the image/link wrapping above, the cursor are positioned after the
      selections, and the desired relative locations for the new cursors are
      stored in {cursorOffsets}. We only need to loop through the current
      selections, and create a new cursor for every selection.

      A selection without a length is a simple cursor that can be re-created at
      that exact location.

      TODO: maybe one of those fancy generators can be used for our
      cursorOffsets?
      */
      const selections = editor.getSelectedBufferRanges()
      let count = 0
      let offsetCount = 0
      for (const selection of selections) {
        const { start, end } = selection
        if ((start.row === end.row) && (start.column === end.column)) {
          if (count) {
            editor.addCursorAtBufferPosition(start)
          } else {
            editor.setCursorBufferPosition(start)
          }
        } else {
          const position = {
            row: end.row,
            column: end.column - cursorOffsets[offsetCount]
          }
          if (count) {
            editor.addCursorAtBufferPosition(position)
          } else {
            editor.setCursorBufferPosition(position)
          }
          offsetCount++
        }
        count++;
      }
    } else {
      event.abortKeyBinding()
    }

    return
  },

  _getEditorAndPosition (event) {
    const editor = atom.workspace.getActiveTextEditor()
    if (editor) {
      const positions = editor.getCursorBufferPositions()
      if (positions) {
        const position = positions[0]
        return { editor, position }
      }
    }
    event.abortKeyBinding()
  },

  toggleTask (event) {
    const editor = atom.workspace.getActiveTextEditor()
    if (!editor) {
      event.abortKeyBinding()
      return
    }

    const ranges = editor.getSelectedBufferRanges()
    for (const range of ranges) {
      const { start, end } = range
      for (let row = start.row; row <= end.row; row++) {
        const listItem = this.isListItem(editor, [row, 0])
        if (listItem && listItem.includes('task')) {
          const currentLine = editor.lineTextForBufferRow(row)
          let newLine
          if (listItem.includes('completed')) {
            newLine = currentLine.replace(/ \[(x|X)\] /, ' [ ] ')
          } else {
            newLine = currentLine.replace(' [ ] ', ' [x] ')
          }
          const newRange = [[row, 0], [row, newLine.length]]
          editor.setTextInBufferRange(newRange, newLine)
        }
      }
    }
    return
  },

  isListItem (editor, position) {
    if (editor) {
      if (editor.getGrammar().name === 'Markdown') {
        const scopeDescriptor = editor.scopeDescriptorForBufferPosition(position)
        for (const scope of scopeDescriptor.scopes) {
          if (scope.includes('list')) {
            /*
            Return {scope}, which evaluates as {true} and can be used by other
            functions to determine the type of list-item
            */
            return scope;
          }
        }
      }
    }
    return false
  },

  wrapText (text, token) {
    const length = token.length
    if ((text.substr(0, length) === token) && (text.substr(-length) === token)) {
      return text.substr(length, text.length - length * 2)
    } else {
      return token + text + token
    }
  },

  isEmbeddedCode (editor, range) {
    const scopeDescriptor = editor.scopeDescriptorForBufferPosition(range.end)
    for (const scope of scopeDescriptor.scopes) {
      if (scope.includes('source')) return true
    }
    return false
  },

  /*
  Selection are returned in the reverse order that they were created by the
  user. We need them in the reverse order that they appear in the document,
  because we don't need a previous changes selection changing the buffer
  position of our selections.
  */
  getSelectedBufferRangesReversed (editor) {
    const ranges = editor.getSelectedBufferRanges()
    ranges.sort(function(a, b) {
      if (a.start.row > b.start.row) return -1
      if (b.start.row > a.start.row) return 1
      if (a.start.column > b.start.column) return -1
      return 1
    })
    return ranges
  },

  compileGrammar () {
    if (atom.inDevMode()) {
      const compiler = new GrammarCompiler()
      compiler.compile()
    }
  }
}
<commit_msg>updated default value for autoIncrementListItem<commit_after>'use babel'

import { CompositeDisposable, Directory } from 'atom'
// import { isListItem, wrapText } from './functions'

CSON = require('season')
fs = require('fs')
GrammarCompiler = require('./GrammarCompiler')
path = require('path')

module.exports = {
  config: {
    addListItems: {
      title: 'Add new list-items',
      description: 'Automatically add a new list-item after the current (non-empty) one when pressing ENTER',
      type: 'boolean',
      default: true
    },

    autoIncrementListItems: {
        title: 'Increment Ordered List Items',
        description: 'Automatically increment a new list-item after the current(non-empty) one when pressing ENTER',
        type: 'boolean',
        default: true
    },

    disableLanguageGfm: {
      title: 'Disable language-gfm',
      description: 'Disable the default `language-gfm` package as this package is intended as its replacement',
      type: 'boolean',
      default: true
    },

    emphasisShortcuts: {
      title: 'Emphasis shortcuts',
      description: 'Enables keybindings `_` for emphasis, `*` for strong emphasis, and `~` for strike-through on selected text; emphasizing an already emphasized selection will de-emphasize it',
      type: 'boolean',
      default: true
    },

    indentListItems: {
      title: 'Indent list-items',
      description: 'Automatically in- and outdent list-items by pressing `TAB` and `SHIFT+TAB`',
      type: 'boolean',
      default: true
    },

    linkShortcuts: {
      title: 'Link shortcuts',
      description: 'Enables keybindings `@` for converting the selected text to a link and `!` for converting the selected text to an image',
      type: 'boolean',
      default: true
    },

    removeEmptyListItems: {
      title: 'Remove empty list-items',
      description: 'Remove the automatically created empty list-items when left empty, leaving an empty line',
      type: 'boolean',
      default: true
    }
  },

  subscriptions: null,

  activate (state) {
    this.subscriptions = new CompositeDisposable()
    this.addCommands()

    /*
    Unless you are an advanced user, there is no need to have both this package
    and the one it replaces (language-gfm) enabled.

    If you are an advanced user, you can easily re-enable language-gfm again.
    */
    if (atom.config.get('language-markdown.disableLanguageGfm')) {
      if (!atom.packages.isPackageDisabled('language-gfm')) {
        atom.packages.disablePackage('language-gfm')
      }
    }

    /*
    I forgot why this action is created inline in activate() and not as a
    separate method, but there was a good reason for it.
    */
    this.subscriptions.add(atom.workspace.observeTextEditors(editor => {
      editor.onDidInsertText(event => {
        const grammar = editor.getGrammar()

        if (grammar.name !== 'Markdown') return
        if (!atom.config.get('language-markdown.addListItems')) return
        if (event.text !== '\n') return

        /*
        At this point, it is rather tedious (as far as I know) to get to the
        tokenized version of {previousLine}. That is the reason why {tokens} a
        little further down is tokenized. But at this stage, we do need to know
        if {previousLine} was in fact Markdown, or from a different perspective,
        not a piece of embedded code. The reason for that is that the tokenized
        line below is tokenized without any context, so is Markdown by default.
        Therefore we determine if our current position is part of embedded code
        or not.
        */

        const previousRowNumber = event.range.start.row
        const previousRowRange = editor.buffer.rangeForRow(previousRowNumber)
        if (this.isEmbeddedCode(editor, previousRowRange)) return

        const previousLine = editor.getTextInRange(previousRowRange)
        let { tokens } = grammar.tokenizeLine(previousLine)
        tokens.reverse()
        for (const token of tokens) {
          let isPunctuation = false
          let isListItem = false
          let typeOfList

          const scopes = token.scopes.reverse()
          for (const scope of scopes) {
            const classes = scope.split('.')

            /*
            A list-item is valid when a punctuation class is immediately
            followed by a non-empty list-item class.
            */
            if (classes.includes('punctuation')) {
              isPunctuation = true
            } else if (isPunctuation && classes.includes('list')) {
              if (!classes.includes('empty')) {
                isListItem = true
                typeOfList = 'unordered'
                if (classes.includes('ordered')) {
                  typeOfList = 'ordered'
                }
                if (classes.includes('definition')) {
                  typeOfList = 'definition'
                }
                break
              } else {
                isListItem = false
                isPunctuation = false
                if (atom.config.get('language-markdown.removeEmptyListItems')) {
                  editor.setTextInBufferRange(previousRowRange, '')
                }
              }
            } else {
              isPunctuation = false
            }
          }

          if (isListItem && typeOfList !== 'definition') {
            let text = token.value
            if (typeOfList === 'ordered') {
              const length = text.length
              const punctuation = text.match(/[^\d]+/)
              var value = parseInt(text)
              if (atom.config.get('language-markdown.autoIncrementListItems')) {
                  value = value + 1
              }
              text = value + punctuation
              if (text.length < length) {
                for (let j = 0; j < text.length - length + 1; j++) {
                  text = '0' + text
                }
              }
            } else {
              text = text.replace('x', ' ')
            }
            editor.insertText(text + '')
            break
          }
        }
      })
    }))
  },

  addCommands () {
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:indent-list-item', (event) => this.indentListItem(event)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:outdent-list-item', (event) => this.outdentListItem(event)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:emphasis', (event) => this.emphasizeSelection(event, '_')))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:strong-emphasis', (event) => this.emphasizeSelection(event, '**')))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:strike-through', (event) => this.emphasizeSelection(event, '~~')))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:link', (event) => this.linkSelection(event)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:image', (event) => this.linkSelection(event, true)))
    this.subscriptions.add(atom.commands.add('atom-text-editor', 'markdown:toggle-task', (event) => this.toggleTask(event)))

    if (atom.inDevMode()) {
      this.subscriptions.add(atom.commands.add('atom-workspace', 'markdown:compile-grammar-and-reload', () => this.compileGrammar()))
    }
  },

  indentListItem (event) {
    const { editor, position } = this._getEditorAndPosition(event)
    const indentListItems = atom.config.get('language-markdown.indentListItems')
    if (indentListItems && this.isListItem(editor, position)) {
      editor.indentSelectedRows(position.row)
      return
    }
    event.abortKeyBinding()
  },

  outdentListItem (event) {
    const { editor, position } = this._getEditorAndPosition(event)
    const indentListItems = atom.config.get('language-markdown.indentListItems')
    if (indentListItems && this.isListItem(editor, position)) {
      editor.outdentSelectedRows(position.row)
      return
    }
    event.abortKeyBinding()
  },

  emphasizeSelection (event, token) {
    let didSomeWrapping = false
    if (atom.config.get('language-markdown.emphasisShortcuts')) {
      const editor = atom.workspace.getActiveTextEditor()
      if (!editor) return

      const ranges = this.getSelectedBufferRangesReversed(editor)
      for (const range of ranges) {
        const text = editor.getTextInBufferRange(range)
        /*
        Skip texts that contain a line-break, or are empty.
        Multi-line emphasis is not supported 'anyway'.

        If afterwards not a single selection has been wrapped, cancel the event
        and insert the character as normal.

        If two cursors were found, but only one of them was a selection, and the
        other a normal cursor, then the normal cursor is ignored, and the single
        selection will be wrapped.
        */
        if (text.length !== 0 && text.indexOf('\n') === -1) {
          const wrappedText = this.wrapText(text, token)
          editor.setTextInBufferRange(range, wrappedText)
          didSomeWrapping = true
        }
      }
    }
    if (!didSomeWrapping) {
      event.abortKeyBinding()
    }
    return
  },

  // TODO: Doesn't place the cursor at the right position afterwards
  linkSelection (event, isImage = false) {
    let didSomeWrapping = false

    if (!atom.config.get('language-markdown.linkShortcuts')) {
      event.abortKeyBinding()
      return
    }

    const editor = atom.workspace.getActiveTextEditor()
    if (!editor) return

    const ranges = this.getSelectedBufferRangesReversed(editor)
    const cursorOffsets = []
    for (const range of ranges) {
      const text = editor.getTextInBufferRange(range)
      // See {emphasizeSelection}
      if (text.length !== 0 && text.indexOf('\n') === -1) {
        const imageToken = isImage ? '!' : ''
        if (text.match(/[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/)) {
          const newText = `${imageToken}[](${text})`
          editor.setTextInBufferRange(range, newText)
          cursorOffsets.push(text.length + 3)
        } else {
          const newText = `${imageToken}[${text}]()`
          editor.setTextInBufferRange(range, newText)
          cursorOffsets.push(1)
        }
        didSomeWrapping = true
      }
    }

    if (didSomeWrapping) {
      /*
      Cursors aren't separate entities, but rather simple {Point}s, ie,
      positions in the buffer. There is no way of updating a cursor. Instead,
      we clear all cursors, and then re-create them from where our current
      selections are.

      After the image/link wrapping above, the cursor are positioned after the
      selections, and the desired relative locations for the new cursors are
      stored in {cursorOffsets}. We only need to loop through the current
      selections, and create a new cursor for every selection.

      A selection without a length is a simple cursor that can be re-created at
      that exact location.

      TODO: maybe one of those fancy generators can be used for our
      cursorOffsets?
      */
      const selections = editor.getSelectedBufferRanges()
      let count = 0
      let offsetCount = 0
      for (const selection of selections) {
        const { start, end } = selection
        if ((start.row === end.row) && (start.column === end.column)) {
          if (count) {
            editor.addCursorAtBufferPosition(start)
          } else {
            editor.setCursorBufferPosition(start)
          }
        } else {
          const position = {
            row: end.row,
            column: end.column - cursorOffsets[offsetCount]
          }
          if (count) {
            editor.addCursorAtBufferPosition(position)
          } else {
            editor.setCursorBufferPosition(position)
          }
          offsetCount++
        }
        count++;
      }
    } else {
      event.abortKeyBinding()
    }

    return
  },

  _getEditorAndPosition (event) {
    const editor = atom.workspace.getActiveTextEditor()
    if (editor) {
      const positions = editor.getCursorBufferPositions()
      if (positions) {
        const position = positions[0]
        return { editor, position }
      }
    }
    event.abortKeyBinding()
  },

  toggleTask (event) {
    const editor = atom.workspace.getActiveTextEditor()
    if (!editor) {
      event.abortKeyBinding()
      return
    }

    const ranges = editor.getSelectedBufferRanges()
    for (const range of ranges) {
      const { start, end } = range
      for (let row = start.row; row <= end.row; row++) {
        const listItem = this.isListItem(editor, [row, 0])
        if (listItem && listItem.includes('task')) {
          const currentLine = editor.lineTextForBufferRow(row)
          let newLine
          if (listItem.includes('completed')) {
            newLine = currentLine.replace(/ \[(x|X)\] /, ' [ ] ')
          } else {
            newLine = currentLine.replace(' [ ] ', ' [x] ')
          }
          const newRange = [[row, 0], [row, newLine.length]]
          editor.setTextInBufferRange(newRange, newLine)
        }
      }
    }
    return
  },

  isListItem (editor, position) {
    if (editor) {
      if (editor.getGrammar().name === 'Markdown') {
        const scopeDescriptor = editor.scopeDescriptorForBufferPosition(position)
        for (const scope of scopeDescriptor.scopes) {
          if (scope.includes('list')) {
            /*
            Return {scope}, which evaluates as {true} and can be used by other
            functions to determine the type of list-item
            */
            return scope;
          }
        }
      }
    }
    return false
  },

  wrapText (text, token) {
    const length = token.length
    if ((text.substr(0, length) === token) && (text.substr(-length) === token)) {
      return text.substr(length, text.length - length * 2)
    } else {
      return token + text + token
    }
  },

  isEmbeddedCode (editor, range) {
    const scopeDescriptor = editor.scopeDescriptorForBufferPosition(range.end)
    for (const scope of scopeDescriptor.scopes) {
      if (scope.includes('source')) return true
    }
    return false
  },

  /*
  Selection are returned in the reverse order that they were created by the
  user. We need them in the reverse order that they appear in the document,
  because we don't need a previous changes selection changing the buffer
  position of our selections.
  */
  getSelectedBufferRangesReversed (editor) {
    const ranges = editor.getSelectedBufferRanges()
    ranges.sort(function(a, b) {
      if (a.start.row > b.start.row) return -1
      if (b.start.row > a.start.row) return 1
      if (a.start.column > b.start.column) return -1
      return 1
    })
    return ranges
  },

  compileGrammar () {
    if (atom.inDevMode()) {
      const compiler = new GrammarCompiler()
      compiler.compile()
    }
  }
}
<|endoftext|>


<commit_before>import { Application } from 'ember';
import autocompleteCss from './templates/autocomplete-css';
import autocompleteTemplate from './templates/autocomplete';
import AutocompleteComponent from './autocomplete';
import AutocompleteOptionComponent from './autocomplete-option';
import AutocompleteToggleComponent from './autocomplete-toggle';
import AutocompleteInputComponent from './autocomplete-input';
import AutocompleteListComponent from './autocomplete-list';

Application.initializer({
  name: 'ic-modal',
  initialize: function(container) {
    container.register('template:components/ic-autocomplete', autocompleteTemplate);
    container.register('template:components/ic-autocomplete-css', autocompleteCss);
    container.register('component:ic-autocomplete', AutocompleteComponent);
    container.register('component:ic-autocomplete-option', AutocompleteOptionComponent);
    container.register('component:ic-autocomplete-toggle', AutocompleteToggleComponent);
    container.register('component:ic-autocomplete-input', AutocompleteInputComponent);
    container.register('component:ic-autocomplete-list', AutocompleteListComponent);
  }
});

export {
  autocompleteCss,
  autocompleteTemplate,
  AutocompleteComponent,
  AutocompleteOptionComponent,
  AutocompleteToggleComponent,
  AutocompleteInputComponent,
  AutocompleteListComponent
};

<commit_msg>[fixed] initializer name<commit_after>import { Application } from 'ember';
import autocompleteCss from './templates/autocomplete-css';
import autocompleteTemplate from './templates/autocomplete';
import AutocompleteComponent from './autocomplete';
import AutocompleteOptionComponent from './autocomplete-option';
import AutocompleteToggleComponent from './autocomplete-toggle';
import AutocompleteInputComponent from './autocomplete-input';
import AutocompleteListComponent from './autocomplete-list';

Application.initializer({
  name: 'ic-autocomplete',
  initialize: function(container) {
    container.register('template:components/ic-autocomplete', autocompleteTemplate);
    container.register('template:components/ic-autocomplete-css', autocompleteCss);
    container.register('component:ic-autocomplete', AutocompleteComponent);
    container.register('component:ic-autocomplete-option', AutocompleteOptionComponent);
    container.register('component:ic-autocomplete-toggle', AutocompleteToggleComponent);
    container.register('component:ic-autocomplete-input', AutocompleteInputComponent);
    container.register('component:ic-autocomplete-list', AutocompleteListComponent);
  }
});

export {
  autocompleteCss,
  autocompleteTemplate,
  AutocompleteComponent,
  AutocompleteOptionComponent,
  AutocompleteToggleComponent,
  AutocompleteInputComponent,
  AutocompleteListComponent
};

<|endoftext|>


<commit_before>'use strict'

var fs = require('fs')

module.exports = {
  /*
   * Main entry point into dotenv. Allows configuration before loading .env and .env.$NODE_ENV
   * @param {Object} options - valid options: path ('.env'), encoding ('utf8')
   * @returns {Boolean}
  */
  config: function (options) {
    var path = '.env'
    var encoding = 'utf8'
    var silent = false

    if (options) {
      if (options.path) {
        path = options.path
      }
      if (options.encoding) {
        encoding = options.encoding
      }
      if (options.silent) {
        silent = options.silent
      }
    }

    try {
      // specifying an encoding returns a string instead of a buffer
      var parsedObj = this.parse(fs.readFileSync(path, { encoding: encoding }))

      Object.keys(parsedObj).forEach(function (key) {
        process.env[key] = process.env[key] || parsedObj[key]
      })

      return true
    } catch(e) {
      if (!silent) {
        console.error(e)
      }
      return false
    }
  },

  /*
   * Parses a string or buffer into an object
   * @param {String|Buffer} src - source to be parsed
   * @returns {Object}
  */
  parse: function (src) {
    var obj = {}

    // convert Buffers before splitting into lines and processing
    src.toString().split('\n').forEach(function (line) {
      // matching "KEY' and 'VAL' in 'KEY=VAL'
      var keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/)
      // matched?
      if (keyValueArr != null) {
        var key = keyValueArr[1]

        // default undefined or missing values to empty string
        var value = keyValueArr[2] ? keyValueArr[2] : ''

        // expand newlines in quoted values
        var len = value ? value.length : 0
        if (len > 0 && value.charAt(0) === '\"' && value.charAt(len - 1) === '\"') {
          value = value.replace(/\\n/gm, '\n')
        }

        // remove any surrounding quotes and extra spaces
        value = value.replace(/(^['"]|['"]$)/g, '').trim()

        // is this value a variable?
        if (value.charAt(0) === '$') {
          var possibleVar = value.substring(1)
          value = obj[possibleVar] || process.env[possibleVar] || ''
        }
        // varaible can be escaped with a \$
        if (value.substring(0, 2) === '\\$') {
          value = value.substring(1)
        }

        obj[key] = value
      }
    })

    return obj
  }

}

module.exports.load = module.exports.config
<commit_msg>Match order to match README order<commit_after>'use strict'

var fs = require('fs')

module.exports = {
  /*
   * Main entry point into dotenv. Allows configuration before loading .env and .env.$NODE_ENV
   * @param {Object} options - valid options: path ('.env'), encoding ('utf8')
   * @returns {Boolean}
  */
  config: function (options) {
    var path = '.env'
    var encoding = 'utf8'
    var silent = false

    if (options) {
      if (options.silent) {
        silent = options.silent
      }
      if (options.path) {
        path = options.path
      }
      if (options.encoding) {
        encoding = options.encoding
      }
    }

    try {
      // specifying an encoding returns a string instead of a buffer
      var parsedObj = this.parse(fs.readFileSync(path, { encoding: encoding }))

      Object.keys(parsedObj).forEach(function (key) {
        process.env[key] = process.env[key] || parsedObj[key]
      })

      return true
    } catch(e) {
      if (!silent) {
        console.error(e)
      }
      return false
    }
  },

  /*
   * Parses a string or buffer into an object
   * @param {String|Buffer} src - source to be parsed
   * @returns {Object}
  */
  parse: function (src) {
    var obj = {}

    // convert Buffers before splitting into lines and processing
    src.toString().split('\n').forEach(function (line) {
      // matching "KEY' and 'VAL' in 'KEY=VAL'
      var keyValueArr = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/)
      // matched?
      if (keyValueArr != null) {
        var key = keyValueArr[1]

        // default undefined or missing values to empty string
        var value = keyValueArr[2] ? keyValueArr[2] : ''

        // expand newlines in quoted values
        var len = value ? value.length : 0
        if (len > 0 && value.charAt(0) === '\"' && value.charAt(len - 1) === '\"') {
          value = value.replace(/\\n/gm, '\n')
        }

        // remove any surrounding quotes and extra spaces
        value = value.replace(/(^['"]|['"]$)/g, '').trim()

        // is this value a variable?
        if (value.charAt(0) === '$') {
          var possibleVar = value.substring(1)
          value = obj[possibleVar] || process.env[possibleVar] || ''
        }
        // varaible can be escaped with a \$
        if (value.substring(0, 2) === '\\$') {
          value = value.substring(1)
        }

        obj[key] = value
      }
    })

    return obj
  }

}

module.exports.load = module.exports.config
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var {Cc, Ci} = require("chrome");
var prefs = require("sdk/preferences/service");

const KEY_PREFIX = "browser.contentHandlers.types.";

const TITLE_KEY = ".title";
const TYPE_KEY = ".type";
const URI_KEY = ".uri";

const TITLE_VAL = "Feedly Cloud";
const TYPE_VAL = "application/vnd.mozilla.maybe.feed";
const URI_VAL = "https://cloud.feedly.com/#subscription/feed/%s"

const AUTO_KEY = "browser.contentHandlers.auto.application/vnd.mozilla.maybe.feed";

exports.main = function (options, callbacks) {
  if (options.loadReason !== "startup") {
    // Register the handler so it'll take effect without restarting
    Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"]
      .getService(Ci.nsIWebContentHandlerRegistrar)
      .registerContentHandler(TYPE_VAL, URI_VAL, TITLE_VAL, null);
  }
};

exports.onUnload = function (reason) {
  var handlerFound = false;
  var handlerNumber = -1;
  var handlerTitle;

  if (reason !== "shutdown") {
    while (!handlerFound) {
      handlerNumber++;
      handlerTitle = prefs.get(KEY_PREFIX + handlerNumber + TITLE_KEY);
      if (!handlerTitle) {
        break;
      }
      handlerFound = handlerTitle === TITLE_VAL;
    }

    if (handlerFound) {
      // Remove the prefs, otherwise if it gets re-enabled this session it'll
      // keep incrementing the content handler number when it registers
      prefs.reset(KEY_PREFIX + handlerNumber + TITLE_KEY);
      prefs.reset(KEY_PREFIX + handlerNumber + TYPE_KEY);
      prefs.reset(KEY_PREFIX + handlerNumber + URI_KEY);

      // If it's set as the "always use", clear that.
      // TODO: Figure out how to make this work without a restart
      if (prefs.get(AUTO_KEY) === URI_VAL) {
        prefs.reset(AUTO_KEY);
      }

      // Unregister the handler, so it'll take effect without restarting
      Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"]
        .getService(Ci.nsIWebContentConverterService)
        .removeContentHandler(TYPE_VAL, URI_VAL);
    }
  }
};
<commit_msg>Feedly's subscription point was changed.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var {Cc, Ci} = require("chrome");
var prefs = require("sdk/preferences/service");

const KEY_PREFIX = "browser.contentHandlers.types.";

const TITLE_KEY = ".title";
const TYPE_KEY = ".type";
const URI_KEY = ".uri";

const TITLE_VAL = "Feedly Cloud";
const TYPE_VAL = "application/vnd.mozilla.maybe.feed";
const URI_VAL = "https://feedly.com/i/spotlight/%s"

const AUTO_KEY = "browser.contentHandlers.auto.application/vnd.mozilla.maybe.feed";

exports.main = function (options, callbacks) {
  if (options.loadReason !== "startup") {
    // Register the handler so it'll take effect without restarting
    Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"]
      .getService(Ci.nsIWebContentHandlerRegistrar)
      .registerContentHandler(TYPE_VAL, URI_VAL, TITLE_VAL, null);
  }
};

exports.onUnload = function (reason) {
  var handlerFound = false;
  var handlerNumber = -1;
  var handlerTitle;

  if (reason !== "shutdown") {
    while (!handlerFound) {
      handlerNumber++;
      handlerTitle = prefs.get(KEY_PREFIX + handlerNumber + TITLE_KEY);
      if (!handlerTitle) {
        break;
      }
      handlerFound = handlerTitle === TITLE_VAL;
    }

    if (handlerFound) {
      // Remove the prefs, otherwise if it gets re-enabled this session it'll
      // keep incrementing the content handler number when it registers
      prefs.reset(KEY_PREFIX + handlerNumber + TITLE_KEY);
      prefs.reset(KEY_PREFIX + handlerNumber + TYPE_KEY);
      prefs.reset(KEY_PREFIX + handlerNumber + URI_KEY);

      // If it's set as the "always use", clear that.
      // TODO: Figure out how to make this work without a restart
      if (prefs.get(AUTO_KEY) === URI_VAL) {
        prefs.reset(AUTO_KEY);
      }

      // Unregister the handler, so it'll take effect without restarting
      Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"]
        .getService(Ci.nsIWebContentConverterService)
        .removeContentHandler(TYPE_VAL, URI_VAL);
    }
  }
};
<|endoftext|>


<commit_before>
//...........................................
// Server Initialization/Setup
//
// Include all of the necessary modules and ensure that
// they will be available throughout the application
// by adding them to the xt namespace.

/** @lends xt */  require('./xt');

// once bootstrapper is complete the framework is up
// and running and procedures can continue...

// load the data server
require('./xt/runtime/dataserver');

// load the devUI server
require('./xt/runtime/devui');

// load the ORM installer interface
require('./xt/runtime/orm');

// load the model generator
require('./xt/runtime/model_generator');

// load the log user interface
require('./xt/runtime/logui');
<commit_msg>add back original build tools<commit_after>
//...........................................
// Server Initialization/Setup
//
// Include all of the necessary modules and ensure that
// they will be available throughout the application
// by adding them to the xt namespace.

/** @lends xt */  require('./xt');

// once bootstrapper is complete the framework is up
// and running and procedures can continue...

// load the data server
require('./xt/runtime/dataserver');

// load the devUI server
require('./xt/runtime/devui');

// load the ORM installer interface
require('./xt/runtime/orm');

// load the model generator
require('./xt/runtime/model_generator');

// load the log user interface
require('./xt/runtime/logui');

require('./xt/runtime/builder');
<|endoftext|>


<commit_before>'use babel';
/* globals atom */

import { execSync } from 'child_process';
import { CompositeDisposable } from 'atom';
import { parseString } from 'xml2js';
import _ from 'underscore';

const linterPackage = atom.packages.getLoadedPackage('linter');
if (!linterPackage) {
  atom.notifications.addError('Linter should be installed first, `apm install linter`', {
    dismissable: true,
  });
}

export default {
  config: {
    cflintPath: {
      type: 'string',
      'default': '',
      description: 'Path to cflint-all.jar',
    },
    javaPath: {
      type: 'string',
      'default': '',
      description: 'Path to Java 7+ executable (JRE or JDK)',
    },
  },

  activate: () => {
    require('atom-package-deps').install('language-cfml');
    require('atom-package-deps').install('linter-cflint');
    this.subscriptions = new CompositeDisposable;
  },

  deactivate: () => {
    return this.subscriptions.dispose();
  },

  provideLinter: () => {
    return {
      name: 'cflint',
      grammarScopes: ['text.html.cfml', 'source.cfscript.embedded', 'punctuation.definition.tag.cfml'],
      scope: 'file',
      lintOnFly: false,
      lint: (textEditor) => {
        return new Promise(resolve => {
          const cflintPath = atom.config.get('linter-cflint.cflintPath');
          const javaPath = atom.config.get('linter-cflint.javaPath');
          const filePath = textEditor.getPath();
          const errorMessage = {type: 'Error', text: 'Something went wrong', range: [[0, 0], [0, 1]], filePath: textEditor.getPath()};
          let lintXML = execSync(
            '"' + javaPath + '" -jar "' + cflintPath + '" '
                + '-file "' + filePath + '"',
            {stdio: 'pipe', encoding: 'utf8'});
          if (lintXML.trim()[0] !== '<') {
            lintXML = lintXML.split('\n').slice(1).join('\n');
          }
          parseString(lintXML, (err, result) => {
            if (err) {
              errorMessage.text = err;
              resolve([errorMessage]);
            }
            const messages = _.chain(result.issues.issue).pluck('location').flatten().map(location => {
              const line = parseInt(location.$.line, 10) - 1;
              const column = parseInt(location.$.column, 10) - 1;
              return {
                type: 'Error', // TODO: get the severity
                text: location.$.message,
                filePath: location.$.file,
                range: [[line, column], [line, column]], // TODO: Expression has the specifics
              };
            }).value();
            resolve(messages);
          });
          resolve([errorMessage]);
        });
      },
    };
  },
};
<commit_msg>Fixed line sorting<commit_after>'use babel';
/* globals atom */

import { execSync } from 'child_process';
import { CompositeDisposable } from 'atom';
import { parseString } from 'xml2js';
import _ from 'underscore';

const linterPackage = atom.packages.getLoadedPackage('linter');
if (!linterPackage) {
  atom.notifications.addError('Linter should be installed first, `apm install linter`', {
    dismissable: true,
  });
}

export default {
  config: {
    cflintPath: {
      type: 'string',
      'default': '',
      description: 'Path to cflint-all.jar',
    },
    javaPath: {
      type: 'string',
      'default': '',
      description: 'Path to Java 7+ executable (JRE or JDK)',
    },
  },

  activate: () => {
    require('atom-package-deps').install('language-cfml');
    require('atom-package-deps').install('linter-cflint');
    this.subscriptions = new CompositeDisposable;
  },

  deactivate: () => {
    return this.subscriptions.dispose();
  },

  provideLinter: () => {
    return {
      name: 'cflint',
      grammarScopes: ['text.html.cfml', 'source.cfscript.embedded', 'punctuation.definition.tag.cfml'],
      scope: 'file',
      lintOnFly: false,
      lint: (textEditor) => {
        return new Promise(resolve => {
          const cflintPath = atom.config.get('linter-cflint.cflintPath');
          const javaPath = atom.config.get('linter-cflint.javaPath');
          const filePath = textEditor.getPath();
          const errorMessage = {type: 'Error', text: 'Something went wrong', range: [[0, 0], [0, 1]], filePath: textEditor.getPath()};
          let lintXML = execSync(
            '"' + javaPath + '" -jar "' + cflintPath + '" '
                + '-file "' + filePath + '"',
            {stdio: 'pipe', encoding: 'utf8'});
          if (lintXML.trim()[0] !== '<') {
            lintXML = lintXML.split('\n').slice(1).join('\n');
          }
          parseString(lintXML, (err, result) => {
            if (err) {
              errorMessage.text = err;
              resolve([errorMessage]);
            }
            const messages =
              _.chain(result.issues.issue)
              .pluck('location')
              .flatten()
              .sortBy(location => parseInt(location.$.line, 10))
              .map(location => {
                const line = parseInt(location.$.line, 10) - 1;
                const column = parseInt(location.$.column, 10) - 1;
                return {
                  type: 'Error', // TODO: get the severity
                  text: location.$.message,
                  filePath: location.$.file,
                  line: line,
                  range: [[line, column], [line, column]], // TODO: Expression has the specifics
                };
              })
              .value();
            resolve(messages);
          });
          resolve([errorMessage]);
        });
      },
    };
  },
};
<|endoftext|>


<commit_before>var _ = require('lodash'),
  Kramed = require('./kramed'),
  Renderer = new Kramed.Renderer();

// Parser Opts
Kramed.setOptions({
  renderer: Renderer,
  gfm: true,
  tables: true,
  breaks: false,
  pedantic: false,
  sanitize: true,
  smartLists: true,
  smartypants: false
});

/**
 * Encode non-alpha string - HTML
 * return: string
 *
*/
function HTMLEncode(str){
  var i = str.length,
      aRet = [];

  while (i--) {
    var iC = str[i].charCodeAt();
    if (iC < 65 || iC > 127 || (iC>90 && iC<97)) {
      aRet[i] = '&#'+iC+';';
    } else {
      aRet[i] = str[i];
    }
   }
  return aRet.join('');
}

function parseClass(text) {

	var str = text.split(' ');
  var cls = "";
  var style = null;
  var pos = null;

  switch(str[0]) {

    case 'fullscreen':
      cls = 'fullscreen';
      break;

    case 'fit':
      cls = "fit";
      break;

    case 'left':
      cls = "left";
			str.shift();
      style = str.join('');
      break;

    case 'right':
      cls = "right";
			str.shift();
      style = str.join('');
      break;

    case 'top':
			cls = "top";
			str.shift();
			style = str.join('');
			break;

	  case 'bottom':
			cls = "bottom";
			str.shift();
			style = str.join('');
			break;

    case 'css':
      str.shift();
      style = str.join(' ');
      break;

    default:
      cls = str[0];
  }

	if (Renderer.ponyoptions.shadows) {
    cls = cls+" shadow";
  }

	return {
		cls: cls,
		style: style
	}

}

;(function() {

/**
 * Markdown to Shower
 * return: string
 *
*/

function Pony(options) {

  var self = this;

  var options = options || {};

  self.debug = options.debug||false;

  self.version = require('../package.json').version;

  self.heading = (options.heading) ? options.heading : [];
  self.sections = (options.sections) ? options.sections : 0;
  self.hideSlideNumbers = (options.hideSlideNumbers) ? options.hideSlideNumbers : "";
  self.hrc = (options.hrc) ? options.hrc : [];

  self.error = (options.error) ? options.error : "

Rendering error

";

  self.header = options.header;
  self.footer = options.footer;

  self._theme = false;
  self.isPonyFile = false;

  Renderer.ponyoptions = {
    format: "",
    slidenumbers: true,
    footer: 'Pony Show',
    timing:false,
    progress:true,
    transition:false,
    shadows:false
  };

  Renderer.list = function(body, ordered) {
    var type = ordered ? 'ol' : 'ul', out="", cls="";

    out = '<' + type + '>\n' + body + '</' + type + '>\n';

    if (self.sections > 0 || !self.isPonyFile) {
      return out;
    } else {
      self.heading.push(out);
      return '';
    }
  };

  Renderer.listitem = function(text) {
    var cls="";
    if (Renderer.ponyoptions.buildLists) {
      cls = "next";
    }

    return '
' + text + '
\n';
  }

  Renderer.hr = function(cls,id) {
    var out = null;
    var timing = false;

    // set format for each section
    if (Renderer.ponyoptions.format) {
      cls = Renderer.ponyoptions.format + " " + cls;
    }

    // Set timing option
    if (Renderer.ponyoptions.timing) {
      timing = 'data-timing="'+Renderer.ponyoptions.timing+'"';
    }

    if (self.sections == 0) {

      // heading
      if (self.heading.length > 0) {
        out = self.heading.join('') + "\n";
      }

      out = out+"\n
\n
\n";
    } else {

      if (self.sections == self.hrc.length) {
        out = "\n
\n
\n";
      } else {
        out = "
\n
\n\n
\n
\n";
      }
    }

    self.sections++;

    return out||"";
  }

  Renderer.heading = function (text, level) {
    var out = false;

    // var str = text.split('[');
    // var style = null;
    //
    // switch(str[0]) {
    //   case 'absolute':
    //     str.shift();
    //     style = str.join('');
    //     break;
    //
    //   default:
    // }

    if (self.sections == 0 && self.heading.length == 0 && self.isPonyFile) {
      self.heading.push('\n');
      self.heading.push('<h' + level + '>' + text + '</h' + level + '>\n');
    } else if (self.sections == 0 && self.isPonyFile && (self.heading.length > 1)) {
      self.heading.push('<h' + level + '>' + text + '</h' + level + '>\n');
    } else {
      // default
      out = '<h' + level + ' class="fit">' + text + '</h' + level + '>\n';
    }

    return (out) ? out : "";
  };

  Renderer.paragraph = function(text) {
    var out = null;
    var arr = [];

    text = text.trim();

    // ignore empty text
    if (text.length == 0) {
      return "";
    }

    if (self.sections > 0 || !self.isPonyFile) {

      // add line breaks
      if (text.indexOf("\n") > -1) {
        arr = text.split("\n");
      } else {
        arr.push(text);
      }

      for (x in arr) {
        var img = text.indexOf(" -1) ? "" : "
";
        post = (img > -1) ? "\n" : "
\n";
      }

      out = pre+arr.join('\n\n')+post;

    } else {

      // Add to heading and ignore all other text
      if (self.sections == 0 && self.heading.length > 0) {
        self.heading.push("
"+text+"
\n");
      }

    }
    return out||"";
  }

  // images are rendered as paragraph / text
  Renderer.image = function(href, title, text) {

    var out = null;

		var attr = parseClass(text);

    var out = '' : '>';
    return out;

  }

  Renderer.link = function(href, title, text) {
    if (this.options.sanitize) {
      try {
        var prot = decodeURIComponent(unescape(href))
          .replace(/[^\w:]/g, '')
          .toLowerCase();
      } catch (e) {
        return '';
      }
      if (prot.indexOf('javascript:') === 0) {
        return '';
      }
    }
    var out = '' + text + '';
    return out;
  };

  Renderer.code = function(text,lang) {
		var attr = {cls:"",style:""};

		if (lang) {
			// parse style attr if available
			if (lang.indexOf(']') >= 0) {
				lang = lang.split(']');
				attr = lang[0].replace('[','');
				lang = lang[1];
				attr = parseClass(attr);
			}
		}

		switch(lang) {
			case 'xml':
				text = HTMLEncode(text);
				break;
			case 'markup':
				text = HTMLEncode(text);
				break;
		}

		var out = '
";

    return out+''+text+'
';
  }

  Renderer.table = function(header, body) {

    return '
\n'
      + '
\n'
      + header
      + '
\n'
      + '
\n'
      + body
      + '
\n'
      + '
\n';
  }

	Renderer.blockquote = function(quote) {
		var attr = {};

		// parse bracket style attr if available
		if (quote.indexOf('
[') >= 0) {
			var re = /^
\[(.*\S+)?\]/gm;
			var m = re.exec(quote);
			attr = parseClass(m[1]);

			// remove bracket styling
			quote = quote.replace(m[0],'
');

		}

		var out = '
";

	  return out+'\n' + quote + 'TEST
\n';
	};

}

Pony.prototype.setHeader = function(str){
  this.header = str;
}

Pony.prototype.setFooter = function(str){
  this.footer = str;
}

Pony.prototype.setDebug = function(bool) {
  this.debug = bool;
}

Pony.prototype.log = function(args) {
  if (this.debug) {
    console.log(args);
  }
}

Pony.prototype.render = function(dat,opts) {

  var self = this;

  var header, footer, LEXED, htmlClass;

  // Set options (if avail)
  var _globalopts = opts||{};

  // Reset
  this.heading = [];
  this.sections = 0;
  this.hideSlideNumbers = "";
  this.hrc = [];

  var tokens = Kramed.lexer(dat);

  // Check if first token is configuration
  if (tokens[0].type == "paragraph") {
    if (tokens[0].text.indexOf("\n") > -1) {

      self.isPonyFile = true;

      // rebase tokens
      var rebase = tokens.shift();

      var arr = rebase.text.split("\n");

      // Parse options
      for(var x=0;x<arr.length;x++) {

        opts = arr[x].split(":");

        var _key = opts[0].trim().toLowerCase();
        var _prop = opts[1].trim().toLowerCase();

        self.log(_key + " = " + _prop);

        switch(_key) {

          case 'theme':
            Renderer.ponyoptions.theme = _prop;
            break;

          case 'footer':
            Renderer.ponyoptions.footer = _prop;
            break;

          case 'slidenumbers':
            Renderer.ponyoptions.slidenumbers = (_prop == "false") ? false : true;
            break;

          case 'timing':
            Renderer.ponyoptions.timing = _prop;
            break;

          case 'error':
            self.error = opts[1].trim();
            break;

          case 'tableclass':
            Renderer.ponyoptions.tableclass = _prop||"";
            break;

          case 'format':
            Renderer.ponyoptions.format = _prop||"";
            break;

          case 'progress':
            Renderer.ponyoptions.progress = (_prop == "false") ? false : true;
            break;

          case 'build-lists':
            Renderer.ponyoptions.buildLists = (_prop == "false") ? false : true;
            break;

          case 'transition':
            Renderer.ponyoptions.transition = _prop;
            break;

          case 'shadows':
            Renderer.ponyoptions.shadows = (_prop == "false") ? false : true;
            break;

          default:
            //out = "
"+text+"
";
        }

      }

    }
  }

  self.log(tokens);

  // count HR
  for(var x in tokens) {
    if (tokens[x].type == "hr") {
      self.hrc.push(x);
    }
  }

  if (tokens[self.hrc[self.hrc.length-1]]) {
    tokens[self.hrc[self.hrc.length-1]].last = true;
  }

  // Check if ponyfile
  if (!self.isPonyFile) {
    for(var x=0;x<tokens.length;x++) {
      if (tokens[x].type == "paragraph") {
        if ((tokens[x].text.indexOf("\n---\n") > -1)) {
          self.isPonyFile = true;
        }
      }
    }
  }

  LEXED = Kramed.parser(tokens);

  self.log(LEXED);
  self.log('___________');

  if (LEXED.length == 0) {
    LEXED = self.error;
  }

  // Merge file config with global configs giving preference to file config
  Renderer.ponyoptions = _.assign(_globalopts, Renderer.ponyoptions);

  if (!Renderer.ponyoptions.slidenumbers) {
    self.hideSlideNumbers = '';
  }

  // Apply transition
  if (Renderer.ponyoptions.transition) {
    htmlClass = Renderer.ponyoptions.transition;

    // update defined header
    if (self.header) {
      self.header = self.header.replace(/().*?<head/mgi, '$1 class="'+htmlClass+'"');
    }
  }

  header = self.header||'<!DOCTYPE HTML>' +
  '\n' +
  '\n' +
  	'<title>Pony Show IDE</title>\n' +
  	'<meta charset="utf-8">\n' +
  	'<meta name="viewport" content="width=792, user-scalable=no">\n' +
  	'<meta http-equiv="x-ua-compatible" content="ie=edge">\n' +
  	'<link rel="stylesheet" href="css/main.css">\n' +
  	'<link rel="stylesheet" href="themes/'+Renderer.ponyoptions.theme+'/styles/screen.css">\n' +
  	self.hideSlideNumbers +
  '\n' +
  '\n\n';

  footer = self.footer||'\n' +
  '\n' +
  '';

  if (Renderer.ponyoptions.progress) {
    footer = '\n

\n' + footer;
  }

  // Check if last section.
  if (self.sections == self.hrc.length) {
    LEXED = LEXED+"\n
\n
\n";
  }

  return header+LEXED+footer;

};

if (typeof module !== 'undefined' && typeof exports === 'object') {
  module.exports = new Pony;
} else if (typeof define === 'function' && define.amd) {
  define(function() { return Pony; });
} else {
  this.render = new Pony;
}

}).call(function() {
  return this || (typeof window !== 'undefined' ? window : global);
}());<commit_msg>remove TEST sting in blockquote (derp)<commit_after>var _ = require('lodash'),
  Kramed = require('./kramed'),
  Renderer = new Kramed.Renderer();

// Parser Opts
Kramed.setOptions({
  renderer: Renderer,
  gfm: true,
  tables: true,
  breaks: false,
  pedantic: false,
  sanitize: true,
  smartLists: true,
  smartypants: false
});

/**
 * Encode non-alpha string - HTML
 * return: string
 *
*/
function HTMLEncode(str){
  var i = str.length,
      aRet = [];

  while (i--) {
    var iC = str[i].charCodeAt();
    if (iC < 65 || iC > 127 || (iC>90 && iC<97)) {
      aRet[i] = '&#'+iC+';';
    } else {
      aRet[i] = str[i];
    }
   }
  return aRet.join('');
}

function parseClass(text) {

	var str = text.split(' ');
  var cls = "";
  var style = null;
  var pos = null;

  switch(str[0]) {

    case 'fullscreen':
      cls = 'fullscreen';
      break;

    case 'fit':
      cls = "fit";
      break;

    case 'left':
      cls = "left";
			str.shift();
      style = str.join('');
      break;

    case 'right':
      cls = "right";
			str.shift();
      style = str.join('');
      break;

    case 'top':
			cls = "top";
			str.shift();
			style = str.join('');
			break;

	  case 'bottom':
			cls = "bottom";
			str.shift();
			style = str.join('');
			break;

    case 'css':
      str.shift();
      style = str.join(' ');
      break;

    default:
      cls = str[0];
  }

	if (Renderer.ponyoptions.shadows) {
    cls = cls+" shadow";
  }

	return {
		cls: cls,
		style: style
	}

}

;(function() {

/**
 * Markdown to Shower
 * return: string
 *
*/

function Pony(options) {

  var self = this;

  var options = options || {};

  self.debug = options.debug||false;

  self.version = require('../package.json').version;

  self.heading = (options.heading) ? options.heading : [];
  self.sections = (options.sections) ? options.sections : 0;
  self.hideSlideNumbers = (options.hideSlideNumbers) ? options.hideSlideNumbers : "";
  self.hrc = (options.hrc) ? options.hrc : [];

  self.error = (options.error) ? options.error : "

Rendering error

";

  self.header = options.header;
  self.footer = options.footer;

  self._theme = false;
  self.isPonyFile = false;

  Renderer.ponyoptions = {
    format: "",
    slidenumbers: true,
    footer: 'Pony Show',
    timing:false,
    progress:true,
    transition:false,
    shadows:false
  };

  Renderer.list = function(body, ordered) {
    var type = ordered ? 'ol' : 'ul', out="", cls="";

    out = '<' + type + '>\n' + body + '</' + type + '>\n';

    if (self.sections > 0 || !self.isPonyFile) {
      return out;
    } else {
      self.heading.push(out);
      return '';
    }
  };

  Renderer.listitem = function(text) {
    var cls="";
    if (Renderer.ponyoptions.buildLists) {
      cls = "next";
    }

    return '
' + text + '
\n';
  }

  Renderer.hr = function(cls,id) {
    var out = null;
    var timing = false;

    // set format for each section
    if (Renderer.ponyoptions.format) {
      cls = Renderer.ponyoptions.format + " " + cls;
    }

    // Set timing option
    if (Renderer.ponyoptions.timing) {
      timing = 'data-timing="'+Renderer.ponyoptions.timing+'"';
    }

    if (self.sections == 0) {

      // heading
      if (self.heading.length > 0) {
        out = self.heading.join('') + "\n";
      }

      out = out+"\n
\n
\n";
    } else {

      if (self.sections == self.hrc.length) {
        out = "\n
\n
\n";
      } else {
        out = "
\n
\n\n
\n
\n";
      }
    }

    self.sections++;

    return out||"";
  }

  Renderer.heading = function (text, level) {
    var out = false;

    // var str = text.split('[');
    // var style = null;
    //
    // switch(str[0]) {
    //   case 'absolute':
    //     str.shift();
    //     style = str.join('');
    //     break;
    //
    //   default:
    // }

    if (self.sections == 0 && self.heading.length == 0 && self.isPonyFile) {
      self.heading.push('\n');
      self.heading.push('<h' + level + '>' + text + '</h' + level + '>\n');
    } else if (self.sections == 0 && self.isPonyFile && (self.heading.length > 1)) {
      self.heading.push('<h' + level + '>' + text + '</h' + level + '>\n');
    } else {
      // default
      out = '<h' + level + ' class="fit">' + text + '</h' + level + '>\n';
    }

    return (out) ? out : "";
  };

  Renderer.paragraph = function(text) {
    var out = null;
    var arr = [];

    text = text.trim();

    // ignore empty text
    if (text.length == 0) {
      return "";
    }

    if (self.sections > 0 || !self.isPonyFile) {

      // add line breaks
      if (text.indexOf("\n") > -1) {
        arr = text.split("\n");
      } else {
        arr.push(text);
      }

      for (x in arr) {
        var img = text.indexOf(" -1) ? "" : "
";
        post = (img > -1) ? "\n" : "
\n";
      }

      out = pre+arr.join('\n\n')+post;

    } else {

      // Add to heading and ignore all other text
      if (self.sections == 0 && self.heading.length > 0) {
        self.heading.push("
"+text+"
\n");
      }

    }
    return out||"";
  }

  // images are rendered as paragraph / text
  Renderer.image = function(href, title, text) {

    var out = null;

		var attr = parseClass(text);

    var out = '' : '>';
    return out;

  }

  Renderer.link = function(href, title, text) {
    if (this.options.sanitize) {
      try {
        var prot = decodeURIComponent(unescape(href))
          .replace(/[^\w:]/g, '')
          .toLowerCase();
      } catch (e) {
        return '';
      }
      if (prot.indexOf('javascript:') === 0) {
        return '';
      }
    }
    var out = '' + text + '';
    return out;
  };

  Renderer.code = function(text,lang) {
		var attr = {cls:"",style:""};

		if (lang) {
			// parse style attr if available
			if (lang.indexOf(']') >= 0) {
				lang = lang.split(']');
				attr = lang[0].replace('[','');
				lang = lang[1];
				attr = parseClass(attr);
			}
		}

		switch(lang) {
			case 'xml':
				text = HTMLEncode(text);
				break;
			case 'markup':
				text = HTMLEncode(text);
				break;
		}

		var out = '
";

    return out+''+text+'
';
  }

  Renderer.table = function(header, body) {

    return '
\n'
      + '
\n'
      + header
      + '
\n'
      + '
\n'
      + body
      + '
\n'
      + '
\n';
  }

	Renderer.blockquote = function(quote) {
		var attr = {};

		// parse bracket style attr if available
		if (quote.indexOf('
[') >= 0) {
			var re = /^
\[(.*\S+)?\]/gm;
			var m = re.exec(quote);
			attr = parseClass(m[1]);

			// remove bracket styling
			quote = quote.replace(m[0],'
');

		}

		var out = '
";

	  return out+'\n' + quote + '
\n';
	};

}

Pony.prototype.setHeader = function(str){
  this.header = str;
}

Pony.prototype.setFooter = function(str){
  this.footer = str;
}

Pony.prototype.setDebug = function(bool) {
  this.debug = bool;
}

Pony.prototype.log = function(args) {
  if (this.debug) {
    console.log(args);
  }
}

Pony.prototype.render = function(dat,opts) {

  var self = this;

  var header, footer, LEXED, htmlClass;

  // Set options (if avail)
  var _globalopts = opts||{};

  // Reset
  this.heading = [];
  this.sections = 0;
  this.hideSlideNumbers = "";
  this.hrc = [];

  var tokens = Kramed.lexer(dat);

  // Check if first token is configuration
  if (tokens[0].type == "paragraph") {
    if (tokens[0].text.indexOf("\n") > -1) {

      self.isPonyFile = true;

      // rebase tokens
      var rebase = tokens.shift();

      var arr = rebase.text.split("\n");

      // Parse options
      for(var x=0;x<arr.length;x++) {

        opts = arr[x].split(":");

        var _key = opts[0].trim().toLowerCase();
        var _prop = opts[1].trim().toLowerCase();

        self.log(_key + " = " + _prop);

        switch(_key) {

          case 'theme':
            Renderer.ponyoptions.theme = _prop;
            break;

          case 'footer':
            Renderer.ponyoptions.footer = _prop;
            break;

          case 'slidenumbers':
            Renderer.ponyoptions.slidenumbers = (_prop == "false") ? false : true;
            break;

          case 'timing':
            Renderer.ponyoptions.timing = _prop;
            break;

          case 'error':
            self.error = opts[1].trim();
            break;

          case 'tableclass':
            Renderer.ponyoptions.tableclass = _prop||"";
            break;

          case 'format':
            Renderer.ponyoptions.format = _prop||"";
            break;

          case 'progress':
            Renderer.ponyoptions.progress = (_prop == "false") ? false : true;
            break;

          case 'build-lists':
            Renderer.ponyoptions.buildLists = (_prop == "false") ? false : true;
            break;

          case 'transition':
            Renderer.ponyoptions.transition = _prop;
            break;

          case 'shadows':
            Renderer.ponyoptions.shadows = (_prop == "false") ? false : true;
            break;

          default:
            //out = "
"+text+"
";
        }

      }

    }
  }

  self.log(tokens);

  // count HR
  for(var x in tokens) {
    if (tokens[x].type == "hr") {
      self.hrc.push(x);
    }
  }

  if (tokens[self.hrc[self.hrc.length-1]]) {
    tokens[self.hrc[self.hrc.length-1]].last = true;
  }

  // Check if ponyfile
  if (!self.isPonyFile) {
    for(var x=0;x<tokens.length;x++) {
      if (tokens[x].type == "paragraph") {
        if ((tokens[x].text.indexOf("\n---\n") > -1)) {
          self.isPonyFile = true;
        }
      }
    }
  }

  LEXED = Kramed.parser(tokens);

  self.log(LEXED);
  self.log('___________');

  if (LEXED.length == 0) {
    LEXED = self.error;
  }

  // Merge file config with global configs giving preference to file config
  Renderer.ponyoptions = _.assign(_globalopts, Renderer.ponyoptions);

  if (!Renderer.ponyoptions.slidenumbers) {
    self.hideSlideNumbers = '';
  }

  // Apply transition
  if (Renderer.ponyoptions.transition) {
    htmlClass = Renderer.ponyoptions.transition;

    // update defined header
    if (self.header) {
      self.header = self.header.replace(/().*?<head/mgi, '$1 class="'+htmlClass+'"');
    }
  }

  header = self.header||'<!DOCTYPE HTML>' +
  '\n' +
  '\n' +
  	'<title>Pony Show IDE</title>\n' +
  	'<meta charset="utf-8">\n' +
  	'<meta name="viewport" content="width=792, user-scalable=no">\n' +
  	'<meta http-equiv="x-ua-compatible" content="ie=edge">\n' +
  	'<link rel="stylesheet" href="css/main.css">\n' +
  	'<link rel="stylesheet" href="themes/'+Renderer.ponyoptions.theme+'/styles/screen.css">\n' +
  	self.hideSlideNumbers +
  '\n' +
  '\n\n';

  footer = self.footer||'\n' +
  '\n' +
  '';

  if (Renderer.ponyoptions.progress) {
    footer = '\n

\n' + footer;
  }

  // Check if last section.
  if (self.sections == self.hrc.length) {
    LEXED = LEXED+"\n
\n
\n";
  }

  return header+LEXED+footer;

};

if (typeof module !== 'undefined' && typeof exports === 'object') {
  module.exports = new Pony;
} else if (typeof define === 'function' && define.amd) {
  define(function() { return Pony; });
} else {
  this.render = new Pony;
}

}).call(function() {
  return this || (typeof window !== 'undefined' ? window : global);
}());<|endoftext|>


<commit_before>(function() {
    'strict mode';

    global.minify = {};

    var DIR,
        LIBDIR,

        path,
        Util;

    /* Constants */
    exports.LIBDIR      = LIBDIR    = './',
    exports.DIR         = DIR       = LIBDIR + '../',

    /* Functions */
    exports.require                 = mrequire,
    exports.librequire              = librequire,
    exports.rootrequire             = rootrequire,

    /* Native Modules*/
    exports.crypto                  = require('crypto'),
    exports.fs                      = require('fs'),
    exports.path    = path          = require('path'),
    /* compitability with old versions of node */
    exports.fs.exists               = exports.fs.exists || exports.path.exists;

    exports.optimize                = optimize,

    /* Needed Modules */
    exports.util    = Util          = require('util.io');
    exports.mainpackage             = rootrequire('package');

    Util.getExtension               = path.extname;

    global.minify.main = exports;

    var html        = librequire('html'),
        js          = librequire('js'),
        css         = librequire('css');

    function optimize(params, callback) {
        var ret    = Util.checkObjTrue(params, ['ext', 'data']),
            p       = params;

        if (ret)
            switch(p.ext) {
                case '.js':
                    js._uglifyJS(p.data, callback);
                    break;

                case '.html':
                    html.htmlMinify(p.data, callback);
                    break;

                case '.css':
                    css._cleanCSS(p.data, callback);
                    break;
            }
    }

    /**
     * function do safe require of needed module
     * @param {String} src
     */
    function mrequire(pSrc) {
        var module;

        Util.exec.tryLog(function() {
            module = require(pSrc);
        });

        return module;
    }

    function rootrequire(pSrc) { return mrequire(DIR + pSrc); }

    function librequire(pSrc) { return mrequire(LIBDIR + pSrc); }

})();
<commit_msg>fix(main) util.io -> util-io<commit_after>(function() {
    'strict mode';

    global.minify = {};

    var DIR,
        LIBDIR,

        path,
        Util;

    /* Constants */
    exports.LIBDIR      = LIBDIR    = './',
    exports.DIR         = DIR       = LIBDIR + '../',

    /* Functions */
    exports.require                 = mrequire,
    exports.librequire              = librequire,
    exports.rootrequire             = rootrequire,

    /* Native Modules*/
    exports.crypto                  = require('crypto'),
    exports.fs                      = require('fs'),
    exports.path    = path          = require('path'),
    /* compitability with old versions of node */
    exports.fs.exists               = exports.fs.exists || exports.path.exists;

    exports.optimize                = optimize,

    /* Needed Modules */
    exports.util    = Util          = require('util-io');
    exports.mainpackage             = rootrequire('package');

    Util.getExtension               = path.extname;

    global.minify.main = exports;

    var html        = librequire('html'),
        js          = librequire('js'),
        css         = librequire('css');

    function optimize(params, callback) {
        var ret    = Util.checkObjTrue(params, ['ext', 'data']),
            p       = params;

        if (ret)
            switch(p.ext) {
                case '.js':
                    js._uglifyJS(p.data, callback);
                    break;

                case '.html':
                    html.htmlMinify(p.data, callback);
                    break;

                case '.css':
                    css._cleanCSS(p.data, callback);
                    break;
            }
    }

    /**
     * function do safe require of needed module
     * @param {String} src
     */
    function mrequire(pSrc) {
        var module;

        Util.exec.tryLog(function() {
            module = require(pSrc);
        });

        return module;
    }

    function rootrequire(pSrc) { return mrequire(DIR + pSrc); }

    function librequire(pSrc) { return mrequire(LIBDIR + pSrc); }

})();
<|endoftext|>