This commit is contained in:
parent
d24bb24c6e
commit
68dd705500
5 changed files with 77 additions and 15 deletions
14
src/api/common/text/elements/quote.ts
Normal file
14
src/api/common/text/elements/quote.ts
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* Quoted text
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = text => {
|
||||||
|
const match = text.match(/^"([\s\S]+?)\n"/);
|
||||||
|
if (!match) return null;
|
||||||
|
const quote = match[0];
|
||||||
|
return {
|
||||||
|
type: 'quote',
|
||||||
|
content: quote,
|
||||||
|
quote: quote.substr(1, quote.length - 2).trim(),
|
||||||
|
};
|
||||||
|
};
|
|
@ -10,6 +10,7 @@ const elements = [
|
||||||
require('./elements/hashtag'),
|
require('./elements/hashtag'),
|
||||||
require('./elements/code'),
|
require('./elements/code'),
|
||||||
require('./elements/inline-code'),
|
require('./elements/inline-code'),
|
||||||
|
require('./elements/quote'),
|
||||||
require('./elements/emoji')
|
require('./elements/emoji')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -33,12 +34,12 @@ export default (source: string) => {
|
||||||
// パース
|
// パース
|
||||||
while (source != '') {
|
while (source != '') {
|
||||||
const parsed = elements.some(el => {
|
const parsed = elements.some(el => {
|
||||||
let tokens = el(source, i);
|
let _tokens = el(source, i);
|
||||||
if (tokens) {
|
if (_tokens) {
|
||||||
if (!Array.isArray(tokens)) {
|
if (!Array.isArray(_tokens)) {
|
||||||
tokens = [tokens];
|
_tokens = [_tokens];
|
||||||
}
|
}
|
||||||
tokens.forEach(push);
|
_tokens.forEach(push);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -3,6 +3,10 @@ import * as emojilib from 'emojilib';
|
||||||
import { url } from '../../../config';
|
import { url } from '../../../config';
|
||||||
import MkUrl from './url.vue';
|
import MkUrl from './url.vue';
|
||||||
|
|
||||||
|
const flatten = list => list.reduce(
|
||||||
|
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
|
||||||
|
);
|
||||||
|
|
||||||
export default Vue.component('mk-post-html', {
|
export default Vue.component('mk-post-html', {
|
||||||
props: {
|
props: {
|
||||||
ast: {
|
ast: {
|
||||||
|
@ -19,20 +23,16 @@ export default Vue.component('mk-post-html', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
const els = [].concat.apply([], (this as any).ast.map(token => {
|
const els = flatten((this as any).ast.map(token => {
|
||||||
switch (token.type) {
|
switch (token.type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
const text = token.content.replace(/(\r\n|\n|\r)/g, '\n');
|
const text = token.content.replace(/(\r\n|\n|\r)/g, '\n');
|
||||||
|
|
||||||
if ((this as any).shouldBreak) {
|
if ((this as any).shouldBreak) {
|
||||||
if (text.indexOf('\n') != -1) {
|
|
||||||
const x = text.split('\n')
|
const x = text.split('\n')
|
||||||
.map(t => [createElement('span', t), createElement('br')]);
|
.map(t => t == '' ? [createElement('br')] : [createElement('span', t), createElement('br')]);
|
||||||
x[x.length - 1].pop();
|
x[x.length - 1].pop();
|
||||||
return x;
|
return x;
|
||||||
} else {
|
|
||||||
return createElement('span', text);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return createElement('span', text.replace(/\n/g, ' '));
|
return createElement('span', text.replace(/\n/g, ' '));
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,46 @@ export default Vue.component('mk-post-html', {
|
||||||
case 'inline-code':
|
case 'inline-code':
|
||||||
return createElement('code', token.html);
|
return createElement('code', token.html);
|
||||||
|
|
||||||
|
case 'quote':
|
||||||
|
const text2 = token.quote.replace(/(\r\n|\n|\r)/g, '\n');
|
||||||
|
|
||||||
|
if ((this as any).shouldBreak) {
|
||||||
|
const x = text2.split('\n')
|
||||||
|
.map(t => [createElement('span', t), createElement('br')]);
|
||||||
|
x[x.length - 1].pop();
|
||||||
|
return createElement('div', {
|
||||||
|
attrs: {
|
||||||
|
class: 'quote'
|
||||||
|
}
|
||||||
|
}, x);
|
||||||
|
} else {
|
||||||
|
return createElement('span', {
|
||||||
|
attrs: {
|
||||||
|
class: 'quote'
|
||||||
|
}
|
||||||
|
}, text2.replace(/\n/g, ' '));
|
||||||
|
}
|
||||||
|
|
||||||
case 'emoji':
|
case 'emoji':
|
||||||
const emoji = emojilib.lib[token.emoji];
|
const emoji = emojilib.lib[token.emoji];
|
||||||
return createElement('span', emoji ? emoji.char : token.content);
|
return createElement('span', emoji ? emoji.char : token.content);
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.log('unknown ast type:', token.type);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return createElement('span', els);
|
const _els = [];
|
||||||
|
els.forEach((el, i) => {
|
||||||
|
if (el.tag == 'br') {
|
||||||
|
if (els[i - 1].tag != 'div') {
|
||||||
|
_els.push(el);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_els.push(el);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return createElement('span', _els);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -416,6 +416,12 @@ export default Vue.extend({
|
||||||
font-size 1.1em
|
font-size 1.1em
|
||||||
color #717171
|
color #717171
|
||||||
|
|
||||||
|
>>> .quote
|
||||||
|
margin 8px
|
||||||
|
padding 6px 12px
|
||||||
|
color #aaa
|
||||||
|
border-left solid 3px #eee
|
||||||
|
|
||||||
.mk-url-preview
|
.mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
|
@ -512,6 +518,7 @@ export default Vue.extend({
|
||||||
|
|
||||||
<style lang="stylus" module>
|
<style lang="stylus" module>
|
||||||
.text
|
.text
|
||||||
|
|
||||||
code
|
code
|
||||||
padding 4px 8px
|
padding 4px 8px
|
||||||
margin 0 0.5em
|
margin 0 0.5em
|
||||||
|
|
|
@ -349,6 +349,12 @@ export default Vue.extend({
|
||||||
font-size 1.1em
|
font-size 1.1em
|
||||||
color #717171
|
color #717171
|
||||||
|
|
||||||
|
>>> .quote
|
||||||
|
margin 8px
|
||||||
|
padding 6px 12px
|
||||||
|
color #aaa
|
||||||
|
border-left solid 3px #eee
|
||||||
|
|
||||||
.mk-url-preview
|
.mk-url-preview
|
||||||
margin-top 8px
|
margin-top 8px
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue