add markdown parser beginning and test site

This commit is contained in:
HF 2021-06-15 20:58:02 +02:00
parent 399d548794
commit 1b33260520
14 changed files with 2268 additions and 353 deletions

View File

@ -12,7 +12,7 @@
"@babel/react"
],
"plugins": [
"@babel/transform-flow-strip-types",
"@babel/plugin-transform-flow-strip-types",
["@babel/plugin-proposal-decorators", { "legacy": true }],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",

View File

@ -57,6 +57,14 @@ msgstr ""
msgid "Stop flooding."
msgstr ""
#: src/ssr-components/Main.jsx:73
msgid "PixelPlanet.fun"
msgstr ""
#: src/ssr-components/Main.jsx:75
msgid "Place color pixels on an map styled canvas with other players online"
msgstr ""
#: src/ssr-components/Globe.jsx:44
msgid "Double click on globe to go back."
msgstr ""
@ -73,14 +81,6 @@ msgstr ""
msgid "A 3D globe of our whole map"
msgstr ""
#: src/ssr-components/Main.jsx:73
msgid "PixelPlanet.fun"
msgstr ""
#: src/ssr-components/Main.jsx:75
msgid "Place color pixels on an map styled canvas with other players online"
msgstr ""
#: src/routes/reset_password.js:58
msgid "You sent an empty password or invalid data :("
msgstr ""
@ -290,6 +290,66 @@ msgstr ""
msgid "Server error occured"
msgstr ""
#: src/routes/api/auth/verify.js:25
#: src/routes/api/auth/verify.js:32
msgid "Mail verification"
msgstr ""
#: src/routes/api/auth/verify.js:26
msgid "You are now verified :)"
msgstr ""
#: src/routes/api/auth/verify.js:32
msgid ""
"Your mail verification code is invalid or already expired :(, please "
"request a new one."
msgstr ""
#: src/routes/api/auth/logout.js:13
msgid "You are not even logged in."
msgstr ""
#: src/routes/api/auth/register.js:31
msgid "E-Mail already in use."
msgstr ""
#: src/routes/api/auth/register.js:33
msgid "Username already in use."
msgstr ""
#: src/routes/api/auth/register.js:61
msgid "Failed to create new user :("
msgstr ""
#: src/routes/api/auth/register.js:77
msgid "Failed to establish session after register :("
msgstr ""
#: src/routes/api/auth/change_mail.js:41
#: src/routes/api/auth/change_passwd.js:37
#: src/routes/api/auth/delete_account.js:38
msgid "You are not authenticated."
msgstr ""
#: src/routes/api/auth/change_mail.js:50
#: src/routes/api/auth/change_passwd.js:46
#: src/routes/api/auth/delete_account.js:48
msgid "Incorrect password!"
msgstr ""
#: src/ssr-components/RedirectionPage.jsx:20
msgid "You will be automatically redirected after 15s"
msgstr ""
#: src/ssr-components/RedirectionPage.jsx:21
#, javascript-format
msgid "Or ${ clickHere } to go back to pixelplanet"
msgstr ""
#: src/ssr-components/RedirectionPage.jsx:25
msgid "PixelPlanet.fun Accounts"
msgstr ""
#: src/canvasesDesc.js:19
msgid "Earth"
msgstr ""
@ -346,64 +406,4 @@ msgstr ""
#: src/canvasesDesc.js:34
msgid "Black and White canvas"
msgstr ""
#: src/routes/api/auth/logout.js:13
msgid "You are not even logged in."
msgstr ""
#: src/routes/api/auth/register.js:31
msgid "E-Mail already in use."
msgstr ""
#: src/routes/api/auth/register.js:33
msgid "Username already in use."
msgstr ""
#: src/routes/api/auth/register.js:61
msgid "Failed to create new user :("
msgstr ""
#: src/routes/api/auth/register.js:77
msgid "Failed to establish session after register :("
msgstr ""
#: src/routes/api/auth/verify.js:25
#: src/routes/api/auth/verify.js:32
msgid "Mail verification"
msgstr ""
#: src/routes/api/auth/verify.js:26
msgid "You are now verified :)"
msgstr ""
#: src/routes/api/auth/verify.js:32
msgid ""
"Your mail verification code is invalid or already expired :(, please "
"request a new one."
msgstr ""
#: src/routes/api/auth/change_mail.js:41
#: src/routes/api/auth/change_passwd.js:37
#: src/routes/api/auth/delete_account.js:38
msgid "You are not authenticated."
msgstr ""
#: src/routes/api/auth/change_mail.js:50
#: src/routes/api/auth/change_passwd.js:46
#: src/routes/api/auth/delete_account.js:48
msgid "Incorrect password!"
msgstr ""
#: src/ssr-components/RedirectionPage.jsx:20
msgid "You will be automatically redirected after 15s"
msgstr ""
#: src/ssr-components/RedirectionPage.jsx:21
#, javascript-format
msgid "Or ${ clickHere } to go back to pixelplanet"
msgstr ""
#: src/ssr-components/RedirectionPage.jsx:25
msgid "PixelPlanet.fun Accounts"
msgstr ""

View File

@ -3,6 +3,11 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
#: src/components/CoordinatesBox.jsx:29
#: src/controls/keypress.js:59
msgid "Copied!"
msgstr ""
#: src/ui/placePixel.js:53
msgid "Error :("
msgstr ""
@ -96,11 +101,6 @@ msgstr ""
msgid "Error ${ retCode }"
msgstr ""
#: src/components/CoordinatesBox.jsx:29
#: src/controls/keypress.js:59
msgid "Copied!"
msgstr ""
#: src/actions/index.js:627
msgid "Register New Account"
msgstr ""
@ -117,11 +117,6 @@ msgstr ""
msgid "Look at past Canvases"
msgstr ""
#: src/components/Converter.jsx:615
#: src/components/CoordinatesBox.jsx:32
msgid "Copy to Clipboard"
msgstr ""
#: src/components/OnlineBox.jsx:30
msgid "User online"
msgstr ""
@ -130,6 +125,11 @@ msgstr ""
msgid "Pixels placed"
msgstr ""
#: src/components/Converter.jsx:615
#: src/components/CoordinatesBox.jsx:32
msgid "Copy to Clipboard"
msgstr ""
#: src/components/Admintools.jsx:224
#: src/components/ModalRoot.jsx:69
#: src/components/Window.jsx:138
@ -141,6 +141,11 @@ msgstr ""
msgid "Restore"
msgstr ""
#: src/components/buttons/CanvasSwitchButton.jsx:23
#: src/components/windows/index.js:22
msgid "Canvas Selection"
msgstr ""
#: src/components/buttons/ChatButton.jsx:92
msgid "Close Chat"
msgstr ""
@ -149,11 +154,6 @@ msgstr ""
msgid "Open Chat"
msgstr ""
#: src/components/buttons/CanvasSwitchButton.jsx:23
#: src/components/windows/index.js:22
msgid "Canvas Selection"
msgstr ""
#: src/components/buttons/ExpandMenuButton.jsx:23
msgid "Close Menu"
msgstr ""
@ -215,15 +215,29 @@ msgstr ""
msgid "Resize"
msgstr ""
#: src/components/buttons/GlobeButton.jsx:35
msgid "Globe View"
msgstr ""
#: src/components/buttons/HelpButton.jsx:23
#: src/components/windows/index.js:16
msgid "Help"
msgstr ""
#: src/components/buttons/SettingsButton.jsx:23
#: src/components/windows/index.js:17
msgid "Settings"
msgstr ""
#: src/components/buttons/LogInButton.jsx:23
#: src/components/windows/index.js:18
msgid "User Area"
msgstr ""
#: src/components/buttons/DownloadButton.jsx:37
msgid "Make Screenshot"
msgstr ""
#: src/components/buttons/GlobeButton.jsx:35
msgid "Globe View"
msgstr ""
#: src/components/buttons/PalselButton.jsx:31
msgid "Close Palette"
msgstr ""
@ -232,18 +246,8 @@ msgstr ""
msgid "Open Palette"
msgstr ""
#: src/components/buttons/LogInButton.jsx:23
#: src/components/windows/index.js:18
msgid "User Area"
msgstr ""
#: src/components/buttons/SettingsButton.jsx:23
#: src/components/windows/index.js:17
msgid "Settings"
msgstr ""
#: src/components/buttons/DownloadButton.jsx:37
msgid "Make Screenshot"
#: src/components/contextmenus/ChannelContextMenu.jsx:55
msgid "Mute"
msgstr ""
#: src/components/contextmenus/UserContextMenu.jsx:53
@ -258,10 +262,6 @@ msgstr ""
msgid "Block"
msgstr ""
#: src/components/contextmenus/ChannelContextMenu.jsx:55
msgid "Mute"
msgstr ""
#: src/components/windows/index.js:19
msgid "Registration"
msgstr ""
@ -327,6 +327,68 @@ msgstr ""
msgid "Send"
msgstr ""
#: src/components/windows/UserArea.jsx:27
msgid "Profile"
msgstr ""
#: src/components/windows/UserArea.jsx:30
msgid "Ranking"
msgstr ""
#: src/components/windows/UserArea.jsx:33
msgid "Converter"
msgstr ""
#: src/components/windows/UserArea.jsx:39
msgid "Admintools"
msgstr ""
#: src/components/windows/UserArea.jsx:39
msgid "Modtools"
msgstr ""
#: src/components/windows/UserArea.jsx:40
msgid "Loading..."
msgstr ""
#: src/components/windows/UserArea.jsx:47
msgid "Consider joining us on Guilded:"
msgstr ""
#: src/components/windows/Register.jsx:81
msgid "Register new account here"
msgstr ""
#: src/components/windows/Register.jsx:92
msgid "Name"
msgstr ""
#: src/components/windows/ForgotPassword.jsx:82
#: src/components/windows/Register.jsx:100
msgid "Email"
msgstr ""
#: src/components/ChangeMail.jsx:80
#: src/components/DeleteAccount.jsx:62
#: src/components/LogInForm.jsx:83
#: src/components/windows/Register.jsx:108
msgid "Password"
msgstr ""
#: src/components/windows/Register.jsx:116
msgid "Confirm Password"
msgstr ""
#: src/components/Admintools.jsx:311
#: src/components/Admintools.jsx:392
#: src/components/Admintools.jsx:466
#: src/components/Admintools.jsx:510
#: src/components/Admintools.jsx:594
#: src/components/windows/ForgotPassword.jsx:86
#: src/components/windows/Register.jsx:119
msgid "Submit"
msgstr ""
#: src/components/windows/Help.jsx:35
msgid "your IP"
msgstr ""
@ -493,68 +555,6 @@ msgstr ""
msgid "Partners:"
msgstr ""
#: src/components/windows/Register.jsx:81
msgid "Register new account here"
msgstr ""
#: src/components/windows/Register.jsx:92
msgid "Name"
msgstr ""
#: src/components/windows/ForgotPassword.jsx:82
#: src/components/windows/Register.jsx:100
msgid "Email"
msgstr ""
#: src/components/ChangeMail.jsx:80
#: src/components/DeleteAccount.jsx:62
#: src/components/LogInForm.jsx:83
#: src/components/windows/Register.jsx:108
msgid "Password"
msgstr ""
#: src/components/windows/Register.jsx:116
msgid "Confirm Password"
msgstr ""
#: src/components/Admintools.jsx:311
#: src/components/Admintools.jsx:392
#: src/components/Admintools.jsx:466
#: src/components/Admintools.jsx:510
#: src/components/Admintools.jsx:594
#: src/components/windows/ForgotPassword.jsx:86
#: src/components/windows/Register.jsx:119
msgid "Submit"
msgstr ""
#: src/components/windows/UserArea.jsx:27
msgid "Profile"
msgstr ""
#: src/components/windows/UserArea.jsx:30
msgid "Ranking"
msgstr ""
#: src/components/windows/UserArea.jsx:33
msgid "Converter"
msgstr ""
#: src/components/windows/UserArea.jsx:39
msgid "Admintools"
msgstr ""
#: src/components/windows/UserArea.jsx:39
msgid "Modtools"
msgstr ""
#: src/components/windows/UserArea.jsx:40
msgid "Loading..."
msgstr ""
#: src/components/windows/UserArea.jsx:47
msgid "Consider joining us on Guilded:"
msgstr ""
#: src/components/windows/Settings.jsx:127
msgid "Show Grid"
msgstr ""
@ -642,6 +642,25 @@ msgstr ""
msgid "Select Language"
msgstr ""
#: src/components/windows/CanvasSelect.jsx:32
msgid ""
"Select the canvas you want to use. Every canvas is unique and has "
"different palettes, cooldown and requirements. Archive of closed canvases "
"can be accessed here:"
msgstr ""
#: src/components/windows/CanvasSelect.jsx:40
msgid "Archive"
msgstr ""
#: src/components/windows/ForgotPassword.jsx:60
msgid "Sent you a mail with instructions to reset your password."
msgstr ""
#: src/components/windows/ForgotPassword.jsx:71
msgid "Enter your mail address and we will send you a new password:"
msgstr ""
#: src/components/windows/Archive.jsx:20
msgid ""
"While we tend to not delete canvases, some canvases are started for fun or "
@ -691,25 +710,6 @@ msgstr ""
msgid "You must be logged in to chat"
msgstr ""
#: src/components/windows/CanvasSelect.jsx:32
msgid ""
"Select the canvas you want to use. Every canvas is unique and has "
"different palettes, cooldown and requirements. Archive of closed canvases "
"can be accessed here:"
msgstr ""
#: src/components/windows/CanvasSelect.jsx:40
msgid "Archive"
msgstr ""
#: src/components/windows/ForgotPassword.jsx:60
msgid "Sent you a mail with instructions to reset your password."
msgstr ""
#: src/components/windows/ForgotPassword.jsx:71
msgid "Enter your mail address and we will send you a new password:"
msgstr ""
#: src/utils/validation.js:18
msgid "Email can't be empty."
msgstr ""
@ -758,158 +758,6 @@ msgstr ""
msgid "Password must be shorter than 60 characters."
msgstr ""
#: src/components/LogInArea.jsx:21
msgid "Login to access more features and stats."
msgstr ""
#: src/components/LogInArea.jsx:23
msgid "Login with Name or Mail:"
msgstr ""
#: src/components/LogInArea.jsx:30
msgid "I forgot my Password."
msgstr ""
#: src/components/LogInArea.jsx:31
msgid "or login with:"
msgstr ""
#: src/components/LogInArea.jsx:72
msgid "or register here:"
msgstr ""
#: src/components/LogInArea.jsx:79
msgid "Register"
msgstr ""
#: src/components/Rankings.jsx:28
msgid "Total"
msgstr ""
#: src/components/Rankings.jsx:36
msgid "Daily"
msgstr ""
#: src/components/Rankings.jsx:40
msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC."
msgstr ""
#: src/components/Converter.jsx:280
msgid "Choose Canvas"
msgstr ""
#: src/components/Converter.jsx:306
msgid "Palette Download"
msgstr ""
#: src/components/Converter.jsx:308
#, javascript-format
msgid "Palette for ${ gimpLink }"
msgstr ""
#: src/components/Converter.jsx:326
#, javascript-format
msgid "Credit for the Palette of the Moon goes to ${ starhouseLink }."
msgstr ""
#: src/components/Converter.jsx:329
msgid "Image Converter"
msgstr ""
#: src/components/Converter.jsx:330
msgid "Convert an image to canvas colors"
msgstr ""
#: src/components/Converter.jsx:341
msgid "Choose Strategy"
msgstr ""
#: src/components/Converter.jsx:368
msgid "Choose Color Mode"
msgstr ""
#: src/components/Converter.jsx:406
msgid "Add Grid (uncheck if you need a 1:1 template)"
msgstr ""
#: src/components/Converter.jsx:431
#: src/components/Converter.jsx:447
msgid "Offset"
msgstr ""
#: src/components/Converter.jsx:477
msgid "Scale Image"
msgstr ""
#: src/components/Converter.jsx:489
msgid "Width"
msgstr ""
#: src/components/Converter.jsx:519
msgid "Height"
msgstr ""
#: src/components/Converter.jsx:557
msgid "Keep Ratio"
msgstr ""
#: src/components/Converter.jsx:570
msgid "Anti Aliasing"
msgstr ""
#: src/components/Converter.jsx:584
msgid "Reset"
msgstr ""
#: src/components/Converter.jsx:603
msgid "Download Template"
msgstr ""
#: src/components/UserAreaContent.jsx:63
msgid "Todays Placed Pixels"
msgstr ""
#: src/components/UserAreaContent.jsx:67
msgid "Daily Rank"
msgstr ""
#: src/components/UserAreaContent.jsx:72
msgid "Placed Pixels"
msgstr ""
#: src/components/UserAreaContent.jsx:76
msgid "Total Rank"
msgstr ""
#: src/components/UserAreaContent.jsx:81
#, javascript-format
msgid "Your name is: ${ name }"
msgstr ""
#: src/components/UserAreaContent.jsx:87
msgid "Log out"
msgstr ""
#: src/components/UserAreaContent.jsx:93
msgid "Change Username"
msgstr ""
#: src/components/UserAreaContent.jsx:102
msgid "Change Mail"
msgstr ""
#: src/components/UserAreaContent.jsx:110
msgid "Change Password"
msgstr ""
#: src/components/UserAreaContent.jsx:116
msgid "Delete Account"
msgstr ""
#: src/components/UserAreaContent.jsx:123
msgid "Social Settings"
msgstr ""
#: src/components/Admintools.jsx:184
msgid "Build image on canvas."
msgstr ""
@ -988,6 +836,75 @@ msgstr ""
msgid "User Name"
msgstr ""
#: src/components/LogInArea.jsx:21
msgid "Login to access more features and stats."
msgstr ""
#: src/components/LogInArea.jsx:23
msgid "Login with Name or Mail:"
msgstr ""
#: src/components/LogInArea.jsx:30
msgid "I forgot my Password."
msgstr ""
#: src/components/LogInArea.jsx:31
msgid "or login with:"
msgstr ""
#: src/components/LogInArea.jsx:72
msgid "or register here:"
msgstr ""
#: src/components/LogInArea.jsx:79
msgid "Register"
msgstr ""
#: src/components/UserAreaContent.jsx:63
msgid "Todays Placed Pixels"
msgstr ""
#: src/components/UserAreaContent.jsx:67
msgid "Daily Rank"
msgstr ""
#: src/components/UserAreaContent.jsx:72
msgid "Placed Pixels"
msgstr ""
#: src/components/UserAreaContent.jsx:76
msgid "Total Rank"
msgstr ""
#: src/components/UserAreaContent.jsx:81
#, javascript-format
msgid "Your name is: ${ name }"
msgstr ""
#: src/components/UserAreaContent.jsx:87
msgid "Log out"
msgstr ""
#: src/components/UserAreaContent.jsx:93
msgid "Change Username"
msgstr ""
#: src/components/UserAreaContent.jsx:102
msgid "Change Mail"
msgstr ""
#: src/components/UserAreaContent.jsx:110
msgid "Change Password"
msgstr ""
#: src/components/UserAreaContent.jsx:116
msgid "Delete Account"
msgstr ""
#: src/components/UserAreaContent.jsx:123
msgid "Social Settings"
msgstr ""
#: src/components/ChangeMail.jsx:91
#: src/components/ChangeName.jsx:68
#: src/components/ChangePassword.jsx:110
@ -995,6 +912,18 @@ msgstr ""
msgid "Save"
msgstr ""
#: src/components/Rankings.jsx:28
msgid "Total"
msgstr ""
#: src/components/Rankings.jsx:36
msgid "Daily"
msgstr ""
#: src/components/Rankings.jsx:40
msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC."
msgstr ""
#: src/components/CanvasItem.jsx:27
msgid "Cooldown"
msgstr ""
@ -1024,6 +953,77 @@ msgstr ""
msgid "Dimensions"
msgstr ""
#: src/components/Converter.jsx:280
msgid "Choose Canvas"
msgstr ""
#: src/components/Converter.jsx:306
msgid "Palette Download"
msgstr ""
#: src/components/Converter.jsx:308
#, javascript-format
msgid "Palette for ${ gimpLink }"
msgstr ""
#: src/components/Converter.jsx:326
#, javascript-format
msgid "Credit for the Palette of the Moon goes to ${ starhouseLink }."
msgstr ""
#: src/components/Converter.jsx:329
msgid "Image Converter"
msgstr ""
#: src/components/Converter.jsx:330
msgid "Convert an image to canvas colors"
msgstr ""
#: src/components/Converter.jsx:341
msgid "Choose Strategy"
msgstr ""
#: src/components/Converter.jsx:368
msgid "Choose Color Mode"
msgstr ""
#: src/components/Converter.jsx:406
msgid "Add Grid (uncheck if you need a 1:1 template)"
msgstr ""
#: src/components/Converter.jsx:431
#: src/components/Converter.jsx:447
msgid "Offset"
msgstr ""
#: src/components/Converter.jsx:477
msgid "Scale Image"
msgstr ""
#: src/components/Converter.jsx:489
msgid "Width"
msgstr ""
#: src/components/Converter.jsx:519
msgid "Height"
msgstr ""
#: src/components/Converter.jsx:557
msgid "Keep Ratio"
msgstr ""
#: src/components/Converter.jsx:570
msgid "Anti Aliasing"
msgstr ""
#: src/components/Converter.jsx:584
msgid "Reset"
msgstr ""
#: src/components/Converter.jsx:603
msgid "Download Template"
msgstr ""
#: src/components/LogInForm.jsx:76
msgid "Name or Email"
msgstr ""
@ -1046,16 +1046,6 @@ msgstr ""
msgid "Click here to request a new verification mail."
msgstr ""
#: src/components/ChangeMail.jsx:59
msgid ""
"Changed Mail successfully. We sent you a verification mail, "
"please verify your new mail address."
msgstr ""
#: src/components/ChangeMail.jsx:87
msgid "New Mail"
msgstr ""
#: src/components/ChangePassword.jsx:22
msgid "Passwords do not match."
msgstr ""
@ -1076,10 +1066,24 @@ msgstr ""
msgid "Confirm New Password"
msgstr ""
#: src/components/ChangeMail.jsx:59
msgid ""
"Changed Mail successfully. We sent you a verification mail, "
"please verify your new mail address."
msgstr ""
#: src/components/ChangeMail.jsx:87
msgid "New Mail"
msgstr ""
#: src/components/ChangeName.jsx:64
msgid "New Username"
msgstr ""
#: src/components/DeleteAccount.jsx:66
msgid "Yes, Delete My Account!"
msgstr ""
#: src/components/SocialSettings.jsx:38
msgid "Block all Private Messages"
msgstr ""
@ -1092,10 +1096,6 @@ msgstr ""
msgid "You have no users blocked"
msgstr ""
#: src/components/DeleteAccount.jsx:66
msgid "Yes, Delete My Account!"
msgstr ""
#: src/components/windows/Help.jsx:15
#: src/components/windows/Settings.jsx:129
msgctxt "keybinds"

1572
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
"bluebird": "^3.5.0",
"body-parser": "^1.17.2",
"bufferutil": "^4.0.3",
"commonmark": "^0.29.3",
"compression": "^1.7.3",
"connect-redis": "^5.1.0",
"cookie": "^0.4.1",
@ -86,6 +87,7 @@
"ws": "^7.4.4"
},
"devDependencies": {
"@babel/cli": "^7.14.3",
"@babel/core": "^7.13.10",
"@babel/node": "^7.13.10",
"@babel/plugin-proposal-class-properties": "^7.13.0",

207
src/core/Markdown.js Normal file
View File

@ -0,0 +1,207 @@
/*
* Markdown parsing
*
* we do not support all markdown, but do additionally parse extra
* stuff like pixelplanet coords and usernames and bare links
*
* @flow
*/
export default class MarkdownParser {
static nonWithespace = /\S|$/;
static expArticle = /(?:\n|^)\s*?(?=\#)|(?<=(?:\n|^)\s*?(?=\#).*?)\n/;
constructor(opt) {
this.parseLinks = opt && opt.parseLinks || false;
this.tabWidth = opt && opt.tabWidth || 4;
this.newlineBreaksArticles = opt && opt.newlineBreaksArticles || true;
}
parseText(text: string, level = 0, start = 0) {
let mdArray = [];
let iter = start;
while (iter < text.length) {
const [aMdArray, newIter] = this.parseArticle(text, iter, level);
iter = newIter;
mdArray = mdArray.concat(aMdArray);
// either heading hit or article end
if (text[iter] === '#') {
let subLvl = 0;
for (;iter + subLvl <= text.length && text[iter + subLvl] === '#'; subLvl += 1) {}
if (subLvl <= level || level === 6) {
// end of article
// encountered title with same level or lower
break;
} else {
// child article
let lineEnd = text.indexOf('\n', iter);
if (lineEnd === -1) lineEnd = text.length;
const title = text.slice(iter + subLvl, lineEnd).trimLeft();
subLvl = Math.min(subLvl, 6);
const [subMdArray, newIter] = this.parseText(
text, subLvl, lineEnd + 1,
);
mdArray.push(['a', subLvl, title, subMdArray]);
iter = newIter;
}
} else {
break;
}
}
return [mdArray, iter];
}
stoppingCondition(text: string, iter: number) {
const chr = text[iter];
if (chr === '\n'
|| chr === '#'
|| (chr === '`' && text[iter + 1] === '`' && text[iter + 2] === '`')
) {
return true;
}
return false;
}
/*
* parses Articles (contains paragraphs, code-blocks, numeration, etc.)
* returns when encountering heading of level or lower (iter is at # position)
* or heading-cancel with three spaces (iter is past newlines)
*/
parseArticle(text: string, start: number, level = 0) {
let iter = start;
const mdArray = [];
let paraStart = iter;
while (true) {
if (iter >= text.length) {
if (paraStart < text.length) {
mdArray.push(['p', text.slice(paraStart)]);
}
break;
}
// beginning of line
const paraLineStart = iter;
iter = this.skipSpaces(text, iter);
if (stoppingCondition(text, iter)) {
const chr = text[iter];
// encountered something - save paragraph
if (paraLineStart - 1 > paraStart) {
mdArray.push(['p', text.slice(paraStart, paraLineStart - 1)]);
}
if (chr === '\n') {
iter = this.skipSpaces(text, iter + 1);
if (text[iter] === '\n') {
if (level > 0 && this.newlineBreaksArticles) {
break;
}
iter += 1;
}
} else if (chr === '#') {
break;
} else if (chr === '`') {
// code block
const [cbArray, newIter] = this.parseCodeBlock(text, iter + 3);
mdArray.push(cbArray);
iter = newIter;
}
paraStart = iter;
continue;
}
// rest of line
for (;iter < text.length && text[iter] !== '\n'; iter += 1) {}
iter += 1;
}
return [mdArray, iter];
}
/*
* parse Code Block
* start is first character after the initializing ```
* we just parse till the ending occures
*/
parseCodeBlock(text: string, start: number) {
const cbStart = this.skipSpaces(text, start, true);
let iter = cbStart;
while (true) {
if (iter >= text.length) {
return [['cb', text.slice(cbStart)], iter];
}
iter = this.skipSpaces(text, iter, true);
if (text[iter] === '`'
&& text[iter + 1] === '`'
&& text[iter + 2] === '`'
) {
const nextIter = this.skipSpaces(text, iter + 3, true);
return [['cb', text.slice(cbStart, iter)], nextIter];
}
for (;iter < text.length && text[iter] !== '\n'; iter += 1) {}
}
}
skipSpaces(text: string, start: number, skipNewlines = false) {
let iter = start;
for (;iter < text.length; iter += 1) {
const char = text[iter];
if (char !== ' ' && char !== '\t' && (!skipNewlines || char !== '\n')) {
break;
}
}
return iter;
}
parseIndents(text: string) {
const lines = text.split('\n');
const indents = [];
const { tabWidth } = this;
/*
* Get indentation of lines
* @param text: string of text to parse
* @return [indents, lines]:
* indents: Array of normalized numerical indents
* lines: Array of trimmed lines
*/
for (let i = 0; i < lines.length; i += 1) {
const line = lines[i];
let indent = 0;
for (let c = 0; c < line.length; c += 1) {
const chr = line[c];
if (chr === '\t') {
indent += this.tabWidth;
} else if (chr === ' ') {
indent += 1;
} else {
break;
}
}
lines[i] = line.trim();
indents.push(indent);
}
// normalize
let min = indents[0];
let max = indents[0];
for (let m = 0; m < indents.length; m += 1) {
const indent = indents[m];
if (indent < min) min = indent;
if (indent > max) max = indent;
}
let cnt = 0;
console.log(min, max);
for (let n = min; n <= max; n += 1) {
let available = false;
for (let c = 0; c < indents.length; c += 1) {
if (indents[c] === n) {
if (!available) available = true;
indents[c] = cnt;
}
}
if (available) cnt += 1;
}
console.log(lines);
console.log(indents);
}
}

View File

@ -0,0 +1,28 @@
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"firefox": "60"
}
}
],
"@babel/typescript",
"@babel/react"
],
"plugins": [
"@babel/plugin-transform-flow-strip-types",
["@babel/plugin-proposal-decorators", { "legacy": true }],
"@babel/plugin-proposal-function-sent",
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-throw-expressions",
["@babel/plugin-proposal-class-properties", { "loose": true }],
"@babel/proposal-object-rest-spread",
"@babel/transform-react-constant-elements",
"@babel/transform-react-inline-elements",
"transform-react-remove-prop-types",
"transform-react-pure-class-to-function",
]
}

View File

@ -0,0 +1,19 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Markdown Parser Test</title>
<meta name="description" content="Testing Markdown Parser">
<meta name="author" content="hf">
</head>
<body>
<script src="./script.js"></script>
<textarea id="input" name="text" cols="100" rows="30"></textarea><br />
<p>Parse-time: <span id="time"/></p>
<textarea id="output" name="text" cols="100" rows="30" readonly></textarea>
</body>
</html>

View File

@ -0,0 +1,24 @@
import MarkdownParser from '../../src/core/Markdown';
import { Parser } from 'commonmark';
document.addEventListener('DOMContentLoaded', () => {
const reader = new Parser({smart: true});
const a = new MarkdownParser();
const input = document.getElementById('input');
const output = document.getElementById('output');
const time = document.getElementById('time');
input.addEventListener('input', () => {
let startt = Date.now();
const [arr] = a.parseText(input.value);
time.innerHTML = Date.now() - startt + 'ms';
startt = Date.now();
const parsed = reader.parse(input.value);
time.innerHTML += ' / commonmark: ' + (Date.now() - startt) + 'ms';
console.log(parsed);
output.value = JSON.stringify(arr, null, 2);
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
/*! http://mths.be/repeat v0.2.0 by @mathias */

View File

@ -0,0 +1,60 @@
var path = require('path');
var webpack = require('webpack');
var babelPlugins = [
'@babel/plugin-transform-flow-strip-types',
['@babel/plugin-proposal-decorators', { legacy: true }],
'@babel/plugin-proposal-function-sent',
'@babel/plugin-proposal-export-namespace-from',
'@babel/plugin-proposal-numeric-separator',
'@babel/plugin-proposal-throw-expressions',
['@babel/plugin-proposal-class-properties', { loose: true }],
'@babel/proposal-object-rest-spread',
// react-optimize
'@babel/transform-react-constant-elements',
'@babel/transform-react-inline-elements',
'transform-react-remove-prop-types',
'transform-react-pure-class-to-function',
];
module.exports = {
name: 'script',
target: 'web',
mode: 'production',
entry: [ path.resolve(__dirname, './mdtest.js') ],
output: {
path: __dirname,
filename: 'script.js',
},
resolve: {
extensions: ['.js', '.jsx' ],
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {
targets: {
browsers: [ 'defaults' ],
},
modules: false,
}],
'@babel/react',
],
plugins: babelPlugins,
},
},
],
},
stats: {
colors: true,
},
};

View File

@ -42,7 +42,7 @@ export function buildWebpackClientConfig(
}
const babelPlugins = [
'@babel/transform-flow-strip-types',
'@babel/plugin-transform-flow-strip-types',
['@babel/plugin-proposal-decorators', { legacy: true }],
'@babel/plugin-proposal-function-sent',
'@babel/plugin-proposal-export-namespace-from',

View File

@ -28,7 +28,7 @@ const basePackageValues = {
const ttag = {};
const babelPlugins = [
'@babel/transform-flow-strip-types',
'@babel/plugin-transform-flow-strip-types',
['@babel/plugin-proposal-decorators', { legacy: true }],
'@babel/plugin-proposal-function-sent',
'@babel/plugin-proposal-export-namespace-from',