Git Product home page Git Product logo

speakingurl's Introduction

SpeakingURL

Build Status NPM version Bower version Gem Version Gitter Flattr

Generate a slug with a lot of options; create a so-called Semantic URL or 'Clean URL' or 'Pretty URL' or 'nice-looking URL' or 'Speaking URL' or 'user-friendly URL' or 'SEO-friendly URL' from a string. This module aims to transliterate the input string.

For use in browser and server - no dependencies!

NPM Badge

Module Status

Installation

npm install speakingurl --save
yarn add speakingurl --dev
bower install --save speakingurl
component install pid/speakingurl
# Add to Gemfile
gem 'speakingurl-rails'

copy the file speakingurl.min.js to your script directory

available versions:

available versions:

Usage

getSlug(input, [options]);

input: {string} to convert

options {object|string} config object or separator string (see below)

  • options {object}

    • separator {string} default: '-'
      • char that replaces the whitespaces
    • lang {string|boolean} default: 'en' // ISO 639-1 Codes
      • language specific transliteration (
        • 'ar' // Arabic
        • 'az' // Azerbaijani*
        • 'cs' // Czech
        • 'de' // German
        • 'dv' // Divehi
        • 'en' // English
        • 'es' // Spanish
        • 'fa' // Persian
        • 'fi' // Finnish
        • 'fr' // French
        • 'ge' // Georgian
        • 'gr' // Greek*
        • 'hu' // Hungarian
        • 'it' // Italian
        • 'lt' // Lithuanian*
        • 'lv' // Latvian
        • 'my' // Burmese
        • 'mk' // Macedonian*
        • 'nl' // Dutch
        • 'pl' // Polish
        • 'pt' // Portuguese
        • 'ro' // Romanian
        • 'ru' // Russian
        • 'sv' // Swedish
        • 'sk' // Slovak
        • 'sr' // Serbian*
        • 'tr' // Turkish
        • 'uk' // Ukranian
        • 'vn' // Vietnamese
    • symbols {boolean} default: true
      • false -> don't convert symbols
      • true -> convert symbols according to the 'lang' setting
    • maintainCase {boolean} default: false
      • true -> maintain case chars
      • false -> convert all chars to lower case
    • titleCase {boolean|array} default: false
      • true -> convert input string to title-case
      • array -> titlecase = true, but omit the words from in the array
    • truncate {number} default: 0
      • 0 -> don't trim length
      • >= 1 -> trim to max length while not breaking any words
    • uric {boolean} default: false
      • true -> additionally allow chars: ";", "?", ":", "@", "&", "=", "+", "$", ",", "/"
      • false
    • uricNoSlash {boolean} default: false
      • true -> additionally allow chars: ";", "?", ":", "@", "&", "=", "+", "$", ","
    • mark {boolean} default: false
      • true -> additionally allow chars: "-", "_", ".", "!", "~", "*", "'", "(", ")"
    • custom {object|array} default: {}
      • object -> custom map for translation, overwrites all i.e. { '&': '#', '*': ' star ' }
      • array -> add chars to allowed charMap (see example)
  • options {string} separator

notes: default only Base64 chars are allowed (/A-Za-z0-9_-/), setting uric, uricNoSlash or/and mark to true will add the specified chars to the list of allowed characters. The separator-character is always allowed.

Node.js
var getSlug = require('speakingurl');
Browser
<script src="bower_components/speakingurl/speakingurl.min.js"></script>

Ruby on Rails

# Add to application.js
//= require speakingurl

Examples

var slug;

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !");
console.log(slug); // Output: schoener-titel-laesst-gruessen-bel-ete

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !", '*');
console.log(slug); // Output: schoener*titel*laesst*gruessen*bel*ete

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !", {
        separator: '_'
	});
console.log(slug); // Output: schoener_titel_laesst_gruessen_bel_ete

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !", {
        uric: true
	});
console.log(slug); // Output: schoener-titel-laesst-gruessen?-bel-ete

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !", {
    	uricNoSlash: true
	});
console.log(slug); // Output: schoener-titel-laesst-gruessen?-bel-ete

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !", {
    	mark: true
	});
console.log(slug); // Output: schoener-titel-laesst-gruessen!-bel-ete-!

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !", {
    	truncate: 20
	});
console.log(slug); // Output: schoener-titel

slug = getSlug("Schöner Titel läßt grüßen!? Bel été !", {
	    maintainCase: true
	});
console.log(slug); // Output: Schoener-Titel-laesst-gruessen-Bel-ete

slug = getSlug("Äpfel & Birnen!", {
	    lang: 'de'
	});
console.log(slug); // Output: aepfel-und-birnen

slug = getSlug("မြန်မာ သာဓက", {
	    lang: 'my'
	});
console.log(slug); // Output: myanma-thadak

slug = getSlug('މިއަދަކީ ހދ ރީތި ދވހކވ', {
        lang: 'dv'
    });
console.log(slug); // Output: miadhakee hd reethi dvhkv

slug = getSlug("Apple & Pear!", {
	    lang: 'en' // lang: "en" is default, just to clarify
	});
console.log(slug); // Output: apple-and-pear

slug = getSlug('Foo & Bar * Baz', {
	    custom: {
	        '&': ' doo '
	    },
	    uric:true
	});
console.log(slug); // Output: foo-doo-bar-baz

slug = getSlug('Foo ♥ Bar');
console.log(slug); // Output: foo-love-bar

slug = getSlug('Foo & Bar | (Baz) * Doo', {
	    custom: {
	        '*': 'Boo'
	    },
	    mark:true
	});
console.log(slug); // Output: foo-and-bar-or-(baz)-boo-doo

slug = getSlug('Foo and Bar or Baz', {
	    custom: {
	        'and': 'und',
	        'or': ''
	    }
	});
console.log(slug); // Output: foo-und-bar-baz

slug = getSlug('[Knöpfe]', {
		custom: [
			'[',
			']'
		]
	});
console.log(slug); // Output: [knoepfe]

slug = getSlug('NEXUS4 only $299');
console.log(slug); // Output: nexus-4-only-usd299

slug = getSlug('NEXUS4 only €299', {
	    maintainCase: true
	});
console.log(slug); // Output: NEXUS-4-only-EUR299

slug = getSlug('Don\'t drink and drive', {
	    titleCase: true
	});
console.log(slug); // Output: Don-t-Drink-And-Drive

slug = getSlug('Don\'t drink and drive', {
	    titleCase: ['and']
	});
console.log(slug); // Output: Don-t-Drink-and-Drive

slug = getSlug('Foo & Bar ♥ Foo < Bar', {
	    lang: false
	});
console.log(slug); // Output: foo-bar-foo-bar

slug = getSlug('Foo & Bar ♥ Foo < Bar', {
	    symbols: false
	});
console.log(slug); // Output: foo-bar-foo-bar

slug = getSlug('ä♥ä', {
		lang: 'tr',
	    symbols: false
	});
console.log(slug); // Output: a

createSlug([options])

options: {object|string} config object or separator string (see above)

Create your own specially configured function.

var options = {
	    maintainCase: true,
	    separator: '_'
	};

var mySlug = require('speakingurl').createSlug(options);
// in browser:
// var mySlug = createSlug(options);

var slug = mySlug("Schöner Titel läßt grüßen!? Bel été !");
console.log(slug); // Output: Schoener_Titel_laesst_gruessen_Bel_ete

Create your own specially configured function with title-case feature.

var options = {
	    titleCase: [
	        "a","an","and","as","at","but",
	        "by","en","for","if","in","nor",
	        "of","on","or","per","the","to","vs"
	    ]
	};

var mySlug = require('speakingurl').createSlug(options);
// in browser:
// var mySlug = createSlug(options);

var slug = mySlug('welcome to the jungle');
console.log(slug); // Output: Welcome-to-the-Jungle

Changelog

see CHANGELOG.md

Tests

Build Status

npm test

Contribution

# fork pid/speakingurl on Github
$ git clone [email protected]:<YOUR_USER>/speakingurl.git
$ cd speakingurl
$ npm install
# add your stuff
# add tests
# add example for new feature
# add release info to CHANGELOG.md
# add description/example to README.md
$ gulp
$ commit files (speakingurl.min.js,...)
# if everything works fine, commit, push to your repository
# create pull request

Release

$ gulp bumpup --patch  # --minor # --major
$ gulp
$ gulp release

Release to RubyGems.org

$ gulp
$ gem build speakingurl-rails.gemspec
$ gem push speakingurl-rails-x.x.x.gem

References

Use in other environments

Ports

Credits

The BSD 3-Clause License (BSD3)

Copyright (c) 2013-2017 Sascha Droste [email protected] All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

speakingurl's People

Contributors

alexandernst avatar alitalaghat avatar apepper avatar bdadam avatar bitdeli-chef avatar borissuska avatar bricesanchez avatar bruchmann avatar chmac avatar dandv avatar djebbz avatar falmp avatar gswalden avatar jawish avatar jmheik avatar kwiatkk1 avatar latal avatar lukasdrgon avatar mgax avatar mvasilkov avatar okhayat avatar oleg2tor avatar petkostas avatar pid avatar rexxars avatar simi avatar simison avatar standaniels avatar stonio avatar yawnt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

speakingurl's Issues

Japanese transliteration / romanization

Japanese can be transliterated or romanized pretty effectively with software. That would be a killer feature for my future needs, as my company has several sites will include URLs for stores that have Japanese titles.

Translation needed: Macedonian

           'mk': {
                '∆': 'delta',
                '∞': 'infinity',
                '♥': 'love',
                '&': 'and',
                '|': 'or',
                '<': 'less than',
                '>': 'greater than',
                '∑': 'sum',
                '¤': 'currency'
            },

!!! Translation must be already transliterated !!!

Node.js has no window object

Hi! Thanks for this great lib!
I am using speakingURL with meteor.js in both enviroments(client(browser), server(node.js)) and I want just to add index.js file in my lib folder. And i have to modify it to work properly on server like so:

now:

(function(root) {
...main code here...
        try {
            if (root.getSlug || root.createSlug) {
                throw 'speakingurl: globals exists /(getSlug|createSlug)/';
            } else {
                root.getSlug = getSlug;
                root.createSlug = createSlug;
            }
        } catch (e) {}
})(this);

was:

(function() {
...main code here...
        try {
            if (window.getSlug || window.createSlug) {
                throw 'speakingurl: globals exists /(getSlug|createSlug)/';
            } else {
                window.getSlug = getSlug;
                window.createSlug = createSlug;
            }
        } catch (e) {}
})();

Can u comment on this please, why dont you attach getSlug to root context(this) passed throught anonymous function?

Russian/Bulgarian letter not interpreted!

Hello. I would like to ask what is the reason for the following interpretation:

'ъ': '',

This can be interpreted with the latin equivalent of 'a' or 'u'. Both would be understandable.

Rebuild speakingurl in CFML language

speakingurl does a wonderful job of converting virtually any text into a readable and SEO friendly string, suitable for use in a URL. I'm looking forward to replacing various half-hearted attempts to create such URLs with speakingurl. Thank you for this library.

I would like to rebuild a copy of speakingurl in the ColdFusion (CFML) language. The code would be open source, and written in CFML cfscript, but based heavily on the logic in your library.

For my open source projects, I like to use the LGPL to promote further open source contributions to the library. I don't believe there is a legal conflict between your BSD3 license and LGPL 2.1. Do you object to my using the LGPL license my derivation of speakingurl?

I'm a big fan of letting people know about existing projects my work is based on, and I will do the same with this project. Examples: jquery-load-json and cf-mailchimp.

Thank you

Custom map works different

It seems default mapping replaces my custom maps.

getSlug('буу', { custom: { 'б': 'б', 'у': 'у' } });
// result: buu
// desired result: буу

I don't want to transliterate cyrillic letters.

Translation needed: Serbian

           'sr': {
                '∆': 'delta',
                '∞': 'infinity',
                '♥': 'love',
                '&': 'and',
                '|': 'or',
                '<': 'less than',
                '>': 'greater than',
                '∑': 'sum',
                '¤': 'currency'
            },

!!! Translation must be already transliterated !!!

Custom replacements only match start of string

Because the customReplacements function uses "\b" in the regex, the custom replacement word must come after a non-character. If not, it wont be replaced.
Example: "Something" // Impossible to replace the phrase "thing"
var slugOptions = {
custom: {
'thing': 'one'
},
uric: true
};

Translation needed: Ukranian

           'uk': {
                '∆': 'delta',
                '∞': 'infinity',
                '♥': 'love',
                '&': 'and',
                '|': 'or',
                '<': 'less than',
                '>': 'greater than',
                '∑': 'sum',
                '¤': 'currency'
            },

!!! Translation must be already transliterated !!!

Translation needed: Latvian

           'lv': {
                '∆': 'delta',
                '∞': 'infinity',
                '♥': 'love',
                '&': 'and',
                '|': 'or',
                '<': 'less than',
                '>': 'greater than',
                '∑': 'sum',
                '¤': 'currency'
            },

!!! Translation must be already transliterated !!!

Why international words being translated into their english equivalents?

All major browsers support unicode urls so you can just leave the words as they are and not transform them into English.

If that's the case and you agree with me you can use my code in your project.

   var text = 'text in every language in the world';
   var XRegExp = require('xregexp');
   var slugRegEx = XRegExp('\\p{^L}+');
   XRegExp.replace(text, slugRegEx, '-').toLowerCase(); 

Add support for "black-listed" words

Hello,

The lib would be wonderful if we could add a list of "black listed" words. This would be super useful for short words (aka stop words) like "the", "a", "and" and the likes. Whatever the language by the way.

Incorrect type checking when looking for Node/AMD

Line 1363 and 1369, you're comparing a typeof against the undefined property instead of 'undefined' as a string.

In a browser, module.exports check is therefore executed resulting in a ReferenceError exception.

optional convert to title-case

Examples:

var options = {
    titleCase: ["to", "the"]
};
var mySlug = require('speakingurl').createSlug(options);

var slug = mySlug('welcome to the jungle');
console.log(slug); // Output: "Welcome-to-the-Jungle"
var options = {
    titleCase: true
};
var mySlug = require('speakingurl').createSlug(options);

var slug = mySlug('welcome to the jungle');
console.log(slug); // Output: "Welcome-To-The-Jungle"

Translation needed: Greek

           'gr': {
                '∆': 'delta',
                '∞': 'infinity',
                '♥': 'love',
                '&': 'and',
                '|': 'or',
                '<': 'less than',
                '>': 'greater than',
                '∑': 'sum',
                '¤': 'currency'
            },

!!! Translation must be already transliterated !!!

add symbols

add converting symbols to corresponding word (en/de), adding new option ie. {'lang': 'en'}

Convert number to string

can you check if (typeof input === 'number') input = input.toString();?

e.g. getSlug(44) should output '44' but it outputs ''

Errors in charmap

Misritten characters :

  • In Polish :
    • 'Ę': 'e' chould be 'Ę': 'E'
  • In Latvian
    • 'Ū': 'u' chould be 'Ū': 'U'

Add support for "black-listed" words

Hello,

The lib would be wonderful if we could add a list of black listed words. This would be super useful for short words for instance, like "the", "a", "and". Whatever the language by the way.

Translation needed: Azerbaijani

           'az': {
                '∆': 'delta',
                '∞': 'infinity',
                '♥': 'love',
                '&': 'and',
                '|': 'or',
                '<': 'less than',
                '>': 'greater than',
                '∑': 'sum',
                '¤': 'currency'
            },

!!! Translation must be already transliterated !!!

An ampersand at the end will cause a TypeError

While I can not think of many cases where you would want an ampersand at the end of something... it should not break speakingurl.

getSlug('test &');

/test/node_modules/speakingurl/lib/index.js:86
            ch += input[i + 1].match(/[A-Za-z0-9]/) ? separator : '';
                               ^
TypeError: Cannot call method 'match' of undefined
    at getSlug (/test/node_modules/speakingurl/lib/index.js:86:36)
    at Object.<anonymous> (/test/test.js:39:3)
    at Object.<anonymous> (/test/test.js:3137:4)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.runMain (module.js:492:10)
    at process.startup.processNextTick.process._tickCallback (node.js:245:9)

Characters translated to empty string are treated as word breaks

There are two cyrillic characters translated to empty string – Ъ and Ь.

Translating word with these characters works like there are two words: Пью > P-yu

To fix this change line 106 from
if (charMap[ch])
to
if (ch in charMap)
so you'll get Пью > Pyu as expected.

Translation needed: Lithuanian

           'lt': {
                '∆': 'delta',
                '∞': 'infinity',
                '♥': 'love',
                '&': 'and',
                '|': 'or',
                '<': 'less than',
                '>': 'greater than',
                '∑': 'sum',
                '¤': 'currency'
            },

!!! Translation must be already transliterated !!!

Add option to include non-latin characters

First of all, awesome library!

I would like to open a discussion for adding an option to support for non-latin characters.
As far as I see it, 99% of browsers would parse this example correctly without messing up the route:

http://www.my-site.com/article/עוגת-בננה-זה-טעים-מאוד
http://www.my-site.com/article/香蕉蛋糕都不错
http://www.my-site.com/article/كعكة-الموز-جيدة

If there's any reason this shouldn't be allowed, I would really like to learn why.

Thanks!

Turkish translation needed

'en': {
   '∆': 'delta',
   '∞': 'infinity',
   '♥': 'love',
   '&': 'and',
   '|': 'or',
   '<': 'less than',
   '>': 'greater than',
   '∑': 'sum',
   '¤': 'currency'
},

index.js - has to add "./" to get it to work with npm/node

Hi,

I did an "npm install speakingurl", but when I try to require it in the REPL, I get this:

$ npm install speakingurl                                                                                                                                       
npm http GET https://registry.npmjs.org/speakingurl
npm http GET https://registry.npmjs.org/speakingurl
npm http 200 https://registry.npmjs.org/speakingurl
npm http GET https://registry.npmjs.org/speakingurl/-/speakingurl-0.2.4.tgz
npm http 200 https://registry.npmjs.org/speakingurl/-/speakingurl-0.2.4.tgz
[email protected] node_modules/speakingurl%                                                                                                                                                      kimptoc:node-scratch/ $ node                                                                                                                                                          
> slug=require("speakingurl")
Error: Cannot find module 'lib/'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/Users/kimptoc/Dropbox/dev/tools/node-scratch/node_modules/speakingurl/index.js:1:80)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)

To fix this I changed speakingurl/index.js from:

module.exports = require('lib/');

to

module.exports = require('./lib/');

Would submit a PR, but not sure if this is the best way to fix this...

Regards,
Chris

russian example - speaking url is translating to english...

Hi,

I am looking to "slugify" the following: ревущий фьорд

I am hoping to get: ревущии-фьорд

This is what speakingurl currently does:

slug=require("speakingurl")
[Function: getSlug]
> slug("ревущий фьорд")
'revushij-ford'
> slug("ревущий фьорд",{lang:'ru'})
'revushij-ford'

Is there an option keep the original characters, but simplified (as I am hoping)?

For background, these are slugs that the World of Warcraft api uses - so I am trying to mimic what it does.. so, perhaps not the best way round of doing this...

Thanks,
Chris

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.