This commit is contained in:
parent
5ad77e8a3a
commit
bc3006f3c4
9 changed files with 92 additions and 17 deletions
19
src/common/text/elements/link.js
Normal file
19
src/common/text/elements/link.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* Link
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = text => {
|
||||||
|
const match = text.match(/^\??\[(.+?)\]\((https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.=\+\-]+)\)/);
|
||||||
|
if (!match) return null;
|
||||||
|
const silent = text[0] == '?';
|
||||||
|
const link = match[0];
|
||||||
|
const title = match[1];
|
||||||
|
const url = match[2];
|
||||||
|
return {
|
||||||
|
type: 'link',
|
||||||
|
content: link,
|
||||||
|
title: title,
|
||||||
|
url: url,
|
||||||
|
silent: silent
|
||||||
|
};
|
||||||
|
};
|
|
@ -3,11 +3,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = text => {
|
module.exports = text => {
|
||||||
const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.=\+\-]+/);
|
const match = text.match(/^https?:\/\/[\w\/:%#@\$&\?!\(\)\[\]~\.=\+\-]+/);
|
||||||
if (!match) return null;
|
if (!match) return null;
|
||||||
const link = match[0];
|
const url = match[0];
|
||||||
return {
|
return {
|
||||||
type: 'link',
|
type: 'url',
|
||||||
content: link
|
content: url,
|
||||||
|
url: url
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
const elements = [
|
const elements = [
|
||||||
require('./elements/bold'),
|
require('./elements/bold'),
|
||||||
require('./elements/url'),
|
require('./elements/url'),
|
||||||
|
require('./elements/link'),
|
||||||
require('./elements/mention'),
|
require('./elements/mention'),
|
||||||
require('./elements/hashtag'),
|
require('./elements/hashtag'),
|
||||||
require('./elements/code'),
|
require('./elements/code'),
|
||||||
|
|
|
@ -21,8 +21,10 @@ module.exports = (tokens, shouldBreak) => {
|
||||||
.replace(/(\r\n|\n|\r)/g, shouldBreak ? '<br>' : ' ');
|
.replace(/(\r\n|\n|\r)/g, shouldBreak ? '<br>' : ' ');
|
||||||
case 'bold':
|
case 'bold':
|
||||||
return '<strong>' + escape(token.bold) + '</strong>';
|
return '<strong>' + escape(token.bold) + '</strong>';
|
||||||
case 'link':
|
case 'url':
|
||||||
return '<mk-url href="' + escape(token.content) + '" target="_blank"></mk-url>';
|
return '<mk-url href="' + escape(token.content) + '" target="_blank"></mk-url>';
|
||||||
|
case 'link':
|
||||||
|
return '<a class="link" href="' + escape(token.url) + '" target="_blank">' + escape(token.title) + '</a>';
|
||||||
case 'mention':
|
case 'mention':
|
||||||
return '<a href="' + CONFIG.url + '/' + escape(token.username) + '" target="_blank" data-user-preview="' + token.content + '" ' + (me && me.username == token.username ? 'data-is-me' : '') + '>' + token.content + '</a>';
|
return '<a href="' + CONFIG.url + '/' + escape(token.username) + '" target="_blank" data-user-preview="' + token.content + '" ' + (me && me.username == token.username ? 'data-is-me' : '') + '>' + token.content + '</a>';
|
||||||
case 'hashtag': // TODO
|
case 'hashtag': // TODO
|
||||||
|
|
|
@ -233,6 +233,16 @@
|
||||||
font-size 1.5em
|
font-size 1.5em
|
||||||
color #717171
|
color #717171
|
||||||
|
|
||||||
|
.link
|
||||||
|
&:after
|
||||||
|
content "\f14c"
|
||||||
|
display inline-block
|
||||||
|
padding-left 2px
|
||||||
|
font-family FontAwesome
|
||||||
|
font-size .9em
|
||||||
|
font-weight 400
|
||||||
|
font-style normal
|
||||||
|
|
||||||
> mk-url-preview
|
> mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
|
@ -367,10 +377,10 @@
|
||||||
|
|
||||||
// URLをプレビュー
|
// URLをプレビュー
|
||||||
tokens
|
tokens
|
||||||
.filter(t => t.type == 'link')
|
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
|
||||||
.map(t => {
|
.map(t => {
|
||||||
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
||||||
url: t.content
|
url: t.url
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -229,6 +229,16 @@
|
||||||
mk-url-preview
|
mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
|
.link
|
||||||
|
&:after
|
||||||
|
content "\f14c"
|
||||||
|
display inline-block
|
||||||
|
padding-left 2px
|
||||||
|
font-family FontAwesome
|
||||||
|
font-size .9em
|
||||||
|
font-weight 400
|
||||||
|
font-style normal
|
||||||
|
|
||||||
> .reply
|
> .reply
|
||||||
margin-right 8px
|
margin-right 8px
|
||||||
color #717171
|
color #717171
|
||||||
|
@ -344,10 +354,10 @@
|
||||||
|
|
||||||
// URLをプレビュー
|
// URLをプレビュー
|
||||||
tokens
|
tokens
|
||||||
.filter(t => t.type == 'link')
|
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
|
||||||
.map(t => {
|
.map(t => {
|
||||||
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
||||||
url: t.content
|
url: t.url
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,6 +230,16 @@
|
||||||
@media (min-width 500px)
|
@media (min-width 500px)
|
||||||
font-size 24px
|
font-size 24px
|
||||||
|
|
||||||
|
.link
|
||||||
|
&:after
|
||||||
|
content "\f14c"
|
||||||
|
display inline-block
|
||||||
|
padding-left 2px
|
||||||
|
font-family FontAwesome
|
||||||
|
font-size .9em
|
||||||
|
font-weight 400
|
||||||
|
font-style normal
|
||||||
|
|
||||||
> mk-url-preview
|
> mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
|
@ -368,10 +378,10 @@
|
||||||
|
|
||||||
// URLをプレビュー
|
// URLをプレビュー
|
||||||
tokens
|
tokens
|
||||||
.filter(t => t.type == 'link')
|
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
|
||||||
.map(t => {
|
.map(t => {
|
||||||
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
||||||
url: t.content
|
url: t.url
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,16 @@
|
||||||
> .dummy
|
> .dummy
|
||||||
display none
|
display none
|
||||||
|
|
||||||
|
.link
|
||||||
|
&:after
|
||||||
|
content "\f14c"
|
||||||
|
display inline-block
|
||||||
|
padding-left 2px
|
||||||
|
font-family FontAwesome
|
||||||
|
font-size .9em
|
||||||
|
font-weight 400
|
||||||
|
font-style normal
|
||||||
|
|
||||||
mk-url-preview
|
mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
|
@ -318,10 +328,10 @@
|
||||||
|
|
||||||
// URLをプレビュー
|
// URLをプレビュー
|
||||||
tokens
|
tokens
|
||||||
.filter(t => t.type == 'link')
|
.filter(t => (t.type == 'url' || t.type == 'link') && !t.silent)
|
||||||
.map(t => {
|
.map(t => {
|
||||||
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
riot.mount(this.refs.text.appendChild(document.createElement('mk-url-preview')), {
|
||||||
url: t.content
|
url: t.url
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
20
test/text.js
20
test/text.js
|
@ -49,11 +49,23 @@ describe('Text', () => {
|
||||||
], tokens);
|
], tokens);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('link', () => {
|
it('url', () => {
|
||||||
const tokens = analyze('https://himasaku.net');
|
const tokens = analyze('https://himasaku.net');
|
||||||
assert.deepEqual([
|
assert.deepEqual([{
|
||||||
{ type: 'link', content: 'https://himasaku.net' }
|
type: 'url',
|
||||||
], tokens);
|
content: 'https://himasaku.net',
|
||||||
|
url: 'https://himasaku.net'
|
||||||
|
}], tokens);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('link', () => {
|
||||||
|
const tokens = analyze('[ひまさく](https://himasaku.net)');
|
||||||
|
assert.deepEqual([{
|
||||||
|
type: 'link',
|
||||||
|
content: '[ひまさく](https://himasaku.net)',
|
||||||
|
title: 'ひまさく',
|
||||||
|
url: 'https://himasaku.net'
|
||||||
|
}], tokens);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('emoji', () => {
|
it('emoji', () => {
|
||||||
|
|
Loading…
Reference in a new issue