Created
July 31, 2023 12:22
-
-
Save szdytom/186b36dcb2b2da98af1081202c5bf80e to your computer and use it in GitHub Desktop.
6cc - Markdown Foldblock Extension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
int now; | |
string s; | |
vector<int> sta; | |
bool match(string t) { | |
if (now + t.size() > s.size()) | |
return false; | |
if (s.substr(now, t.size()) != t) | |
return false; | |
now += t.size(); | |
return true; | |
} | |
bool matchg() { | |
int old = now; | |
while (now < min(old + 4, (int)s.size()) && s[now] == ' ') | |
now++; | |
if (now - old < 4 && match(">")) | |
return match(" "), true; | |
return now = old, false; | |
} | |
int matchl() { | |
int old = now; | |
while (now < min(old + 4, (int)s.size()) && s[now] == ' ') | |
now++; | |
if (now - old < 4) { | |
bool matched = 0; | |
if (match("+ ") || match("- ") || match("* ")) | |
matched = 1; | |
if (!matched) { | |
bool digit = 0; | |
while (now < s.size() && isdigit(s[now])) | |
digit = 1, now++; | |
if (digit && match(". ")) | |
matched = 1; | |
} | |
if (matched) { | |
for (int i = 0; i <= 3; i++) | |
match(" "); | |
return now - old; | |
} | |
} | |
return now = old, 0; | |
} | |
void matchcb(int &codemode) { | |
int old = now; | |
while (now < min(old + 4, (int)s.size()) && s[now] == ' ') | |
now++; | |
if (now - old < 4) { | |
if ((codemode == 0 || codemode == 1) && match("```")) | |
return void(codemode = codemode ^ 1); | |
if ((codemode == 0 || codemode == 2) && match("~~~")) | |
return void(codemode = codemode ^ 2); | |
} | |
now = old; | |
} | |
void printsta() { | |
for (int x : sta) { | |
if (x == -1) | |
printf("> "); | |
else if (x != -2) | |
printf("%s", string(x, ' ').c_str()); | |
} | |
} | |
void popblank() { | |
while (!s.empty() && isblank(s.back())) | |
s.pop_back(); | |
reverse(s.begin(), s.end()); | |
while (!s.empty() && isblank(s.back())) | |
s.pop_back(); | |
reverse(s.begin(), s.end()); | |
} | |
void foundblock(int type) { | |
printsta(); | |
printf("<details open%s>", | |
type == -2 ? "" : " class=\"detail-fold-default-closed\""); | |
s = s.substr(now); | |
popblank(); | |
if (s.empty()) | |
puts(""); | |
else | |
printf("<summary>%s</summary>\n", s.c_str()); | |
sta.push_back(-2); | |
printsta(), puts(""); | |
} | |
string text; | |
void printhelp(const char *name) { | |
printf("6cc the extended commonmark compiler, built on %s.\n" | |
"Usage: %s <inputfile> <outputfile>\n", | |
__DATE__, name); | |
exit(1); | |
} | |
int main(int argc, char **argv) { | |
if (argc != 3) | |
printhelp(argv[0]); | |
freopen(argv[1], "r", stdin); | |
freopen(argv[2], "w", stdout); | |
bool ended = 0; | |
int codemode = 0; | |
while (!cin.eof() || !ended) { | |
if (cin.eof()) | |
ended = 1, s = ""; | |
else | |
getline(cin, s); | |
text += s + "\n"; | |
now = 0; | |
if (codemode) { | |
for (int t = 0; t < sta.size(); t++) { | |
int x = sta[t]; | |
if (x < 0) | |
assert(matchg()); | |
else | |
assert(match(string(x, ' '))); | |
} | |
printsta(); | |
printf("%s\n", s.substr(now).c_str()); | |
matchcb(codemode); | |
continue; | |
} | |
int t = 0; | |
bool flag = 0; | |
for (; t < sta.size(); t++) { | |
int x = sta[t]; | |
if (x < 0) { | |
if (matchg()) { | |
flag = 1; | |
continue; | |
} | |
break; | |
} else { | |
assert(x); | |
if (match(string(x, ' '))) { | |
flag = 0; | |
continue; | |
} | |
break; | |
} | |
} | |
for (int p = now; p < s.size(); p++) | |
if (s[p] != ' ') | |
goto PS; | |
for (; t < sta.size(); ++t) | |
if (sta[t] < 0) | |
goto PS; | |
printsta(), puts(""); | |
continue; | |
PS: | |
int type = -1; | |
if (flag) { | |
if (match("[+]")) | |
type = -2; | |
else if (match("[-]")) | |
type = -3; | |
if (type != -1) | |
t--; | |
} | |
while (sta.size() > t) { | |
int x = sta.back(); | |
sta.pop_back(); | |
if (x == -2) { | |
printsta(); | |
puts("</details>"); | |
} | |
} | |
if (type == -1) | |
while (matchg()) { | |
if (match("[+]")) | |
type = -2; | |
else if (match("[-]")) | |
type = -3; | |
if (type != -1) | |
break; | |
sta.push_back(-1); | |
} | |
if (type != -1) { | |
match(" "); | |
foundblock(type); | |
continue; | |
} | |
printsta(); | |
printf("%s\n", s.substr(now).c_str()); | |
int x = matchl(); | |
if (x) | |
sta.push_back(x); | |
matchcb(codemode); | |
} | |
printf("<!--\n%s-->", text.c_str()); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment