diff --git a/.travis.yml b/.travis.yml index 17f302b..dc08449 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ language: node_js node_js: - - "0.10" - - "0.12" - "4" - "6" + - "7" os: - linux - osx diff --git a/README.md b/README.md index cde67b7..a0bf5d1 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,16 @@ Oh, and `limax` is the Latin word for slug. ## Usage ```javascript -var slug = require('limax'); +import slug from 'limax'; ``` ### slug(text) ```javascript -var latin = slug('i ♥ latin'); // i-love-latin -var cyrillic = slug('Я люблю русский'); // ya-lyublyu-russkij -var pinyin = slug('我爱官话'); // wo3-ai4-guan1-hua4 -var romaji = slug('私は ひらがな が大好き'); // ha-hiragana-gaki +const latin = slug('i ♥ latin'); // i-love-latin +const cyrillic = slug('Я люблю русский'); // ya-lyublyu-russkij +const pinyin = slug('我爱官话'); // wo3-ai4-guan1-hua4 +const romaji = slug('私は ひらがな が大好き'); // ha-hiragana-gaki ``` ### slug(text, options) @@ -58,22 +58,22 @@ options: * Array, add chars to allowed charMap ```javascript -var strich = slug('Ich ♥ Deutsch', {lang: 'de'}); // ich-liebe-deutsch -var unterstreichen1 = slug('Ich ♥ Deutsch', {lang: 'de', replacement: '_'}); // i_liebe_deutsch -var unterstreichen2 = slug('Ich ♥ Deutsch', {lang: 'de', separator: '_'}); // i_liebe_deutsch -var wuYin = slug('弄堂里的菜品赤醬', {tone: false}); // nong-tang-li-di-cai-pin-chi-jiang +const strich = slug('Ich ♥ Deutsch', {lang: 'de'}); // ich-liebe-deutsch +const unterstreichen1 = slug('Ich ♥ Deutsch', {lang: 'de', replacement: '_'}); // i_liebe_deutsch +const unterstreichen2 = slug('Ich ♥ Deutsch', {lang: 'de', separator: '_'}); // i_liebe_deutsch +const wuYin = slug('弄堂里的菜品赤醬', {tone: false}); // nong-tang-li-di-cai-pin-chi-jiang // separateNumbers example -var numbersInWord = slug('hello2world', {separateNumbers: false}); // hello2world -var numbersSeparated = slug('hello2world'); // hello-2-world +const numbersInWord = slug('hello2world', {separateNumbers: false}); // hello2world +const numbersSeparated = slug('hello2world'); // hello-2-world // maintainCase example -var caseNotMaintained = slug('Hello2World'); // hello-2-world -var caseMaintained = slug('Hello2World', { maintainCase: true }); // Hello-2-World +const caseNotMaintained = slug('Hello2World'); // hello-2-world +const caseMaintained = slug('Hello2World', { maintainCase: true }); // Hello-2-World // custom example -var custom1 = slug('hello.world', { custom: ['.'] }); // hello.world -var custom2 = slug('hello-*-world', { custom: { '*': 'asterisk' } }); // hello-asterisk-world +const custom1 = slug('hello.world', { custom: ['.'] }); // hello.world +const custom2 = slug('hello-*-world', { custom: { '*': 'asterisk' } }); // hello-asterisk-world ``` ### slug(text, replacement) @@ -81,7 +81,7 @@ var custom2 = slug('hello-*-world', { custom: { '*': 'asterisk' } }); // hello-a Provided to support backwards-compatibility with the `slug` module. ```javascript -var underscore = slug('i ♥ unicode', '_'); // i_love_unicode +const underscore = slug('i ♥ unicode', '_'); // i_love_unicode ``` ## Test [![Build Status](https://travis-ci.org/lovell/limax.png?branch=master)](https://travis-ci.org/lovell/limax) diff --git a/appveyor.yml b/appveyor.yml index 254df4f..b0b7e18 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,10 +4,6 @@ build: off platform: x64 environment: matrix: - - nodejs_version: "0.12" - nodejs_arch: "x86" - - nodejs_version: "0.12" - nodejs_arch: "x64" - nodejs_version: "4" nodejs_arch: "x86" - nodejs_version: "4" @@ -16,6 +12,10 @@ environment: nodejs_arch: "x86" - nodejs_version: "6" nodejs_arch: "x64" + - nodejs_version: "7" + nodejs_arch: "x86" + - nodejs_version: "7" + nodejs_arch: "x64" install: - ps: Install-Product node $env:nodejs_version $env:nodejs_arch - npm install diff --git a/lib/limax.js b/lib/limax.js index 0ccb323..b373d93 100644 --- a/lib/limax.js +++ b/lib/limax.js @@ -1,34 +1,27 @@ 'use strict'; -var speakingurl = require('speakingurl'); -var pinyin = require('pinyin'); -var hepburn = require('hepburn'); +const speakingurl = require('speakingurl'); +const pinyin = require('pinyin'); +const hepburn = require('hepburn'); module.exports = function(text, opt) { - var options = opt || {}; - var separateNumbers = true; - - if (typeof options === 'string') { - options = {separator: options}; - } - - if (typeof options.separateNumbers !== 'undefined') { - separateNumbers = options.separateNumbers; - } + const options = typeof opt === 'string' + ? { separator: opt } + : opt || {}; // Remove apostrophes contained within a word text = text.replace(/(\S)['\u2018\u2019\u201A\u201B\u2032\u2035\u0301](\S)/g, '$1$2'); // Break out any numbers contained within a word - if (separateNumbers) { + if (options.separateNumbers !== false) { text = text.replace(/([^\d\s])([0-9]+)([^\d\s])/g, '$1 $2 $3'); } // Should we remove the separator before a digit where previous word does not end in a digit? - var mergeDigitSuffixes = false; + let mergeDigitSuffixes = false; // Language-specific behaviour - var lang = options.lang; + const lang = options.lang; if (typeof lang === 'undefined') { if (hepburn.containsKana(text)) { // Convert from Japanese Kana using Hepburn romanisation @@ -39,7 +32,7 @@ module.exports = function(text, opt) { // Convert Mandarin Chinese to Pinyin with numeric tones mergeDigitSuffixes = true; // Should we use tone numbers? (default is true) - var tone = (typeof options.tone === 'boolean') ? options.tone : true; + const tone = (typeof options.tone === 'boolean') ? options.tone : true; text = pinyin(text, { 'style': tone ? pinyin.STYLE_TONE2 : pinyin.STYLE_NORMAL }).join(' '); @@ -50,19 +43,15 @@ module.exports = function(text, opt) { } } // Convert to slug using speakingurl - var separator = options.replacement || options.separator; - if (typeof separator !== 'string') { - separator = '-'; - } - var slug = speakingurl(text, { + const separator = options.replacement || options.separator; + const slug = speakingurl(text, { lang: lang || 'en', - separator: separator, + separator: typeof separator === 'string' ? separator : '-', maintainCase: options.maintainCase || false, custom: options.custom || {} }); // Remove separator before a digit where previous word does not end in a digit - if (mergeDigitSuffixes) { - slug = slug.replace(/([^0-9])-([0-9])/g, '$1$2'); - } - return slug; + return mergeDigitSuffixes + ? slug.replace(/([^0-9])-([0-9])/g, '$1$2') + : slug; }; diff --git a/package.json b/package.json index 53e494b..04506df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "limax", - "version": "1.4.1", + "version": "1.5.0", "main": "./lib/limax", "description": "Node.js module to generate URL slugs. Another one? This one cares about i18n and transliterates non-Latin scripts to conform to the RFC3986 standard. Mostly API-compatible with similar modules.", "repository": { @@ -8,7 +8,7 @@ "url": "git://github.com/lovell/limax" }, "engines": { - "node": ">=0.10" + "node": ">=4" }, "scripts": { "test": "node test/unit" @@ -39,7 +39,7 @@ "license": "Apache-2.0", "dependencies": { "hepburn": "^1.0.0", - "pinyin": "2.6.2", - "speakingurl": "^10.0.0" + "pinyin": "^2.8.2", + "speakingurl": "^13.0.0" } } diff --git a/test/unit.js b/test/unit.js index 7134d03..e60a10a 100644 --- a/test/unit.js +++ b/test/unit.js @@ -1,9 +1,9 @@ 'use strict'; -var assert = require('assert'); -var slug = require('../lib/limax'); +const assert = require('assert'); +const slug = require('../lib/limax'); -var tests = { +const tests = { 'i ♥ latin': 'i-love-latin', 'Я люблю русский': 'ya-lyublyu-russkii', '私は ひらがな が大好き': 'ha-hiragana-gaki', @@ -13,7 +13,7 @@ var tests = { 'The User\'s Guide': 'the-users-guide', 'The User’s Guide': 'the-users-guide', // https://github.com/lovell/limax/issues/4 - '弄堂里的菜品赤醬': 'nong4-tang2-li3-di2-cai4-pin3-chi4-jiang4', + '弄堂里的菜品赤醬': 'nong4-tang2-li3-de-cai4-pin3-chi4-jiang4', // https://github.com/lovell/limax/issues/12 '12345': '12345', 'one 2three': 'one-2three', @@ -22,34 +22,34 @@ var tests = { }; Object.keys(tests).forEach(function(test) { - var actual = slug(test); - var expected = tests[test]; + const actual = slug(test); + const expected = tests[test]; assert.strictEqual(actual, expected); }); Object.keys(tests).forEach(function(test) { - var actual = slug(test, '_'); - var expected = tests[test].replace(/-/g, '_'); + const actual = slug(test, '_'); + const expected = tests[test].replace(/-/g, '_'); assert.strictEqual(actual, expected); }); Object.keys(tests).forEach(function(test) { - var actual = slug(test, {replacement: '_'}); - var expected = tests[test].replace(/-/g, '_'); + const actual = slug(test, {replacement: '_'}); + const expected = tests[test].replace(/-/g, '_'); assert.strictEqual(actual, expected); }); Object.keys(tests).forEach(function(test) { - var actual = slug(test, {separator: '_'}); - var expected = tests[test].replace(/-/g, '_'); + const actual = slug(test, {separator: '_'}); + const expected = tests[test].replace(/-/g, '_'); assert.strictEqual(actual, expected); }); assert.strictEqual(slug('Ich ♥ Deutsch', {lang: 'de'}), 'ich-liebe-deutsch'); // https://github.com/lovell/limax/issues/4 -assert.strictEqual(slug('弄堂里的菜品赤醬', {tone: true}), 'nong4-tang2-li3-di2-cai4-pin3-chi4-jiang4'); -assert.strictEqual(slug('弄堂里的菜品赤醬', {tone: false}), 'nong-tang-li-di-cai-pin-chi-jiang'); +assert.strictEqual(slug('弄堂里的菜品赤醬', {tone: true}), 'nong4-tang2-li3-de-cai4-pin3-chi4-jiang4'); +assert.strictEqual(slug('弄堂里的菜品赤醬', {tone: false}), 'nong-tang-li-de-cai-pin-chi-jiang'); // https://github.com/lovell/limax/issues/14 assert.strictEqual(slug('hello2world', { separateNumbers: false }), 'hello2world');