Skip to content

Commit 75e673e

Browse files
author
Nick Frasser
committed
IE8 Support (#137)
* Better IE8 support for element and HTML interfaces * Build updates for better IE8 support * QUnit test updates for IE8 support * Karma tests now only run qunit. Mocha tests will test logic/behaviour, Karma ensures test browser functionality * Ensure correct jquery version is used for CI tests * Additional render possibility to get IE8 to work * IE8 readme docs [ci skip]
1 parent 7f58815 commit 75e673e

30 files changed

+406
-172
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,8 @@ env:
77
global:
88
- secure: LhH+mMqOktTe6cIt97PGKBfgUjZM8vRd0qddyg61FSxg7a3WrHQoHE8WdRioJ9+DDzpu/NSTsHEUFUpGN+kSRw1UY4tsNLH6HoBQnqrNN4tVOeefudJpdeteOKZrJ8r8TaA/eO7sAgXO2T+RLJ8+qTbhx8FVZtLaCAgkrS0w9Qk=
99
- secure: Okwm1aAR3oo09AhHDsjFSq1UGlIUtWYYvYeoolJScC/UVFGMiK9oC4fzRtUHv3kXcnshDlcVDrr/Q5JL9Qx6E+tosPJp+tioaqE8X4IDbVk7PPs/ToOOEmWnGvxkgmfCGSDuneG8RVhILkhls3fbm0z+rRWlvJkjefeA96T6zps=
10+
install:
11+
- npm install
12+
- npm install jquery@1
1013
script: ./run-tests.sh
1114
after_script: npm run coverage

README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ __Jump to__
2020
- [Node.js/Browserify](#node-js-browserify)
2121
- [AMD Modules](#amd-modules)
2222
- [Browser](#browser)
23+
- [Internet Explorer](#internet-explorer)
2324
- [Downloads](#downloads)
2425
- [API Documentation](#api-documentation)
2526
- [Caveats](#caveats)
@@ -33,7 +34,7 @@ __Jump to__
3334
* **Extensibility**<br>Linkify is designed to be fast and lightweight, but comes with a powerful plugin API that lets you detect even more information like #hashtags and @mentions.
3435
* **Small footprint**<br>Linkify and its jQuery interface clock in at approximately 15KB minified (5KB gzipped) - approximately 50% the size of Twitter Text
3536
* **Modern implementation**<br>Linkify is written in ECMAScript6 and compiles to ES5 for modern JavaScript runtimes.
36-
* Linkify is compatible with all modern browsers, as well as Internet Explorer 9 and up. Full IE8 support coming soon.
37+
* Linkify is compatible with all modern browsers, as well as Internet Explorer 8 and up.
3738

3839
## Demo
3940
[Launch demo](http://soapbox.github.io/linkifyjs/)
@@ -64,6 +65,8 @@ Add [linkify](https://github.com/nfrasser/linkify-shim/raw/master/linkify.min.js
6465
<script src="linkify-jquery.min.js"></script>
6566
```
6667

68+
**Note:** A [polyfill](#internet-explorer) is required for Internet Explorer 8.
69+
6770
#### Find all links and convert them to anchor tags
6871

6972
```js
@@ -167,6 +170,22 @@ var htmlStr = linkifyStr('Check out soapboxhq.com it is great!');
167170
$('p').linkify();
168171
```
169172

173+
## Internet Explorer
174+
175+
Linkify natively supports Internet Explorer 9 and above. Internet Explorer 8 is supported with a polyfill.
176+
177+
You can use either [es5-shim](https://github.com/es-shims/es5-shim) (sham also required) or the provided `linkify-polyfill.js`:
178+
179+
```html
180+
<script src="jquery.js"></script>
181+
182+
<!--[if IE 8]>
183+
<script src="linkify-polyfill.js"></script>
184+
<![endif]-->
185+
<script src="linkify.js"></script>
186+
<script src="linkify-jquery.js"></script>
187+
```
188+
170189
## Downloads
171190

172191
Download the [**latest release**](https://github.com/SoapBox/linkifyjs/releases) or clone the [**build repository**](https://github.com/nfrasser/linkify-shim).

gulpfile.js

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,17 @@ const concat = require('gulp-concat');
1616
const istanbul = require('gulp-istanbul');
1717
const jshint = require('gulp-jshint');
1818
const mocha = require('gulp-mocha');
19-
const qunit = require('gulp-qunit');
2019
const rename = require('gulp-rename');
2120
const replace = require('gulp-replace');
2221
const uglify = require('gulp-uglify');
2322
const wrap = require('gulp-wrap');
2423

2524
const rollup = require('./tasks/rollup');
25+
const quickEs3 = require('./tasks/quick-es3');
2626

2727
var paths = {
2828
src: 'src/**/*.js',
29-
srcCore: [
30-
'src/linkify/core/*.js',
31-
'src/linkify/utils/*.js',
32-
'src/linkify.js'
33-
],
29+
srcCore: 'src/linkify.js',
3430
lib: ['lib/**/*.js'],
3531
libTest: ['lib/*.js', 'lib/linkify/**/*.js'],
3632
libCore: [
@@ -41,7 +37,8 @@ var paths = {
4137
amd: 'build/amd/**/*.js',
4238
test: 'test/index.js',
4339
spec: 'test/spec/**.js',
44-
qunit: 'test/qunit/*html'
40+
qunit: 'test/qunit/**.js',
41+
polyfill: 'polyfill.js'
4542
};
4643

4744
var tldsReplaceStr = `'${tlds.join('|')}'.split('|')`;
@@ -74,14 +71,15 @@ gulp.task('babel-amd', () =>
7471
.pipe(gulp.dest('build/amd')) // Required for building plugins separately
7572
.pipe(amdOptimize('linkify'))
7673
.pipe(concat('linkify.amd.js'))
74+
.pipe(quickEs3())
7775
.pipe(gulp.dest('build'))
7876
);
7977

8078
/**
8179
Build core linkify.js
8280
*/
8381
gulp.task('build-core', () =>
84-
gulp.src('src/linkify.js', {read: false})
82+
gulp.src(paths.srcCore, {read: false})
8583
.pipe(rollup({
8684
bundle: {
8785
format: 'iife',
@@ -159,6 +157,7 @@ gulp.task('build-interfaces', () => {
159157
stream = gulp.src(files.amd)
160158
.pipe(concat(`linkify-${intrface}.amd.js`))
161159
.pipe(wrap({src: `templates/linkify-${intrface}.amd.js`}))
160+
.pipe(quickEs3())
162161
.pipe(gulp.dest('build'));
163162

164163
streams.push(stream);
@@ -202,6 +201,7 @@ gulp.task('build-plugins', () => {
202201
stream = gulp.src(`build/amd/linkify/plugins/${plugin}.js`)
203202
.pipe(wrap({src: `templates/linkify/plugins/${plugin}.amd.js`}))
204203
.pipe(concat(`linkify-plugin-${plugin}.amd.js`))
204+
.pipe(quickEs3())
205205
.pipe(gulp.dest('build'));
206206
streams.push(stream);
207207

@@ -210,20 +210,27 @@ gulp.task('build-plugins', () => {
210210
return merge.apply(this, streams);
211211
});
212212

213+
gulp.task('build-polyfill', () =>
214+
gulp.src(paths.polyfill)
215+
.pipe(concat('linkify-polyfill.js'))
216+
.pipe(gulp.dest('build'))
217+
);
218+
213219
// Build steps
214220
gulp.task('build', [
215221
'babel',
216222
'babel-amd',
217223
'build-core',
218224
'build-interfaces',
219-
'build-plugins'
225+
'build-plugins',
226+
'build-polyfill'
220227
], (cb) => { cb(); });
221228

222229
/**
223230
Lint using jshint
224231
*/
225232
gulp.task('jshint', () =>
226-
gulp.src([paths.src, paths.test, paths.spec])
233+
gulp.src([paths.src, paths.test, paths.spec, paths.qunit])
227234
.pipe(jshint())
228235
.pipe(jshint.reporter(stylish))
229236
.pipe(jshint.reporter('fail'))
@@ -232,15 +239,15 @@ gulp.task('jshint', () =>
232239
/**
233240
Run mocha tests
234241
*/
235-
gulp.task('mocha', ['build'], () =>
242+
gulp.task('mocha', ['jshint', 'build'], () =>
236243
gulp.src(paths.test, {read: false})
237244
.pipe(mocha())
238245
);
239246

240247
/**
241248
Code coverage reort for mocha tests
242249
*/
243-
gulp.task('coverage', ['build'], (callback) => {
250+
gulp.task('coverage', ['jshint', 'build'], (callback) => {
244251
// IMPORTANT: return not required here (and will actually cause bugs!)
245252
gulp.src(paths.libTest)
246253
.pipe(istanbul()) // Covering files
@@ -253,33 +260,65 @@ gulp.task('coverage', ['build'], (callback) => {
253260
});
254261
});
255262

256-
gulp.task('karma', ['build'], (callback) => {
263+
gulp.task('karma', (callback) => {
257264
let server = new Server({
258265
configFile: __dirname + '/test/dev.conf.js',
259266
singleRun: true
260267
}, callback);
261268
return server.start();
262269
});
263270

264-
gulp.task('karma-chrome', ['build'], (callback) => {
271+
gulp.task('karma-chrome', (callback) => {
265272
let server = new Server({
266273
configFile: __dirname + '/test/chrome.conf.js',
267274
}, callback);
268275
return server.start();
269276
});
270277

271-
gulp.task('karma-ci', ['build'], (callback) => {
278+
gulp.task('karma-firefox', (callback) => {
279+
let server = new Server({
280+
configFile: __dirname + '/test/firefox.conf.js',
281+
}, callback);
282+
return server.start();
283+
});
284+
285+
gulp.task('karma-ci', (callback) => {
272286
let server = new Server({
273287
configFile: __dirname + '/test/ci.conf.js',
274288
singleRun: true
275289
}, callback);
276290
return server.start();
277291
});
278292

279-
gulp.task('qunit', ['build'], () =>
280-
gulp.src(paths.qunit)
281-
.pipe(qunit())
282-
);
293+
gulp.task('karma-amd', (callback) => {
294+
let server = new Server({
295+
configFile: __dirname + '/test/dev.amd.conf.js',
296+
singleRun: true
297+
}, callback);
298+
return server.start();
299+
});
300+
301+
gulp.task('karma-amd-chrome', (callback) => {
302+
let server = new Server({
303+
configFile: __dirname + '/test/chrome.amd.conf.js',
304+
}, callback);
305+
return server.start();
306+
});
307+
308+
gulp.task('karma-amd-firefox', (callback) => {
309+
let server = new Server({
310+
configFile: __dirname + '/test/firefox.amd.conf.js',
311+
}, callback);
312+
return server.start();
313+
});
314+
315+
gulp.task('karma-amd-ci', (callback) => {
316+
let server = new Server({
317+
configFile: __dirname + '/test/ci.amd.conf.js',
318+
singleRun: true
319+
}, callback);
320+
return server.start();
321+
});
283322

284323
// Build the deprecated legacy interface
285324
gulp.task('build-legacy', ['build'], () =>
@@ -322,14 +361,15 @@ gulp.task('uglify', ['build-legacy'], () => {
322361

323362
gulp.task('dist', ['uglify']);
324363
gulp.task('test', (callback) =>
325-
runSequence('jshint', 'qunit', 'coverage', callback)
364+
runSequence('coverage', 'karma', 'karma-amd', callback)
365+
);
366+
gulp.task('test-ci', (callback) =>
367+
runSequence('karma-ci', 'karma-amd-ci', callback)
326368
);
327-
gulp.task('test-ci', ['karma-ci']);
328-
// Using with other tasks causes an error here for some reason
329369

330370
/**
331371
Build JS and begin watching for changes
332372
*/
333-
gulp.task('default', ['babel'], () =>
334-
gulp.watch(paths.src, ['babel'])
373+
gulp.task('default', ['jshint', 'babel'], () =>
374+
gulp.watch(paths.src, ['jshint', 'babel'])
335375
);

package.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
"babel-plugin-transform-es2015-modules-amd": "^6.6.5",
3434
"babel-preset-es2015": "^6.6.0",
3535
"babel-preset-es2015-loose": "^7.0.0",
36-
"brfs": "^1.4.1",
37-
"browserify": "^13.0.0",
3836
"coveralls": "^2.11.4",
3937
"expect.js": "^0.3.1",
4038
"glob": "^7.0.3",
@@ -44,7 +42,6 @@
4442
"gulp-istanbul": "^0.10.2",
4543
"gulp-jshint": "^2.0.0",
4644
"gulp-mocha": "^2.1.3",
47-
"gulp-qunit": "^1.3.0",
4845
"gulp-rename": "^1.2.0",
4946
"gulp-replace": "^0.5.4",
5047
"gulp-uglify": "^1.4.2",
@@ -54,17 +51,17 @@
5451
"jshint": "^2.9.1",
5552
"jshint-stylish": "^2.0.1",
5653
"karma": "^0.13.15",
57-
"karma-browserify": "^5.0.3",
5854
"karma-chrome-launcher": "^0.2.1",
5955
"karma-firefox-launcher": "^0.1.6",
60-
"karma-mocha": "^0.2.0",
6156
"karma-phantomjs-launcher": "^1.0.0",
57+
"karma-qunit": "^1.0.0",
6258
"karma-sauce-launcher": "^0.3.0",
59+
"lazypipe": "^1.0.1",
6360
"lodash": "^4.11.1",
6461
"merge-stream": "^1.0.0",
6562
"mocha": "^2.3.3",
6663
"phantomjs-prebuilt": "^2.1.7",
67-
"qunitjs": "^2.0.0-rc1",
64+
"qunitjs": ">=1.23.1",
6865
"requirejs": "^2.1.22",
6966
"rollup": "^0.26.0",
7067
"run-sequence": "^1.1.5",

polyfill.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
(function () {
2+
if (typeof Object.freeze != 'function') {
3+
Object.freeze = function (obj) { return obj; }
4+
}
5+
if (typeof Object.create != 'function') {
6+
Object.create = (function() {
7+
var Temp = function() {};
8+
return function (prototype) {
9+
if(prototype !== Object(prototype) && prototype !== null) {
10+
throw TypeError('Argument must be an object or null');
11+
}
12+
if (prototype === null) {
13+
throw Error('null [[Prototype]] not supported');
14+
}
15+
Temp.prototype = prototype;
16+
var result = new Temp();
17+
Temp.prototype = null;
18+
return result;
19+
};
20+
})();
21+
}
22+
23+
if (typeof Object.defineProperty != 'function') {
24+
Object.defineProperty = function defineProperty(object, property, descriptor) {
25+
if ('value' in descriptor) {
26+
object[property] = descriptor.value;
27+
}
28+
return object;
29+
};
30+
}
31+
32+
if (!Array.prototype.indexOf) {
33+
Array.prototype.indexOf = function (searchElement, fromIndex) {
34+
var k;
35+
if (this == null) {
36+
throw new TypeError('"this" is null or not defined');
37+
}
38+
var o = Object(this);
39+
var len = o.length >>> 0;
40+
if (len === 0) {
41+
return -1;
42+
}
43+
var n = +fromIndex || 0;
44+
if (Math.abs(n) === Infinity) {
45+
n = 0;
46+
}
47+
if (n >= len) {
48+
return -1;
49+
}
50+
k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
51+
while (k < len) {
52+
if (k in o && o[k] === searchElement) {
53+
return k;
54+
}
55+
k++;
56+
}
57+
return -1;
58+
};
59+
}
60+
})();

src/linkify-element.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ function linkifyElementHelper(element, opts, doc) {
9797
let ignoreTags = opts.ignoreTags;
9898

9999
// Is this element already a link?
100-
if (element.tagName === 'A' || ignoreTags.indexOf(element.tagName) >= 0) {
100+
if (element.tagName === 'A' || options.contains(ignoreTags, element.tagName)) {
101101
// No need to linkify
102102
return element;
103103
}

src/linkify-html.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import HTML5Tokenizer from './simple-html-tokenizer';
22
import * as linkify from './linkify';
33

4+
const options = linkify.options;
45
const StartTag = 'StartTag';
56
const EndTag = 'EndTag';
67
const Chars = 'Chars';
@@ -27,7 +28,8 @@ export default function linkifyHtml(str, opts={}) {
2728

2829
// Ignore all the contents of ignored tags
2930
let tagName = token.tagName.toUpperCase();
30-
let isIgnored = tagName === 'A' || opts.ignoreTags.indexOf(tagName) >= 0;
31+
let isIgnored = tagName === 'A' ||
32+
options.contains(opts.ignoreTags, tagName);
3133
if (!isIgnored) continue;
3234

3335
let preskipLen = linkifiedTokens.length;

0 commit comments

Comments
 (0)