API Docs for:
Show:

File: src/lib/jp-wrap.coffee


Word = require './word'

Regexps = require './regexps'

###*
日本語の禁則処理を行って改行する

@class JpWrap
@module jp-wrap
###
class JpWrap

    DEFAULT_WIDTH: 100

    @notStartingCharRegExp         : Regexps.notStartingChars
    @notStartingCharWithHalfRegExp : Regexps.notStartingCharsWithHalf
    @notEndingCharRegExp           : Regexps.notEndingChars

    ###*
    @constructor
    @param {Number} [width=100] 半角1, 全角2としたときの全体の幅
    @param {Object} [options]
    @param {Boolean} [options.half] 半角文字の行頭禁則処理を行うか
    @param {Boolean} [options.trim=true] 入力文字列の改行を取り除くかどうか
    @param {Boolean} [options.breakAll] trueだとcssのword-break:break-allと同じ挙動をする
    @param {Boolean} [options.fullWidthSpace=true] 全角スペースが行頭にあった場合削除するか
    @param {Boolean} [options.sameWidth] 全角文字と半角文字の幅を両方とも2として計算する
    @param {Object} [options.regexs] 幅の計算方法を正規表現で指定する
    ###
    constructor: (@width = @DEFAULT_WIDTH, options = {}) ->

        @trim = !! (options.trim ? true)
        @breakAll = !! options.breakAll
        @half = !! options.half
        @fullWidthSpace = !! (options.fullWidthSpace ? true)
        @regexs = (options.regexs ? [])
        @sameWidth = !! options.sameWidth


    ###*
    textを分割し、行(String)の配列を取得

    @method wrap
    @public
    @param {String} text
    @return {Array(String)} lines 分割された行の配列
    ###
    wrap: (text) ->

        (line.str for line in @getLines(text))


    ###*
    textを分割し、行(Wordオブジェクト)の配列を取得
    戦略:文字列を単語ごとに分解してから、行を埋めていく

    @method getLines
    @public
    @param {String} text
    @return {Array(String)} lines 分割された行の配列
    ###
    getLines: (text) ->

        lines = []

        words = @splitTextIntoWords(text)

        currentLine = null

        for word in words

            if not currentLine?
                currentLine = word.ltrim(@fullWidthSpace)

            else if currentLine.hasLineBreak()
                lines.push currentLine
                currentLine = word.ltrim(@fullWidthSpace)

            else if currentLine.width + word.width <= @width
                currentLine.append word

            else
                lines.push currentLine
                currentLine = word.ltrim(@fullWidthSpace)

        lines.push currentLine if currentLine.hasStr()

        return lines


    ###*
    与えられた文字列を単語に分割
    行頭に来ることができないものを前の文字の続きにして分割

    @method splitTextIntoWords
    @private
    @param {String} text
    @return {Array(Word)}
    ###
    splitTextIntoWords: (text) ->

        words = []

        currentWord = new Word('', {sameWidth: @sameWidth, regexs: @regexs})

        for c in text

            if c is '\n'

                if not @trim
                    words.push currentWord.appendLineBreak(c)
                    currentWord = new Word()

                continue

            word = new Word(c, {sameWidth: @sameWidth, regexs: @regexs})

            if @isJoinable(currentWord, word)

                currentWord.append word

            else
                words.push currentWord if currentWord.hasStr()
                currentWord = word

        words.push currentWord if currentWord.hasStr()

        return words


    ###*
    word1にword2をjoinしていいのかどうか
    @method isJoinable
    @private
    @param {Word} word1
    @param {Word} word2
    ###
    isJoinable: (word1, word2) ->

        return false if word1.width + word2.width > @width

        return true if word1.last()?.match @constructor.notEndingCharRegExp

        return false if @breakAll

        return true if word1.isAlphaNumeric and word2.isAlphaNumeric

        regex = if @half then @constructor.notStartingCharWithHalfRegExp else @constructor.notStartingCharRegExp

        return !! word2.str.match(regex)


module.exports = JpWrap