Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
b8c01524
Commit
b8c01524
authored
Dec 09, 2021
by
steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
web: update memo editor and about me
parent
06bffd0b
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
83 additions
and
93 deletions
+83
-93
AboutSiteDialog.tsx
web/src/components/AboutSiteDialog.tsx
+7
-29
MemoEditor.tsx
web/src/components/MemoEditor.tsx
+11
-10
marked.ts
web/src/helpers/marked.ts
+1
-1
convertResourceToDataURL.ts
web/src/labs/html2image/convertResourceToDataURL.ts
+4
-4
getFontsStyleElement.ts
web/src/labs/html2image/getFontsStyleElement.ts
+46
-0
index.ts
web/src/labs/html2image/index.ts
+10
-45
about-site-dialog.less
web/src/less/about-site-dialog.less
+3
-4
memolist.less
web/src/less/memolist.less
+1
-0
No files found.
web/src/components/AboutSiteDialog.tsx
View file @
b8c01524
...
...
@@ -12,45 +12,23 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
<
span
className=
"icon-text"
>
🤠
</
span
>
关于
<
b
>
Memos
</
b
>
<
span
className=
"icon-text"
>
🤠
</
span
>
About
<
b
>
Memos
</
b
>
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
</
button
>
</
div
>
<
div
className=
"dialog-content-container"
>
<
p
>
一个碎片化知识记录工具。
</
p
>
<
br
/>
<
i
>
为何做这个?
</
i
>
<
ul
>
<
li
>
实践
<
strong
>
卢曼卡片盒笔记法
</
strong
>
;
</
li
>
<
li
>
用于记录:📅 每日/周计划、💡 突发奇想、📕 读后感...
</
li
>
<
li
>
代替了我在微信上经常使用的“文件传输助手”;
</
li
>
<
li
>
打造一个属于自己的轻量化“卡片”笔记簿;
</
li
>
</
ul
>
<
br
/>
<
i
>
有何特点呢?
</
i
>
<
ul
>
<
li
>
✨
{
" "
}
<
a
target=
"_blank"
href=
"https://github.com/boojack/insmemo-web"
rel=
"noreferrer"
>
开源项目
</
a
>
</
li
>
<
li
>
😋 精美且细节的视觉样式;
</
li
>
<
li
>
📑 体验优良的交互逻辑;
</
li
>
</
ul
>
<
br
/>
<
a
target=
"_blank"
href=
"https://github.com/boojack/insmemo-web/discussions"
rel=
"noreferrer"
>
🤔 问题反馈
</
a
>
<
p
>
An open-source alternative to
<
a
href=
"https://flomoapp.com"
>
flomo
</
a
>
.
</
p
>
<
p
>
You are in charge of your data and customizations.
</
p
>
<
p
>
Built with React and Go.
</
p
>
<
br
/>
<
p
>
Enjoy it and have fun~
</
p
>
<
hr
/>
<
p
className=
"normal-text"
>
Last updated on
<
span
className=
"pre-text"
>
2021/1
1/26 16:17:44
</
span
>
🎉
Last updated on
<
span
className=
"pre-text"
>
2021/1
2/09 10:14:32
</
span
>
🎉
</
p
>
</
div
>
</>
...
...
web/src/components/MemoEditor.tsx
View file @
b8c01524
...
...
@@ -16,26 +16,27 @@ const MemoEditor: React.FC<Props> = (props: Props) => {
const
{
className
,
editMemoId
}
=
props
;
const
{
globalState
}
=
useContext
(
appContext
);
const
editorRef
=
useRef
<
EditorRefActions
>
(
null
);
const
prevGlobalStateRef
=
useRef
(
globalState
);
useEffect
(()
=>
{
if
(
globalState
.
markMemoId
)
{
if
(
editMemoId
===
globalState
.
editMemoId
||
(
!
editMemoId
&&
!
globalState
.
editMemoId
))
{
const
editorCurrentValue
=
editorRef
.
current
?.
getContent
();
const
memoLinkText
=
`
${
editorCurrentValue
?
"
\n
"
:
""
}
Mark: [@MEMO](
${
globalState
.
markMemoId
}
)`
;
editorRef
.
current
?.
insertText
(
memoLinkText
);
globalStateService
.
setMarkMemoId
(
""
);
}
}
},
[
globalState
.
markMemoId
]);
if
(
editMemoId
&&
globalState
.
editMemoId
)
{
const
editMemo
=
memoService
.
getMemoById
(
globalState
.
editMemoId
);
useEffect
(()
=>
{
if
(
editMemoId
)
{
const
editMemo
=
memoService
.
getMemoById
(
editMemoId
);
if
(
editMemo
)
{
editorRef
.
current
?.
setContent
(
editMemo
.
content
??
""
);
editorRef
.
current
?.
focus
();
}
}
prevGlobalStateRef
.
current
=
globalState
;
},
[
globalState
.
markMemoId
,
globalState
.
editMemoId
]);
},
[
editMemoId
]);
const
handleSaveBtnClick
=
useCallback
(
async
(
content
:
string
)
=>
{
if
(
content
===
""
)
{
...
...
web/src/helpers/marked.ts
View file @
b8c01524
...
...
@@ -54,7 +54,7 @@ const parseCodeToPrism = (codeStr: string): string => {
const
parseMarkedToHtml
=
(
markedStr
:
string
):
string
=>
{
const
htmlText
=
parseCodeToPrism
(
markedStr
)
.
replace
(
DOT_LI_REG
,
"<span class='counter-block'>
•
</span>"
)
.
replace
(
DOT_LI_REG
,
"<span class='counter-block'>
◦
</span>"
)
.
replace
(
NUM_LI_REG
,
"<span class='counter-block'>$1.</span>"
)
.
replace
(
TODO_BLOCK_REG
,
"<span class='todo-block' data-type='todo'>⬜</span>"
)
.
replace
(
DONE_BLOCK_REG
,
"<span class='todo-block' data-type='done'>✅</span>"
)
...
...
web/src/labs/html2image/convertResourceToDataURL.ts
View file @
b8c01524
const
cachedResource
=
new
Map
<
string
,
string
>
();
const
cachedResource
Map
=
new
Map
<
string
,
string
>
();
function
convertResourceToDataURL
(
url
:
string
,
useCache
=
true
):
Promise
<
string
>
{
if
(
useCache
&&
cachedResource
.
has
(
url
))
{
return
Promise
.
resolve
(
cachedResource
.
get
(
url
)
as
string
);
if
(
useCache
&&
cachedResource
Map
.
has
(
url
))
{
return
Promise
.
resolve
(
cachedResource
Map
.
get
(
url
)
as
string
);
}
return
new
Promise
(
async
(
resolve
)
=>
{
...
...
@@ -11,7 +11,7 @@ function convertResourceToDataURL(url: string, useCache = true): Promise<string>
var
reader
=
new
FileReader
();
reader
.
onloadend
=
()
=>
{
const
base64Url
=
reader
.
result
as
string
;
cachedResource
.
set
(
url
,
base64Url
);
cachedResource
Map
.
set
(
url
,
base64Url
);
resolve
(
base64Url
);
};
reader
.
readAsDataURL
(
blob
);
...
...
web/src/labs/html2image/getFontsStyleElement.ts
0 → 100644
View file @
b8c01524
import
convertResourceToDataURL
from
"./convertResourceToDataURL"
;
async
function
getFontsStyleElement
(
element
:
HTMLElement
)
{
const
styleSheets
=
element
.
ownerDocument
.
styleSheets
;
const
fontFamilyStyles
:
CSSStyleDeclaration
[]
=
[];
for
(
const
sheet
of
styleSheets
)
{
for
(
const
rule
of
sheet
.
cssRules
)
{
if
(
rule
.
constructor
.
name
===
"CSSFontFaceRule"
)
{
fontFamilyStyles
.
push
((
rule
as
CSSFontFaceRule
).
style
);
}
}
}
const
styleElement
=
document
.
createElement
(
"style"
);
for
(
const
f
of
fontFamilyStyles
)
{
const
fontFamily
=
f
.
getPropertyValue
(
"font-family"
);
const
fontWeight
=
f
.
getPropertyValue
(
"font-weight"
);
const
src
=
f
.
getPropertyValue
(
"src"
);
const
resourceUrls
=
src
.
split
(
","
).
map
((
s
)
=>
{
return
s
.
replace
(
/url
\(
"
?(
.+
?)
"
?\)
/
,
"$1"
);
});
let
base64Urls
=
[];
for
(
const
url
of
resourceUrls
)
{
try
{
const
base64Url
=
await
convertResourceToDataURL
(
url
);
base64Urls
.
push
(
`url("
${
base64Url
}
")`
);
}
catch
(
error
)
{
// do nth
}
}
styleElement
.
innerHTML
+=
`
@font-face {
font-family: "
${
fontFamily
}
";
src:
${
base64Urls
.
join
(
","
)}
;
font-weight:
${
fontWeight
}
;
}`
;
}
return
styleElement
;
}
export
default
getFontsStyleElement
;
web/src/labs/html2image/index.ts
View file @
b8c01524
...
...
@@ -5,8 +5,8 @@
* 1. html-to-image: https://github.com/bubkoo/html-to-image
* 2. <foreignObject>: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject
*/
import
convertResourceToDataURL
from
"./convertResourceToDataURL"
;
import
getCloneStyledElement
from
"./getCloneStyledElement"
;
import
getFontsStyleElement
from
"./getFontsStyleElement"
;
type
Options
=
Partial
<
{
backgroundColor
:
string
;
...
...
@@ -29,14 +29,14 @@ function convertSVGToDataURL(svg: SVGElement): string {
}
function
generateSVGElement
(
width
:
number
,
height
:
number
,
element
:
HTMLElement
):
SVGSVGElement
{
const
xml
ns
=
"http://www.w3.org/2000/svg"
;
const
svg
=
document
.
createElementNS
(
xmlns
,
"svg"
);
const
xml
NS
=
"http://www.w3.org/2000/svg"
;
const
svg
Element
=
document
.
createElementNS
(
xmlNS
,
"svg"
);
svg
.
setAttribute
(
"width"
,
`
${
width
}
`
);
svg
.
setAttribute
(
"height"
,
`
${
height
}
`
);
svg
.
setAttribute
(
"viewBox"
,
`0 0
${
width
}
${
height
}
`
);
svg
Element
.
setAttribute
(
"width"
,
`
${
width
}
`
);
svg
Element
.
setAttribute
(
"height"
,
`
${
height
}
`
);
svg
Element
.
setAttribute
(
"viewBox"
,
`0 0
${
width
}
${
height
}
`
);
const
foreignObject
=
document
.
createElementNS
(
xml
ns
,
"foreignObject"
);
const
foreignObject
=
document
.
createElementNS
(
xml
NS
,
"foreignObject"
);
foreignObject
.
setAttribute
(
"width"
,
"100%"
);
foreignObject
.
setAttribute
(
"height"
,
"100%"
);
...
...
@@ -45,44 +45,9 @@ function generateSVGElement(width: number, height: number, element: HTMLElement)
foreignObject
.
setAttribute
(
"externalResourcesRequired"
,
"true"
);
foreignObject
.
appendChild
(
element
);
svg
.
appendChild
(
foreignObject
);
svg
Element
.
appendChild
(
foreignObject
);
return
svg
;
}
// TODO need rethink how to get the needed font-family
async
function
getFontsStyleElement
()
{
const
styleElement
=
document
.
createElement
(
"style"
);
const
fonts
=
[
{
name
:
"DINPro"
,
url
:
"/fonts/DINPro-Regular.otf"
,
weight
:
"normal"
,
},
{
name
:
"DINPro"
,
url
:
"/fonts/DINPro-Bold.otf"
,
weight
:
"bold"
,
},
{
name
:
"ubuntu-mono"
,
url
:
"/fonts/UbuntuMono.ttf"
,
weight
:
"normal"
,
},
];
for
(
const
f
of
fonts
)
{
const
base64Url
=
await
convertResourceToDataURL
(
f
.
url
);
styleElement
.
innerHTML
+=
`
@font-face {
font-family: "
${
f
.
name
}
";
src: url("
${
base64Url
}
");
font-weight:
${
f
.
weight
}
;
}`
;
}
return
styleElement
;
return
svgElement
;
}
export
async
function
toSVG
(
element
:
HTMLElement
,
options
?:
Options
)
{
...
...
@@ -95,7 +60,7 @@ export async function toSVG(element: HTMLElement, options?: Options) {
}
const
svg
=
generateSVGElement
(
width
,
height
,
clonedElement
);
svg
.
prepend
(
await
getFontsStyleElement
());
svg
.
prepend
(
await
getFontsStyleElement
(
element
));
const
url
=
convertSVGToDataURL
(
svg
);
...
...
web/src/less/about-site-dialog.less
View file @
b8c01524
...
...
@@ -7,10 +7,8 @@
> .dialog-content-container {
line-height: 1.8;
> ul {
margin: 4px 0;
padding-left: 4px;
width: 100%;
> p {
margin: 2px 0;
}
> hr {
...
...
@@ -26,6 +24,7 @@
font-size: 13px;
color: gray;
white-space: pre-wrap;
.mono-font-family();
}
.pre-text {
...
...
web/src/less/memolist.less
View file @
b8c01524
...
...
@@ -9,6 +9,7 @@
> .memo-edit {
margin-top: 8px;
width: 100%;
}
> .status-text-container {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment