From 58524fe5344684700a25adbb7991d3054a588a08 Mon Sep 17 00:00:00 2001 From: Yuichi Yogo Date: Wed, 24 Mar 2021 08:52:01 +0900 Subject: [PATCH 1/6] fix re-render issue on props change --- index.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index bc98bd9..2d4ea87 100644 --- a/index.js +++ b/index.js @@ -2,8 +2,21 @@ import linkify from 'linkifyjs/html' (function () { - function install (el, binding) { - el.innerHTML = linkify(el.innerHTML, binding.value) + function surround (tagName, content) { + return `<${tagName}>${content}` + } + + function traverse (vnode, binding) { + const { text, tag, children } = vnode + if (text) return linkify(text, binding) + if (children) { + const content = children.map(childVNode => traverse(childVNode, binding)).join('') + return surround(tag, content) + } + } + + function install (el, binding, vnode) { + el.innerHTML = traverse(vnode, binding) } if (typeof exports === 'object') { From 7ca04d4c069af0c92c97273cbf9a68afa3e5ae8c Mon Sep 17 00:00:00 2001 From: Yuichi Yogo Date: Wed, 24 Mar 2021 08:52:12 +0900 Subject: [PATCH 2/6] fix test command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c47d33e..12484d6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "lint": "./node_modules/.bin/eslint index.js", "build": "./node_modules/.bin/eslint index.js && BABEL_ENV=production && babel index.js -o ./dist/vue-linkify.min.js", - "test": "npm build && karma start test/unit/karma.conf.js --single-run" + "test": "npm run build && karma start test/unit/karma.conf.js --single-run" }, "keywords": [ "vue", From dba9a8cb24965efa4060f99c1a1bdd6cae324734 Mon Sep 17 00:00:00 2001 From: Yuichi Yogo Date: Wed, 24 Mar 2021 08:54:54 +0900 Subject: [PATCH 3/6] respectively handle cases when either v-html is used or not --- index.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 2d4ea87..cc1d718 100644 --- a/index.js +++ b/index.js @@ -6,17 +6,23 @@ import linkify from 'linkifyjs/html' return `<${tagName}>${content}` } - function traverse (vnode, binding) { + function traverse (vnode, opts) { const { text, tag, children } = vnode - if (text) return linkify(text, binding) + if (text) return linkify(text, opts) if (children) { - const content = children.map(childVNode => traverse(childVNode, binding)).join('') + const content = children.map(childVNode => traverse(childVNode, opts)).join('') return surround(tag, content) } } function install (el, binding, vnode) { - el.innerHTML = traverse(vnode, binding) + if (vnode.data.domProps && vnode.data.domProps.innerHTML) { + // when v-html is used + el.innerHTML = linkify(el.innerHTML, binding.value) + } else { + // when `{{}}` syntax is used + el.innerHTML = traverse(vnode, binding.value) + } } if (typeof exports === 'object') { From 73100fb5566c85c2f887b479ec09ed5dc3a2d76a Mon Sep 17 00:00:00 2001 From: Yuichi Yogo Date: Wed, 24 Mar 2021 09:00:35 +0900 Subject: [PATCH 4/6] add tests for {{}} support --- test/unit/index.js | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/test/unit/index.js b/test/unit/index.js index 17db9d1..1ffde3a 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -25,4 +25,46 @@ describe('vue-linkify', () => { expect(vm.$el.innerHTML).to.be .equal('Hello from vuejs.org') }) + + it('should correctly linkify content with {{}} syntax', () => { + const vm = new Vue({ + el: document.createElement('div'), + data: { + msg: 'https://vuejs.org' + }, + template: 'Site url: {{ msg }}' + }).$mount() + + expect(vm.$el.innerHTML).to.be + .equal('Site url: https://vuejs.org') + }) + + it('should correctly linkify content with {{}} syntax and options', () => { + const vm = new Vue({ + el: document.createElement('div'), + data: { + msg: 'https://vuejs.org' + }, + template: 'Site url: {{ msg }}' + }).$mount() + + expect(vm.$el.innerHTML).to.be + .equal('Site url: https://vuejs.org') + }) + + it('should correctly linkify content with {{}} even after update', () => { + const vm = new Vue({ + el: document.createElement('div'), + data: { + msg: 'https://vuejs.org' + }, + template: 'Site url: {{ msg }}' + }).$mount() + + vm.msg = 'https://reactjs.org' + Vue.nextTick(() => { + expect(vm.$el.innerHTML).to.be + .equal('Site url: https://reactjs.org') + }) + }) }) From 062356904aaa53642de5eff7f28a470b95274481 Mon Sep 17 00:00:00 2001 From: Yuichi Yogo Date: Wed, 24 Mar 2021 09:01:26 +0900 Subject: [PATCH 5/6] build --- dist/vue-linkify.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/vue-linkify.min.js b/dist/vue-linkify.min.js index f46c0f9..b434192 100644 --- a/dist/vue-linkify.min.js +++ b/dist/vue-linkify.min.js @@ -1 +1 @@ -'use strict';var _typeof='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&'function'==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?'symbol':typeof obj};/*global define*/var _html=require('linkifyjs/html'),_html2=_interopRequireDefault(_html);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}(function(){function a(b,c){b.innerHTML=(0,_html2.default)(b.innerHTML,c.value)}'object'==('undefined'==typeof exports?'undefined':_typeof(exports))?module.exports=a:'function'==typeof define&&define.amd?define([],function(){return a}):window.Vue&&window.Vue.directive('linkified',a)})(); +'use strict';var _typeof='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&'function'==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?'symbol':typeof obj};/*global define*/var _html=require('linkifyjs/html'),_html2=_interopRequireDefault(_html);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}(function(){function a(d,e){return'<'+d+'>'+e+''}function b(d,e){var f=d.text,g=d.tag,h=d.children;if(f)return(0,_html2.default)(f,e);if(h){var i=h.map(function(j){return b(j,e)}).join('');return a(g,i)}}function c(d,e,f){d.innerHTML=f.data.domProps&&f.data.domProps.innerHTML?(0,_html2.default)(d.innerHTML,e.value):b(f,e.value)}'object'==('undefined'==typeof exports?'undefined':_typeof(exports))?module.exports=c:'function'==typeof define&&define.amd?define([],function(){return c}):window.Vue&&window.Vue.directive('linkified',c)})(); From 89a3e95a7ef685e77d524f80481e01c348e5fb05 Mon Sep 17 00:00:00 2001 From: Yuichi Yogo Date: Wed, 24 Mar 2021 09:18:15 +0900 Subject: [PATCH 6/6] fix: remove duplicate parent tag --- dist/vue-linkify.min.js | 2 +- index.js | 8 +++++--- test/unit/index.js | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/dist/vue-linkify.min.js b/dist/vue-linkify.min.js index b434192..4bd2a58 100644 --- a/dist/vue-linkify.min.js +++ b/dist/vue-linkify.min.js @@ -1 +1 @@ -'use strict';var _typeof='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&'function'==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?'symbol':typeof obj};/*global define*/var _html=require('linkifyjs/html'),_html2=_interopRequireDefault(_html);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}(function(){function a(d,e){return'<'+d+'>'+e+''}function b(d,e){var f=d.text,g=d.tag,h=d.children;if(f)return(0,_html2.default)(f,e);if(h){var i=h.map(function(j){return b(j,e)}).join('');return a(g,i)}}function c(d,e,f){d.innerHTML=f.data.domProps&&f.data.domProps.innerHTML?(0,_html2.default)(d.innerHTML,e.value):b(f,e.value)}'object'==('undefined'==typeof exports?'undefined':_typeof(exports))?module.exports=c:'function'==typeof define&&define.amd?define([],function(){return c}):window.Vue&&window.Vue.directive('linkified',c)})(); +'use strict';var _typeof='function'==typeof Symbol&&'symbol'==typeof Symbol.iterator?function(obj){return typeof obj}:function(obj){return obj&&'function'==typeof Symbol&&obj.constructor===Symbol&&obj!==Symbol.prototype?'symbol':typeof obj};/*global define*/var _html=require('linkifyjs/html'),_html2=_interopRequireDefault(_html);function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}(function(){function a(d,e){return'<'+d+'>'+e+''}function b(d,e,f){var g=d.text,h=d.tag,i=d.children;if(g)return(0,_html2.default)(g,e);if(i){var j=i.map(function(k){return b(k,e,!1)}).join('');return f?j:a(h,j)}}function c(d,e,f){d.innerHTML=f.data.domProps&&f.data.domProps.innerHTML?(0,_html2.default)(d.innerHTML,e.value):b(f,e.value,!0)}'object'==('undefined'==typeof exports?'undefined':_typeof(exports))?module.exports=c:'function'==typeof define&&define.amd?define([],function(){return c}):window.Vue&&window.Vue.directive('linkified',c)})(); diff --git a/index.js b/index.js index cc1d718..d3db1da 100644 --- a/index.js +++ b/index.js @@ -6,11 +6,12 @@ import linkify from 'linkifyjs/html' return `<${tagName}>${content}` } - function traverse (vnode, opts) { + function traverse (vnode, opts, isParent) { const { text, tag, children } = vnode if (text) return linkify(text, opts) if (children) { - const content = children.map(childVNode => traverse(childVNode, opts)).join('') + const content = children.map(childVNode => traverse(childVNode, opts, false)).join('') + if (isParent) return content return surround(tag, content) } } @@ -21,7 +22,8 @@ import linkify from 'linkifyjs/html' el.innerHTML = linkify(el.innerHTML, binding.value) } else { // when `{{}}` syntax is used - el.innerHTML = traverse(vnode, binding.value) + const isParent = true + el.innerHTML = traverse(vnode, binding.value, isParent) } } diff --git a/test/unit/index.js b/test/unit/index.js index 1ffde3a..700c133 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -36,7 +36,7 @@ describe('vue-linkify', () => { }).$mount() expect(vm.$el.innerHTML).to.be - .equal('Site url: https://vuejs.org') + .equal('Site url: https://vuejs.org') }) it('should correctly linkify content with {{}} syntax and options', () => { @@ -49,7 +49,7 @@ describe('vue-linkify', () => { }).$mount() expect(vm.$el.innerHTML).to.be - .equal('Site url: https://vuejs.org') + .equal('Site url: https://vuejs.org') }) it('should correctly linkify content with {{}} even after update', () => { @@ -64,7 +64,7 @@ describe('vue-linkify', () => { vm.msg = 'https://reactjs.org' Vue.nextTick(() => { expect(vm.$el.innerHTML).to.be - .equal('Site url: https://reactjs.org') + .equal('Site url: https://reactjs.org') }) }) })