opti:title bar and task list checkbox style optimization

This commit is contained in:
Jocs 2018-02-28 15:44:00 +08:00
parent 5004b96770
commit f30cbfd837
17 changed files with 615 additions and 107 deletions

View File

@ -3,3 +3,4 @@ test/unit/*.js
test/e2e/*.js
src/editor/parser/marked.js
src/editor/assets/symbolIcon/index.js
src/renderer/assets/symbolIcon/index.js

View File

@ -4,6 +4,14 @@
- fix the bug that click at the edge of code block will caused the code block does not be focused.
**Optimization**
- Optimize the display of word count in title bar. we also delete the background color of title bar to make it more concise.
- Customize the style of checkbox in Task List Item.
- Change the display of Insert Table dialog.
### 0.3.0
**Features**

View File

@ -2,6 +2,8 @@
# MarkText
[![GitHub version](https://badge.fury.io/gh/jocs%2Fmarktext.svg)](https://badge.fury.io/gh/jocs%2Fmarktext)
**MarkText** is an **open source** Markdown editor for OS X, released under the **MIT license**. It is inspired by outstanding markdown editor **Typora**.
![](https://github.com/marktext/marktext/blob/master/summary.gif)

View File

@ -1,11 +1,16 @@
#### TODO LIST
- [ ] Support Raw HTML in editor.
- [ ] Support Search and Replacement.
- [ ] add Dark, Light and GitHub theme.
- [ ] source code edit mode.
- [ ] Support Raw HTML in editor.
- [ ] Support auto accompliment.
- [ ] Left click menu.
- [ ] Rename and moveTo in **File Menu**

View File

@ -79,6 +79,7 @@ export const CLASS_OR_ID = genUpper2LowerKeyHash([
'AG_TASK_LIST',
'AG_TASK_LIST_ITEM',
'AG_TASK_LIST_ITEM_CHECKBOX',
'AG_CHECKBOX_CHECKED',
'AG_TABLE_TOOL_BAR'
])

View File

@ -138,9 +138,9 @@ const updateCtrl = ContentState => {
// handle task list item checkbox click
ContentState.prototype.listItemCheckBoxClick = function (checkbox) {
const { checked, id } = checkbox
console.log(checked)
const block = this.getBlock(id)
block.checked = checked
this.render()
}
ContentState.prototype.updateList = function (block, type, marker = '') {

View File

@ -103,6 +103,7 @@ class FloatBox {
this.index = 0
if (this.show) {
this.box.classList.remove(CLASS_OR_ID['AG_SHOW_FLOAT_BOX'])
this.box.removeAttribute('style')
}
this.show = false
}

View File

@ -21,6 +21,10 @@ h6.ag-active::before {
font-weight: 100;
}
*::selection {
background: #efefef;
}
figure {
padding: 0;
margin: 0;
@ -28,6 +32,7 @@ figure {
position: relative;
}
.ag-table-tool-bar {
width: 100%;
user-select: none;
position: absolute;
top: -20px;
@ -40,6 +45,7 @@ figure {
margin: 0;
padding: 0;
display: flex;
width: 100%;
}
.ag-table-tool-bar ul li {
box-sizing: border-box;
@ -55,6 +61,9 @@ figure {
.ag-table-tool-bar ul li[data-label=delete] {
color: #E6A23C;
position: absolute;
right: 0;
top: 0;
}
.ag-table-tool-bar ul li.active {
@ -110,6 +119,43 @@ li.ag-task-list-item > input[type=checkbox] {
left: -20px;
}
li.ag-task-list-item > input.ag-checkbox-checked ~ p {
color: #909399;
}
li.ag-task-list-item > input[type=checkbox]::before {
content: '';
width: 16px;
height: 16px;
box-sizing: border-box;
display: inline-block;
border: 2px solid #606266;
border-radius: 2px;
background-color: #FFFFFF;
position: absolute;
top: 0;
left: 0;
}
li.ag-task-list-item > input.ag-checkbox-checked::before {
border: none;
background-color: #606266;
}
li.ag-task-list-item > input.ag-checkbox-checked::after {
content: '';
transform: rotate(-45deg);
width: 7px;
height: 3px;
border: 2px solid #fff;
border-top: none;
border-right: none;
position: absolute;
display: inline-block;
top: 4px;
left: 4px;
}
li p .ag-hide:first-child {
display: none;
}
@ -193,7 +239,7 @@ pre.ag-active .ag-language-input {
#ag-editor-id, [contenteditable] {
outline: none;
caret-color: #333;
caret-color: #303133;
}
.ag-gray {
color: lavender;

View File

@ -156,10 +156,11 @@ class StateRender {
if (block.type === 'input') {
const { checked, type, key } = block
Object.assign(data.attrs, { type: 'checkbox' })
blockSelector = `${type}#${key}.${CLASS_OR_ID['AG_TASK_LIST_ITEM_CHECKBOX']}`
if (checked) {
Object.assign(data.attrs, { checked: true })
blockSelector += `.${CLASS_OR_ID['AG_CHECKBOX_CHECKED']}`
}
blockSelector = `${type}#${key}.${CLASS_OR_ID['AG_TASK_LIST_ITEM_CHECKBOX']}`
children = ''
}

465
src/editor/themes/light.css Normal file
View File

@ -0,0 +1,465 @@
:root {
--side-bar-bg-color: #fafafa;
--control-text-color: #777;
}
@include-when-export url(http://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext);
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: normal;
src: local('Open Sans Regular'), url('./github/400.woff') format('woff')
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: normal;
src: local('Open Sans Italic'), url('./github/400i.woff') format('woff')
}
@font-face {
font-family: 'Open Sans';
font-style: normal;
font-weight: bold;
src: local('Open Sans Bold'), url('./github/700.woff') format('woff')
}
@font-face {
font-family: 'Open Sans';
font-style: italic;
font-weight: bold;
src: local('Open Sans Bold Italic'), url('./github/700i.woff') format('woff')
}
html, body {
font-size: 16px;
background: rgb(252, 252, 252);
}
body {
font-family: "Open Sans", "Clear Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #303133;
line-height: 1.6;
}
#ag-editor-id {
max-width: 860px;
margin: 0 auto;
padding: 20px 30px 40px 30px;
padding-top: 20px;
padding-bottom: 100px;
}
#ag-editor-id>ul:first-child,
#ag-editor-id>ol:first-child {
margin-top: 30px;
}
body>*:first-child {
margin-top: 0 !important;
}
body>*:last-child {
margin-bottom: 0 !important;
}
a {
color: #4183C4;
}
h1,
h2,
h3,
h4,
h5,
h6 {
position: relative;
margin-top: 1rem;
margin-bottom: 1rem;
font-weight: bold;
line-height: 1.4;
cursor: text;
}
h1:hover a.anchor,
h2:hover a.anchor,
h3:hover a.anchor,
h4:hover a.anchor,
h5:hover a.anchor,
h6:hover a.anchor {
/*background: url("../../images/modules/styleguide/para.png") no-repeat 10px center;*/
text-decoration: none;
}
h1 tt,
h1 code {
font-size: inherit;
}
h2 tt,
h2 code {
font-size: inherit;
}
h3 tt,
h3 code {
font-size: inherit;
}
h4 tt,
h4 code {
font-size: inherit;
}
h5 tt,
h5 code {
font-size: inherit;
}
h6 tt,
h6 code {
font-size: inherit;
}
h1 {
padding-bottom: .3em;
font-size: 2.25em;
line-height: 1.2;
border-bottom: 1px solid #eee;
}
h2 {
padding-bottom: .3em;
font-size: 1.75em;
line-height: 1.225;
border-bottom: 1px solid #eee;
}
h3 {
font-size: 1.5em;
line-height: 1.43;
}
h4 {
font-size: 1.25em;
}
h5 {
font-size: 1em;
}
h6 {
font-size: 1em;
color: #777;
}
p,
blockquote,
ul,
ol,
dl,
table {
margin: 0.8em 0;
}
li>ol,
li>ul {
margin: 0 0;
}
hr {
height: 4px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
overflow: hidden;
box-sizing: content-box;
border-bottom: 1px solid #ddd;
}
body>h2:first-child {
margin-top: 0;
padding-top: 0;
}
body>h1:first-child {
margin-top: 0;
padding-top: 0;
}
body>h1:first-child+h2 {
margin-top: 0;
padding-top: 0;
}
body>h3:first-child,
body>h4:first-child,
body>h5:first-child,
body>h6:first-child {
margin-top: 0;
padding-top: 0;
}
a:first-child h1,
a:first-child h2,
a:first-child h3,
a:first-child h4,
a:first-child h5,
a:first-child h6 {
margin-top: 0;
padding-top: 0;
}
h1 p,
h2 p,
h3 p,
h4 p,
h5 p,
h6 p {
margin-top: 0;
}
li p.first {
display: inline-block;
}
ul,
ol {
padding-left: 30px;
}
ul:first-child,
ol:first-child {
margin-top: 0;
}
ul:last-child,
ol:last-child {
margin-bottom: 0;
}
blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777;
}
blockquote blockquote {
padding-right: 0;
}
table {
padding: 0;
word-break: initial;
}
table tr {
margin: 0;
padding: 0;
}
table thead tr,
table tr:nth-child(2n) {
background-color: #fafafa;
}
table tr th {
font-weight: bold;
border: 1px solid #ebeef5;
text-align: left;
margin: 0;
padding: 6px 13px;
}
table tr td {
border: 1px solid #ebeef5;
text-align: left;
margin: 0;
padding: 6px 13px;
}
table tr th:first-child,
table tr td:first-child {
margin-top: 0;
}
table tr th:last-child,
table tr td:last-child {
margin-bottom: 0;
}
.CodeMirror-gutters {
border-right: 1px solid #ddd;
}
.md-fences,
code,
tt {
border: 1px solid #ddd;
background-color: #f8f8f8;
border-radius: 3px;
padding: 0;
font-family: Consolas, "Liberation Mono", Courier, monospace;
padding: 2px 4px 0px 4px;
font-size: 0.9em;
}
/* custom add */
.md-fences,
code {
border: none;
padding: 2px 4px;
font-size: 90%;
color: #c7254e;
background-color: #f9f2f4;
border-radius: 4px;
font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
}
.md-fences {
margin-bottom: 15px;
margin-top: 15px;
padding: 0.2em 1em;
padding-top: 8px;
padding-bottom: 6px;
border: none;
}
.task-list {
padding-left: 0;
}
.task-list-item {
padding-left: 32px;
}
.task-list-item input {
top: 3px;
left: 8px;
}
@media screen and (min-width: 914px) {
/*body {
width: 854px;
margin: 0 auto;
}*/
}
@media print {
html {
font-size: 13px;
}
table,
pre {
page-break-inside: avoid;
}
pre {
word-wrap: break-word;
}
}
.md-fences {
background-color: #f8f8f8;
}
#ag-editor-id pre.ag-code-block {
padding: .4rem 1rem;
font-size: 90%;
line-height: 1.6;
background-color: #f6f8fa;
border: 0;
border-radius: 3px;
color: #777777;
margin-top: 0;
}
.mathjax-block>.code-tooltip {
bottom: .375rem;
}
#ag-editor-id>h3.md-focus:before {
left: -1.5625rem;
top: .375rem;
}
#ag-editor-id>h4.md-focus:before {
left: -1.5625rem;
top: .285714286rem;
}
#ag-editor-id>h5.md-focus:before {
left: -1.5625rem;
top: .285714286rem;
}
#ag-editor-id>h6.md-focus:before {
left: -1.5625rem;
top: .285714286rem;
}
.md-image>.md-meta {
border: 1px solid #ddd;
border-radius: 3px;
font-family: Consolas, "Liberation Mono", Courier, monospace;
padding: 2px 4px 0px 4px;
font-size: 0.9em;
color: inherit;
}
.md-tag {
color: inherit;
}
.md-toc {
margin-top: 20px;
padding-bottom: 20px;
}
.sidebar-tabs {
border-bottom: none;
}
#typora-quick-open {
border: 1px solid #ddd;
background-color: #f8f8f8;
}
#typora-quick-open-item {
background-color: #FAFAFA;
border-color: #FEFEFE #e5e5e5 #e5e5e5 #eee;
border-style: solid;
border-width: 1px;
}
#md-notification:before {
top: 10px;
}
/** focus mode */
.on-focus-mode blockquote {
border-left-color: rgba(85, 85, 85, 0.12);
}
header,
.context-menu,
.megamenu-content,
footer {
font-family: "Segoe UI", "Arial", sans-serif;
}
.file-node-content:hover .file-node-icon,
.file-node-content:hover .file-node-open-state {
visibility: visible;
}
.mac-seamless-mode #typora-sidebar {
background-color: #fafafa;
background-color: var(--side-bar-bg-color);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

File diff suppressed because one or more lines are too long

View File

@ -2,18 +2,24 @@
<div>
<div ref="editor" class="editor-component"></div>
<el-dialog
title="Insert Table"
:visible.sync="dialogTableVisible"
:show-close="isShowClose"
:modal="false"
:modal="true"
custom-class="ag-dialog-table"
width="450px"
center
>
<div slot="title" class="dialog-title">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-table"></use>
</svg>
</div>
<el-form :model="tableChecker" :inline="true">
<el-form-item label="Rows">
<el-input-number
ref="rowInput"
size="mini" v-model="tableChecker.rows"
size="mini"
v-model="tableChecker.rows"
controls-position="right"
:min="2"
:max="20"
@ -21,7 +27,8 @@
</el-form-item>
<el-form-item label="Columns">
<el-input-number
size="mini" v-model="tableChecker.columns"
size="mini"
v-model="tableChecker.columns"
controls-position="right"
:min="2"
:max="20"
@ -29,8 +36,16 @@
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogTableVisible = false" size="mini">Cancel</el-button>
<el-button type="primary" @click="handleDialogTableConfirm" size="mini">Ok</el-button>
<el-button @click="dialogTableVisible = false" size="mini">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-close"></use>
</svg>
</el-button>
<el-button type="primary" @click="handleDialogTableConfirm" size="mini">
<svg class="icon" aria-hidden="true">
<use xlink:href="#icon-gou"></use>
</svg>
</el-button>
</div>
</el-dialog>
</div>
@ -48,8 +63,8 @@
isShowClose: false,
dialogTableVisible: false,
tableChecker: {
rows: 2,
columns: 2
rows: 4,
columns: 3
}
}
},
@ -146,13 +161,21 @@
</script>
<style>
@import '../../editor/themes/github.css';
@import '../../editor/themes/light.css';
@import '../../editor/index.css';
.editor-component {
height: calc(100vh - 22px);
overflow: auto;
}
.v-modal {
background: #fff;
opacity: .8;
}
.ag-dialog-table {
background: rgb(239, 239, 239);
box-shadow: none;
}
.ag-dialog-table .dialog-title svg {
width: 1.5em;
height: 1.5em;
}
</style>

View File

@ -0,0 +1,13 @@
<template>
<div class="search-bar">
</div>
</template>
<script>
</script>
<style scoped>
</style>

View File

@ -10,29 +10,7 @@
<div
class="word-count"
@click.stop="handleWordClick"
>{{wordCount.word >= 2 ? `${wordCount.word} Words` : `${wordCount.word} Word`}}</div>
</div>
<div
class="popup"
:class="{ 'show-popup': show }"
@click.stop="noop"
>
<div class="pop-item">
<div class="label">Words</div>
<div class="value">{{wordCount.word}}</div>
</div>
<div class="pop-item">
<div class="label">Paragraphs</div>
<div class="value">{{wordCount.paragraph}}</div>
</div>
<div class="pop-item">
<div class="label">Characters</div>
<div class="value">{{wordCount.character}}</div>
</div>
<div class="pop-item">
<div class="label">All</div>
<div class="value">{{wordCount.all}}</div>
</div>
>{{ `${HASH[show]} ${wordCount[show]}` }}</div>
</div>
</div>
</template>
@ -40,8 +18,14 @@
<script>
export default {
data () {
this.HASH = {
'word': 'W',
'character': 'C',
'paragraph': 'P',
'all': 'A'
}
return {
show: false
show: 'word'
}
},
props: {
@ -49,16 +33,15 @@
active: Boolean,
wordCount: Object
},
created () {
document.addEventListener('click', event => {
this.show = false
})
},
methods: {
handleWordClick () {
this.show = !this.show
},
noop () {}
const ITEMS = ['word', 'paragraph', 'character', 'all']
const len = ITEMS.length
let index = ITEMS.indexOf(this.show)
index += 1
if (index >= len) index = 0
this.show = ITEMS[index]
}
}
}
</script>
@ -69,19 +52,17 @@
user-select: none;
width: 100%;
height: 22px;
border-bottom: 1px solid #ccc;
box-sizing: border-box;
color: #999;
background: linear-gradient(180deg, #ffffff, #efefef);
color: #C0C4CC;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1;
transition: color .4s ease-in;
}
.active {
background: linear-gradient(180deg, #efefef, #ccc);
color: #333;
color: #909399;
}
img {
height: 90%;
@ -104,68 +85,21 @@
right: 0;
width: 100px;
display: flex;
flex-direction: row-reverse;
}
.word-count {
cursor: pointer;
font-size: 12px;
color: #666;
color: #C0C4CC;
height: 15px;
line-height: 15px;
margin-top: 3px;
padding: 0 3px;
border-radius: 2px;
cursor: pointer;
margin-top: 4px;
padding: 1px 5px;
border-radius: 1px;
transition: all .3s ease-in;
}
.word-count:hover {
background: #bbb;
color: #000;
}
.popup {
font-size: 12px;
font-weight: 500;
width: 150px;
height: auto;
padding: 10px;
background: rgb(239, 239, 239);
position: absolute;
top: 35px;
right: 10px;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 6px 0 rgba(0,0,0,.1);
transition: all .2s ease-out;
transform-origin: top;
transform: scale(0);
opacity: .3;
}
.show-popup {
transform: scale(1);
opacity: 1;
}
.popup::before {
content: '';
width: 15px;
height: 15px;
background: rgb(239, 239, 239);
border: 1px solid #ddd;
display: inline-block;
position: absolute;
top: -9px;
right: 60px;
border-right: none;
border-bottom: none;
transform: rotate(45deg);
}
.pop-item {
display: flex;
}
.label {
width: 75px;
flex-shrink: 1;
text-align: right;
font-weight: 600;
}
.value {
padding-left: 25px;
background: #F2F6FC;
color: #606266;
}
</style>

View File

@ -1,3 +1,9 @@
.icon {
width: 1em; height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
@media print {
body .editor-component {
height: auto !important;

View File

@ -4,6 +4,7 @@ import axios from 'axios'
import App from './App'
import store from './store'
import './assets/symbolIcon'
import './index.css'
import { Dialog, Form, FormItem, InputNumber, Button } from 'element-ui'