mirror of
https://github.com/marktext/marktext.git
synced 2025-05-04 01:10:04 +08:00
Add loose and tight list compatibility (#74)
* Add loose and tight list compatibility * Fix 'false' preference booleans are not handled
This commit is contained in:
parent
e594705223
commit
4d7d850969
@ -89,7 +89,9 @@ export const CLASS_OR_ID = genUpper2LowerKeyHash([
|
|||||||
'AG_HIGHLIGHT',
|
'AG_HIGHLIGHT',
|
||||||
'AG_MATH',
|
'AG_MATH',
|
||||||
'AG_MATH_RENDER',
|
'AG_MATH_RENDER',
|
||||||
'AG_MATH_ERROR'
|
'AG_MATH_ERROR',
|
||||||
|
'AG_LOOSE_LIST_ITEM',
|
||||||
|
'AG_TIGHT_LIST_ITEM'
|
||||||
])
|
])
|
||||||
|
|
||||||
export const codeMirrorConfig = {
|
export const codeMirrorConfig = {
|
||||||
|
@ -187,6 +187,7 @@ const enterCtrl = ContentState => {
|
|||||||
newBlock = this.createBlockLi(post)
|
newBlock = this.createBlockLi(post)
|
||||||
newBlock.listItemType = block.listItemType
|
newBlock.listItemType = block.listItemType
|
||||||
}
|
}
|
||||||
|
newBlock.isLooseListItem = block.isLooseListItem
|
||||||
} else {
|
} else {
|
||||||
block.text = pre
|
block.text = pre
|
||||||
newBlock = this.createBlock(type, post)
|
newBlock = this.createBlock(type, post)
|
||||||
@ -218,6 +219,7 @@ const enterCtrl = ContentState => {
|
|||||||
newBlock = this.createBlockLi()
|
newBlock = this.createBlockLi()
|
||||||
newBlock.listItemType = parent.listItemType
|
newBlock.listItemType = parent.listItemType
|
||||||
}
|
}
|
||||||
|
newBlock.isLooseListItem = parent.isLooseListItem
|
||||||
this.insertAfter(newBlock, parent)
|
this.insertAfter(newBlock, parent)
|
||||||
const index = this.findIndex(parent.children, block)
|
const index = this.findIndex(parent.children, block)
|
||||||
const partChildren = parent.children.splice(index + 1)
|
const partChildren = parent.children.splice(index + 1)
|
||||||
@ -245,6 +247,7 @@ const enterCtrl = ContentState => {
|
|||||||
newBlock = this.createBlockLi()
|
newBlock = this.createBlockLi()
|
||||||
newBlock.listItemType = block.listItemType
|
newBlock.listItemType = block.listItemType
|
||||||
}
|
}
|
||||||
|
newBlock.isLooseListItem = block.isLooseListItem
|
||||||
} else {
|
} else {
|
||||||
newBlock = this.createBlock('p')
|
newBlock = this.createBlock('p')
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ const updateCtrl = ContentState => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentState.prototype.checkInlineUpdate = function (block) {
|
ContentState.prototype.checkInlineUpdate = function (block, preferLooseListItem) {
|
||||||
if (/th|td|figure/.test(block.type)) return false
|
if (/th|td|figure/.test(block.type)) return false
|
||||||
const { text } = block
|
const { text } = block
|
||||||
const parent = this.getParent(block)
|
const parent = this.getParent(block)
|
||||||
@ -43,11 +43,11 @@ const updateCtrl = ContentState => {
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
case !!bullet:
|
case !!bullet:
|
||||||
this.updateList(block, 'bullet', bullet)
|
this.updateList(block, 'bullet', preferLooseListItem, bullet)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case !!tasklist && parent && parent.listItemType === 'bullet': // only `bullet` list item can be update to `task` list item
|
case !!tasklist && parent && parent.listItemType === 'bullet': // only `bullet` list item can be update to `task` list item
|
||||||
this.updateTaskListItem(block, 'tasklist', tasklist)
|
this.updateTaskListItem(block, 'tasklist', preferLooseListItem, tasklist)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case !!order:
|
case !!order:
|
||||||
@ -144,7 +144,7 @@ const updateCtrl = ContentState => {
|
|||||||
this.render()
|
this.render()
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentState.prototype.updateList = function (block, type, marker = '') {
|
ContentState.prototype.updateList = function (block, type, preferLooseListItem, marker = '') {
|
||||||
const parent = this.getParent(block)
|
const parent = this.getParent(block)
|
||||||
const preSibling = this.getPreSibling(block)
|
const preSibling = this.getPreSibling(block)
|
||||||
const nextSibling = this.getNextSibling(block)
|
const nextSibling = this.getNextSibling(block)
|
||||||
@ -155,6 +155,7 @@ const updateCtrl = ContentState => {
|
|||||||
const endOffset = end.offset
|
const endOffset = end.offset
|
||||||
const newBlock = this.createBlockLi(newText, block.type)
|
const newBlock = this.createBlockLi(newText, block.type)
|
||||||
newBlock.listItemType = type
|
newBlock.listItemType = type
|
||||||
|
newBlock.isLooseListItem = preferLooseListItem
|
||||||
|
|
||||||
if (preSibling && preSibling.listType === type && nextSibling && nextSibling.listType === type) {
|
if (preSibling && preSibling.listType === type && nextSibling && nextSibling.listType === type) {
|
||||||
this.appendChild(preSibling, newBlock)
|
this.appendChild(preSibling, newBlock)
|
||||||
@ -224,7 +225,7 @@ const updateCtrl = ContentState => {
|
|||||||
block.type = 'hr'
|
block.type = 'hr'
|
||||||
}
|
}
|
||||||
|
|
||||||
ContentState.prototype.updateState = function (event) {
|
ContentState.prototype.updateState = function (event, preferLooseListItem) {
|
||||||
const { floatBox } = this
|
const { floatBox } = this
|
||||||
const { start, end } = selection.getCursorRange()
|
const { start, end } = selection.getCursorRange()
|
||||||
const { start: oldStart, end: oldEnd } = this.cursor
|
const { start: oldStart, end: oldEnd } = this.cursor
|
||||||
@ -233,7 +234,7 @@ const updateCtrl = ContentState => {
|
|||||||
}
|
}
|
||||||
if (event.type === 'click' && start.key !== end.key) {
|
if (event.type === 'click' && start.key !== end.key) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.updateState(event)
|
this.updateState(event, preferLooseListItem)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (event.type === 'input' && oldStart.key !== oldEnd.key) {
|
if (event.type === 'input' && oldStart.key !== oldEnd.key) {
|
||||||
@ -326,7 +327,7 @@ const updateCtrl = ContentState => {
|
|||||||
this.cursor = { start, end }
|
this.cursor = { start, end }
|
||||||
|
|
||||||
const checkMarkedUpdate = this.checkNeedRender(block)
|
const checkMarkedUpdate = this.checkNeedRender(block)
|
||||||
const checkInlineUpdate = this.checkInlineUpdate(block)
|
const checkInlineUpdate = this.checkInlineUpdate(block, preferLooseListItem)
|
||||||
|
|
||||||
if (checkMarkedUpdate || checkInlineUpdate || needRender) {
|
if (checkMarkedUpdate || checkInlineUpdate || needRender) {
|
||||||
this.render()
|
this.render()
|
||||||
|
@ -19,7 +19,7 @@ import './assets/symbolIcon/index.css'
|
|||||||
|
|
||||||
class Aganippe {
|
class Aganippe {
|
||||||
constructor (container, options) {
|
constructor (container, options) {
|
||||||
const { focusMode = false, theme = 'light', markdown = '' } = options
|
const { focusMode = false, theme = 'light', markdown = '', preferLooseListItem = true } = options
|
||||||
this.container = container
|
this.container = container
|
||||||
const eventCenter = this.eventCenter = new EventCenter()
|
const eventCenter = this.eventCenter = new EventCenter()
|
||||||
const floatBox = this.floatBox = new FloatBox(eventCenter)
|
const floatBox = this.floatBox = new FloatBox(eventCenter)
|
||||||
@ -31,6 +31,7 @@ class Aganippe {
|
|||||||
this.markdown = markdown
|
this.markdown = markdown
|
||||||
this.fontSize = 16
|
this.fontSize = 16
|
||||||
this.lineHeight = 1.6
|
this.lineHeight = 1.6
|
||||||
|
this.preferLooseListItem = preferLooseListItem
|
||||||
// private property
|
// private property
|
||||||
this._isEditChinese = false
|
this._isEditChinese = false
|
||||||
this.init()
|
this.init()
|
||||||
@ -342,7 +343,7 @@ class Aganippe {
|
|||||||
// const style = getComputedStyle(target)
|
// const style = getComputedStyle(target)
|
||||||
// if (event.type === 'click' && !style.contenteditable) return
|
// if (event.type === 'click' && !style.contenteditable) return
|
||||||
if (!this._isEditChinese) {
|
if (!this._isEditChinese) {
|
||||||
this.contentState.updateState(event)
|
this.contentState.updateState(event, this.preferLooseListItem)
|
||||||
}
|
}
|
||||||
if (event.type === 'click' || event.type === 'keyup') {
|
if (event.type === 'click' || event.type === 'keyup') {
|
||||||
const selectionChanges = this.getSelection()
|
const selectionChanges = this.getSelection()
|
||||||
|
@ -113,6 +113,7 @@ class StateRender {
|
|||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
blockSelector += block.isLooseListItem ? `.${CLASS_OR_ID['AG_LOOSE_LIST_ITEM']}` : `.${CLASS_OR_ID['AG_TIGHT_LIST_ITEM']}`
|
||||||
}
|
}
|
||||||
if (block.type === 'ol') {
|
if (block.type === 'ol') {
|
||||||
Object.assign(data.attrs, { start: block.start })
|
Object.assign(data.attrs, { start: block.start })
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { CLASS_OR_ID } from '../config'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* marked - a markdown parser
|
* marked - a markdown parser
|
||||||
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
|
* Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
|
||||||
@ -155,7 +157,7 @@ Lexer.prototype.lex = function(src) {
|
|||||||
|
|
||||||
Lexer.prototype.token = function(src, top, bq) {
|
Lexer.prototype.token = function(src, top, bq) {
|
||||||
var src = src.replace(/^ +$/gm, ''),
|
var src = src.replace(/^ +$/gm, ''),
|
||||||
next, loose, cap, bull, b, item, space, i, l, checked;
|
loose, cap, bull, b, item, space, i, l, checked;
|
||||||
|
|
||||||
while (src) {
|
while (src) {
|
||||||
// newline
|
// newline
|
||||||
@ -288,14 +290,18 @@ Lexer.prototype.token = function(src, top, bq) {
|
|||||||
listType: bull.length > 1 ? (/\d/.test(bull) ? 'order' : 'task') : 'bullet'
|
listType: bull.length > 1 ? (/\d/.test(bull) ? 'order' : 'task') : 'bullet'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let next = false;
|
||||||
|
let prevNext = true;
|
||||||
|
let listItemIndices = [];
|
||||||
|
|
||||||
// Get each top-level item.
|
// Get each top-level item.
|
||||||
cap = cap[0].match(this.rules.item);
|
cap = cap[0].match(this.rules.item);
|
||||||
next = false;
|
|
||||||
l = cap.length;
|
l = cap.length;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
for (; i < l; i++) {
|
for (; i < l; i++) {
|
||||||
item = cap[i];
|
const itemWithBullet = cap[i];
|
||||||
|
item = itemWithBullet;
|
||||||
|
|
||||||
// Remove the list item's bullet
|
// Remove the list item's bullet
|
||||||
// so it is seen as the next token.
|
// so it is seen as the next token.
|
||||||
@ -331,13 +337,33 @@ Lexer.prototype.token = function(src, top, bq) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine whether item is loose or not.
|
var prevItem = '';
|
||||||
// Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
|
if (i === 0) {
|
||||||
// for discount behavior.
|
prevItem = item;
|
||||||
loose = next || /\n\n(?!\s*$)/.test(item);
|
} else {
|
||||||
if (i !== l - 1) {
|
prevItem = cap[i - 1];
|
||||||
next = item.charAt(item.length - 1) === '\n';
|
}
|
||||||
if (!loose) loose = next;
|
|
||||||
|
// Determine whether item is loose or not. If previous item is loose
|
||||||
|
// this item is also loose.
|
||||||
|
loose = next = next || /^ *([*+-]|\d+\.) +\S+\n\n(?!\s*$)/.test(itemWithBullet);
|
||||||
|
|
||||||
|
// Check if previous line ends with a new line.
|
||||||
|
if (!loose && (i !== 0 || l > 1) && prevItem.length !== 0 && prevItem.charAt(prevItem.length - 1) === '\n') {
|
||||||
|
loose = next = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A list is either loose or tight, so update previous list items.
|
||||||
|
if (next && prevNext !== next) {
|
||||||
|
for(const index of listItemIndices) {
|
||||||
|
this.tokens[index].type = 'loose_item_start'
|
||||||
|
}
|
||||||
|
listItemIndices = [];
|
||||||
|
}
|
||||||
|
prevNext = next;
|
||||||
|
|
||||||
|
if (!loose) {
|
||||||
|
listItemIndices.push(this.tokens.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tokens.push({
|
this.tokens.push({
|
||||||
@ -828,19 +854,26 @@ Renderer.prototype.list = function(body, ordered, taskList) {
|
|||||||
return '<' + type + classes + '>\n' + body + '</' + type + '>\n';
|
return '<' + type + classes + '>\n' + body + '</' + type + '>\n';
|
||||||
};
|
};
|
||||||
|
|
||||||
Renderer.prototype.listitem = function(text, checked, listItemType) {
|
Renderer.prototype.listitem = function(text, checked, listItemType, loose) {
|
||||||
var classes
|
var classes;
|
||||||
switch (listItemType) {
|
switch (listItemType) {
|
||||||
case 'order':
|
case 'order':
|
||||||
classes = ' class="order-list-item"'
|
classes = ' class="order-list-item';
|
||||||
break
|
break;
|
||||||
case 'task':
|
case 'task':
|
||||||
classes = ' class="task-list-item"'
|
classes = ' class="task-list-item';
|
||||||
break
|
break;
|
||||||
case 'bullet':
|
case 'bullet':
|
||||||
classes = ' class="bullet-list-item"'
|
classes = ' class="bullet-list-item';
|
||||||
break
|
break;
|
||||||
|
default:
|
||||||
|
throw new
|
||||||
|
Error('Invalid state');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "tight-list-item" is only used to remove <p> padding
|
||||||
|
classes += loose ? ` .${CLASS_OR_ID['AG_LOOSE_LIST_ITEM']}"` : ` .${CLASS_OR_ID['AG_TIGHT_LIST_ITEM']}"`;
|
||||||
|
|
||||||
if (checked === undefined) {
|
if (checked === undefined) {
|
||||||
return '<li ' + classes + '>' + text + '</li>\n';
|
return '<li ' + classes + '>' + text + '</li>\n';
|
||||||
}
|
}
|
||||||
@ -1107,7 +1140,7 @@ Parser.prototype.tok = function() {
|
|||||||
this.tok();
|
this.tok();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.renderer.listitem(body, checked, listItemType);
|
return this.renderer.listitem(body, checked, listItemType, false);
|
||||||
}
|
}
|
||||||
case 'loose_item_start':
|
case 'loose_item_start':
|
||||||
{
|
{
|
||||||
@ -1119,7 +1152,7 @@ Parser.prototype.tok = function() {
|
|||||||
body += this.tok();
|
body += this.tok();
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.renderer.listitem(body, checked, listItemType);
|
return this.renderer.listitem(body, checked, listItemType, true);
|
||||||
}
|
}
|
||||||
case 'html':
|
case 'html':
|
||||||
{
|
{
|
||||||
|
@ -4,6 +4,8 @@ class ExportMarkdown {
|
|||||||
constructor (blocks) {
|
constructor (blocks) {
|
||||||
this.blocks = blocks
|
this.blocks = blocks
|
||||||
this.listType = [] // 'ul' or 'ol'
|
this.listType = [] // 'ul' or 'ol'
|
||||||
|
// helper to translate the first tight item in a nested list
|
||||||
|
this.isLooseParentList = true
|
||||||
}
|
}
|
||||||
|
|
||||||
generate () {
|
generate () {
|
||||||
@ -20,7 +22,7 @@ class ExportMarkdown {
|
|||||||
switch (block.type) {
|
switch (block.type) {
|
||||||
case 'p':
|
case 'p':
|
||||||
case 'hr':
|
case 'hr':
|
||||||
this.insertLineBreak(result, indent)
|
this.insertLineBreak(result, indent, true)
|
||||||
result.push(this.normalizeParagraphText(block, indent))
|
result.push(this.normalizeParagraphText(block, indent))
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -30,43 +32,58 @@ class ExportMarkdown {
|
|||||||
case 'h4':
|
case 'h4':
|
||||||
case 'h5':
|
case 'h5':
|
||||||
case 'h6':
|
case 'h6':
|
||||||
this.insertLineBreak(result, indent)
|
this.insertLineBreak(result, indent, true)
|
||||||
result.push(this.normalizeHeaderText(block, indent))
|
result.push(this.normalizeHeaderText(block, indent))
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'figure':
|
case 'figure':
|
||||||
this.insertLineBreak(result, indent)
|
this.insertLineBreak(result, indent, true)
|
||||||
const table = block.children[1]
|
const table = block.children[1]
|
||||||
result.push(this.normalizeTable(table, indent))
|
result.push(this.normalizeTable(table, indent))
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'li':
|
case 'li': {
|
||||||
this.insertLineBreak(result, indent)
|
const insertNewLine = block.isLooseListItem
|
||||||
result.push(this.normalizeListItem(block, indent))
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'ul':
|
// helper variable to correct the first tight item in a nested list
|
||||||
this.insertLineBreak(result, indent)
|
this.isLooseParentList = insertNewLine
|
||||||
|
|
||||||
|
this.insertLineBreak(result, indent, insertNewLine)
|
||||||
|
result.push(this.normalizeListItem(block, indent))
|
||||||
|
this.isLooseParentList = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'ul': {
|
||||||
|
const insertNewLine = this.isLooseParentList
|
||||||
|
this.isLooseParentList = true
|
||||||
|
|
||||||
|
this.insertLineBreak(result, indent, insertNewLine)
|
||||||
this.listType.push({ type: 'ul' })
|
this.listType.push({ type: 'ul' })
|
||||||
result.push(this.normalizeList(block, indent))
|
result.push(this.normalizeList(block, indent))
|
||||||
this.listType.pop()
|
this.listType.pop()
|
||||||
break
|
break
|
||||||
|
}
|
||||||
|
|
||||||
case 'ol':
|
case 'ol': {
|
||||||
this.insertLineBreak(result, indent)
|
const insertNewLine = this.isLooseParentList
|
||||||
|
this.isLooseParentList = true
|
||||||
|
|
||||||
|
this.insertLineBreak(result, indent, insertNewLine)
|
||||||
const listCount = block.start !== undefined ? block.start : 1
|
const listCount = block.start !== undefined ? block.start : 1
|
||||||
this.listType.push({ type: 'ol', listCount })
|
this.listType.push({ type: 'ol', listCount })
|
||||||
result.push(this.normalizeList(block, indent))
|
result.push(this.normalizeList(block, indent))
|
||||||
this.listType.pop()
|
this.listType.pop()
|
||||||
break
|
break
|
||||||
|
}
|
||||||
|
|
||||||
case 'pre':
|
case 'pre':
|
||||||
this.insertLineBreak(result, indent)
|
this.insertLineBreak(result, indent, true)
|
||||||
result.push(this.normalizeCodeBlock(block, indent))
|
result.push(this.normalizeCodeBlock(block, indent))
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'blockquote':
|
case 'blockquote':
|
||||||
this.insertLineBreak(result, indent)
|
this.insertLineBreak(result, indent, true)
|
||||||
result.push(this.normalizeBlockquote(block, indent))
|
result.push(this.normalizeBlockquote(block, indent))
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -77,12 +94,13 @@ class ExportMarkdown {
|
|||||||
return result.join('')
|
return result.join('')
|
||||||
}
|
}
|
||||||
|
|
||||||
insertLineBreak (result, indent) {
|
insertLineBreak (result, indent, insertNewLine) {
|
||||||
|
const newLine = insertNewLine ? '\n' : ''
|
||||||
if (result.length > 0) {
|
if (result.length > 0) {
|
||||||
if (/\S/.test(indent)) {
|
if (/\S/.test(indent)) {
|
||||||
result.push(`${indent}\n`)
|
result.push(`${indent}${newLine}`)
|
||||||
} else {
|
} else if (insertNewLine) {
|
||||||
result.push('\n')
|
result.push(newLine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,9 +153,11 @@ const importRegister = ContentState => {
|
|||||||
break
|
break
|
||||||
|
|
||||||
case 'li':
|
case 'li':
|
||||||
const isTask = child.attrs.some(attr => attr.name === 'class' && attr.value === 'task-list-item')
|
const isTask = child.attrs.some(attr => attr.name === 'class' && attr.value.includes('task-list-item'))
|
||||||
|
const isLoose = child.attrs.some(attr => attr.name === 'class' && attr.value.includes(CLASS_OR_ID['AG_LOOSE_LIST_ITEM']))
|
||||||
block = this.createBlock('li')
|
block = this.createBlock('li')
|
||||||
block.listItemType = parent.nodeName === 'ul' ? (isTask ? 'task' : 'bullet') : 'order'
|
block.listItemType = parent.nodeName === 'ul' ? (isTask ? 'task' : 'bullet') : 'order'
|
||||||
|
block.isLooseListItem = isLoose
|
||||||
this.appendChild(parent, block)
|
this.appendChild(parent, block)
|
||||||
travel(block, child.childNodes)
|
travel(block, child.childNodes)
|
||||||
break
|
break
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
computed: {
|
computed: {
|
||||||
...mapState([
|
...mapState([
|
||||||
'pathname', 'filename', 'isSaved', 'windowActive', 'wordCount',
|
'pathname', 'filename', 'isSaved', 'windowActive', 'wordCount',
|
||||||
'typewriter', 'focus', 'sourceCode', 'markdown',
|
'typewriter', 'focus', 'sourceCode', 'markdown', 'preferLooseListItem',
|
||||||
'cursor', 'theme', 'platform', 'lightColor', 'darkColor', 'fontSize', 'lineHeight'
|
'cursor', 'theme', 'platform', 'lightColor', 'darkColor', 'fontSize', 'lineHeight'
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapState } from 'vuex'
|
||||||
import Aganippe from '../../editor'
|
import Aganippe from '../../editor'
|
||||||
import bus from '../bus'
|
import bus from '../bus'
|
||||||
import { animatedScrollTo } from '../util'
|
import { animatedScrollTo } from '../util'
|
||||||
@ -94,6 +95,11 @@
|
|||||||
lightColor: String,
|
lightColor: String,
|
||||||
darkColor: String
|
darkColor: String
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState([
|
||||||
|
'preferLooseListItem'
|
||||||
|
])
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
selectionChange: null,
|
selectionChange: null,
|
||||||
@ -139,8 +145,9 @@
|
|||||||
created () {
|
created () {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const ele = this.$refs.editor
|
const ele = this.$refs.editor
|
||||||
const { theme, focus: focusMode, markdown, typewriter } = this
|
const { theme, focus: focusMode, markdown, preferLooseListItem, typewriter } = this
|
||||||
const { container } = this.editor = new Aganippe(ele, { theme, focusMode, markdown })
|
|
||||||
|
const { container } = this.editor = new Aganippe(ele, { theme, focusMode, markdown, preferLooseListItem })
|
||||||
|
|
||||||
if (typewriter) {
|
if (typewriter) {
|
||||||
this.scrollToCursor()
|
this.scrollToCursor()
|
||||||
@ -162,6 +169,7 @@
|
|||||||
bus.$on('insert-image', this.handleSelect)
|
bus.$on('insert-image', this.handleSelect)
|
||||||
bus.$on('content-in-source-mode', this.handleMarkdownChange)
|
bus.$on('content-in-source-mode', this.handleMarkdownChange)
|
||||||
bus.$on('editor-blur', this.blurEditor)
|
bus.$on('editor-blur', this.blurEditor)
|
||||||
|
bus.$on('update-prefer-loose-list-item', this.handlePreferLooseListItemChange)
|
||||||
bus.$on('image-auto-path', this.handleImagePath)
|
bus.$on('image-auto-path', this.handleImagePath)
|
||||||
|
|
||||||
this.editor.on('insert-image', type => {
|
this.editor.on('insert-image', type => {
|
||||||
@ -324,6 +332,12 @@
|
|||||||
|
|
||||||
blurEditor () {
|
blurEditor () {
|
||||||
this.editor.blur()
|
this.editor.blur()
|
||||||
|
},
|
||||||
|
|
||||||
|
handlePreferLooseListItemChange (preferLooseListItem) {
|
||||||
|
if (this.editor) {
|
||||||
|
this.editor.preferLooseListItem = preferLooseListItem
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -339,6 +353,7 @@
|
|||||||
bus.$off('find', this.handleFind)
|
bus.$off('find', this.handleFind)
|
||||||
bus.$off('dotu-select', this.handleSelect)
|
bus.$off('dotu-select', this.handleSelect)
|
||||||
bus.$off('editor-blur', this.blurEditor)
|
bus.$off('editor-blur', this.blurEditor)
|
||||||
|
bus.$off('update-pref-list-item-type', this.handlePreferLooseListItemChange)
|
||||||
bus.$on('image-auto-path', this.handleImagePath)
|
bus.$on('image-auto-path', this.handleImagePath)
|
||||||
|
|
||||||
this.editor.destroy()
|
this.editor.destroy()
|
||||||
|
@ -17,6 +17,7 @@ const state = {
|
|||||||
lightColor: '#303133', // color in light theme
|
lightColor: '#303133', // color in light theme
|
||||||
darkColor: 'rgb(217, 217, 217)', // color in dark theme
|
darkColor: 'rgb(217, 217, 217)', // color in dark theme
|
||||||
autoSave: false,
|
autoSave: false,
|
||||||
|
preferLooseListItem: true, // prefer loose or tight list items
|
||||||
// edit mode
|
// edit mode
|
||||||
typewriter: false, // typewriter mode
|
typewriter: false, // typewriter mode
|
||||||
focus: false, // focus mode
|
focus: false, // focus mode
|
||||||
@ -66,7 +67,7 @@ const mutations = {
|
|||||||
},
|
},
|
||||||
SET_USER_PREFERENCE (state, preference) {
|
SET_USER_PREFERENCE (state, preference) {
|
||||||
Object.keys(preference).forEach(key => {
|
Object.keys(preference).forEach(key => {
|
||||||
if (preference[key]) {
|
if (typeof preference[key] !== 'undefined' && typeof state[key] !== 'undefined') {
|
||||||
state[key] = preference[key]
|
state[key] = preference[key]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -101,9 +102,15 @@ const actions = {
|
|||||||
ipcRenderer.send('AGANI::ask-for-user-preference')
|
ipcRenderer.send('AGANI::ask-for-user-preference')
|
||||||
ipcRenderer.on('AGANI::user-preference', (e, preference) => {
|
ipcRenderer.on('AGANI::user-preference', (e, preference) => {
|
||||||
const { autoSave } = preference
|
const { autoSave } = preference
|
||||||
|
const { preferLooseListItem } = state // old value
|
||||||
|
|
||||||
commit('SET_USER_PREFERENCE', preference)
|
commit('SET_USER_PREFERENCE', preference)
|
||||||
|
|
||||||
|
if (typeof preference.preferLooseListItem !== 'undefined' &&
|
||||||
|
preference.preferLooseListItem !== preferLooseListItem) {
|
||||||
|
bus.$emit('update-prefer-loose-list-item', preference.preferLooseListItem)
|
||||||
|
}
|
||||||
|
|
||||||
// handle autoSave
|
// handle autoSave
|
||||||
if (autoSave) {
|
if (autoSave) {
|
||||||
const { pathname, markdown } = state
|
const { pathname, markdown } = state
|
||||||
|
@ -14,7 +14,8 @@ Edit and save to update preferences, You can only change the json bellow!
|
|||||||
"lineHeight": "1.6",
|
"lineHeight": "1.6",
|
||||||
"theme": "light",
|
"theme": "light",
|
||||||
"autoSave": false,
|
"autoSave": false,
|
||||||
"aidou": false
|
"aidou": false,
|
||||||
|
"preferLooseListItem": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -248,6 +248,11 @@ li p.first {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li.ag-tight-list-item > p {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
|
@ -221,6 +221,11 @@ li p.first {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
li.ag-tight-list-item > p {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
ul,
|
ul,
|
||||||
ol {
|
ol {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
|
Loading…
Reference in New Issue
Block a user