From 69a9134f11ed36a7cbaea3c82d8af456c0d350c7 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Tue, 10 Mar 2026 05:04:34 +0900 Subject: [PATCH] better handling of relative path --- src/action/markdown.c | 21 +++---- src/action/markdown_dir.c | 129 ++++++++++++++++++++++++++++++++++---- src/action/site.c | 2 +- 3 files changed, 127 insertions(+), 25 deletions(-) diff --git a/src/action/markdown.c b/src/action/markdown.c index dc97580..58fb921 100644 --- a/src/action/markdown.c +++ b/src/action/markdown.c @@ -6,7 +6,6 @@ static int mode = 0; static char* title = NULL; static int in_title = 0; static int in_section = 0; -static int in_pre = 0; static char** mapping; static int mapping_len; @@ -90,12 +89,11 @@ static int enter_block(MD_BLOCKTYPE type, void* detail, void* user) { indent++; } else if(type == MD_BLOCK_CODE) { print_indent(); - fprintf(out, "
");
+		fprintf(out, "
\n");
 		indent++;
 		print_indent();
-		fprintf(out, "");
+		fprintf(out, "\n");
 		indent++;
-		in_pre = 1;
 	} else if(type == MD_BLOCK_TABLE) {
 		print_indent();
 		fprintf(out, "\n");
@@ -178,7 +176,6 @@ static int leave_block(MD_BLOCKTYPE type, void* detail, void* user) {
 		indent--;
 		print_indent();
 		fprintf(out, "\n");
-		in_pre = 0;
 	} else if(type == MD_BLOCK_TABLE) {
 		indent--;
 		print_indent();
@@ -216,9 +213,13 @@ static int enter_span(MD_SPANTYPE type, void* detail, void* user) {
 		fprintf(out, "\n");
 		indent++;
 	} else if(type == MD_SPAN_A) {
-		MD_SPAN_A_DETAIL* det  = detail;
-		char*		  href = encode(det->href.text, det->href.size);
+		MD_SPAN_A_DETAIL* det	  = detail;
+		char*		  href	  = encode(det->href.text, det->href.size);
+		char*		  href_wd = href;
 		int		  i;
+		char*		  str;
+
+		while((str = strstr(href_wd, "./")) == href_wd) href_wd = str + 2;
 
 		for(i = 0; i < mapping_len; i++) {
 			char* key   = u_strdup(mapping[i]);
@@ -229,7 +230,7 @@ static int enter_span(MD_SPANTYPE type, void* detail, void* user) {
 				value++;
 			}
 
-			if(value != NULL && strcmp(key, href) == 0) {
+			if(value != NULL && strcmp(key, href_wd) == 0) {
 				free(href);
 				href = encode(value, -1);
 			}
@@ -311,7 +312,7 @@ static int leave_span(MD_SPANTYPE type, void* detail, void* user) {
 }
 
 static int text(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* user) {
-	if(in_title && (type == MD_TEXT_NORMAL || type == MD_TEXT_ENTITY)) {
+	if(in_title && (type == MD_TEXT_NORMAL || type == MD_TEXT_ENTITY || type == MD_TEXT_CODE)) {
 		if(title == NULL) {
 			title = malloc(size + 1);
 
@@ -411,7 +412,6 @@ int action_markdown(int argc, char** argv) {
 
 	in_title   = 0;
 	in_section = 0;
-	in_pre	   = 0;
 	mode	   = 0;
 	if(md_parse(buffer, size, &parser, NULL)) {
 		free(buffer);
@@ -432,7 +432,6 @@ int action_markdown(int argc, char** argv) {
 
 	in_title   = 0;
 	in_section = 0;
-	in_pre	   = 0;
 	mode	   = 1;
 	if(md_parse(buffer, size, &parser, NULL)) {
 		free(buffer);
diff --git a/src/action/markdown_dir.c b/src/action/markdown_dir.c
index 486b179..38444ae 100644
--- a/src/action/markdown_dir.c
+++ b/src/action/markdown_dir.c
@@ -1,8 +1,70 @@
 #include 
 
-static int scan(const char* inp, const char* path) {
+static const char* inp;
+static const char* oup;
+
+typedef struct stringkv {
+	char* key;
+	char* value;
+} stringkv_t;
+
+static stringkv_t* paths = NULL;
+
+#define IS_INDEX(x) (strcmp((x), "README.md") == 0)
+
+static void populate(const char* path) {
+	char*	in = u_strvacat(inp, "/", path, NULL);
+	IO_DIR* dir;
+
+	if((dir = io_opendir(in)) != NULL) {
+		struct io_dirent* d;
+
+		while((d = io_readdir(dir)) != NULL) {
+			char*	       p;
+			struct io_stat s;
+
+			if(strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) continue;
+
+			p = u_strvacat(in, d->d_name, NULL);
+			if(io_stat(p, &s) == 0) {
+				char* str;
+				int   is_md = 0;
+
+				str = strrchr(d->d_name, '.');
+				if(str != NULL && strcmp(str, ".md") == 0) is_md = 1;
+
+				if(IO_S_ISDIR(s.st_mode)) {
+					char* p2 = u_strvacat(path, d->d_name, "/", NULL);
+					populate(p2);
+					free(p2);
+				} else if(is_md) {
+					char* p2 = u_strvacat(path, d->d_name, NULL);
+					char* pathv;
+
+					if(IS_INDEX(d->d_name)) {
+						pathv = u_strdup(path);
+					} else {
+						char* n = u_strdup(d->d_name);
+						char* str;
+						if((str = strchr(n, '.')) != NULL) str[0] = 0;
+
+						pathv = u_strvacat(path, n, "/", NULL);
+
+						free(n);
+					}
+					shput(paths, p2, pathv);
+
+					free(p2);
+				}
+			}
+			free(p);
+		}
+	}
+}
+
+static int scan(const char* top, const char* path) {
 	char*	in  = u_strvacat(inp, "/", path, NULL);
-	char*	out = u_strvacat("site/content/", path, NULL);
+	char*	out = u_strvacat(oup, path, NULL);
 	IO_DIR* dir;
 
 	io_mkdir(out, 0755);
@@ -24,12 +86,14 @@ static int scan(const char* inp, const char* path) {
 				if(str != NULL && strcmp(str, ".md") == 0) is_md = 1;
 
 				if(IO_S_ISDIR(s.st_mode)) {
-					char* p2 = u_strvacat(d->d_name, "/", NULL);
+					char* p2 = u_strvacat(path, d->d_name, "/", NULL);
 					char* o	 = u_strvacat(out, d->d_name, NULL);
+					char* t	 = u_strvacat(top, "../", NULL);
 
 					io_mkdir(o, 0755);
 					free(o);
-					if(!scan(inp, p2)) {
+					if(!scan(t, p2)) {
+						free(t);
 						free(p2);
 						free(p);
 						io_closedir(dir);
@@ -38,33 +102,57 @@ static int scan(const char* inp, const char* path) {
 
 						return 0;
 					}
+					free(t);
 					free(p2);
 				} else if(is_md) {
 					char** argv = NULL;
 					char*  o    = NULL;
+					int    i;
 
 					printf("%s:\n", p);
 
 					arrput(argv, p);
-					if(strcmp(d->d_name, "README.md") == 0) {
+					if(IS_INDEX(d->d_name)) {
 						o = u_strvacat(out, "index.xml", NULL);
 					} else {
 						char* n = u_strdup(d->d_name);
 						char* str;
-						char* d;
+						char* pathd;
 						if((str = strchr(n, '.')) != NULL) str[0] = 0;
 
-						d = u_strvacat(out, n, NULL);
-						o = u_strvacat(d, "/index.xml", NULL);
-						io_mkdir(d, 0755);
-						free(d);
+						pathd = u_strvacat(out, n, NULL);
+						o     = u_strvacat(pathd, "/index.xml", NULL);
+						io_mkdir(pathd, 0755);
+						free(pathd);
 
 						free(n);
 					}
 
-					if(o != NULL) arrput(argv, o);
+					arrput(argv, o);
+
+					for(i = 0; i < shlen(paths); i++) {
+						char* t;
+						char* v;
+
+						if(IS_INDEX(d->d_name)) {
+							t = u_strdup(top);
+						} else {
+							t = u_strvacat(top, "../", NULL);
+						}
+
+						if(strstr(paths[i].value, path) == paths[i].value) {
+							v = u_strvacat(paths[i].key + strlen(path), "=", paths[i].value + strlen(path), NULL);
+							arrput(argv, v);
+						}
+
+						v = u_strvacat(top, paths[i].key, "=", t, paths[i].value, NULL);
+						arrput(argv, v);
+
+						free(t);
+					}
 
 					if(action_markdown(arrlen(argv), argv)) {
+						for(i = 2; i < arrlen(argv); i++) free(argv[i]);
 						free(o);
 						arrfree(argv);
 						free(p);
@@ -74,6 +162,7 @@ static int scan(const char* inp, const char* path) {
 						return 0;
 					}
 					free(o);
+					for(i = 2; i < arrlen(argv); i++) free(argv[i]);
 					arrfree(argv);
 				}
 			}
@@ -90,15 +179,29 @@ static int scan(const char* inp, const char* path) {
 }
 
 int action_markdown_dir(int argc, char** argv) {
+	int i;
 	if(argc != 1) {
-		fprintf(stderr, "Usage: markdown-dir input\n");
+		fprintf(stderr, "Usage: markdown-dir input [output]\n");
 
 		return 1;
 	}
 
-	if(!scan(argv[0], "")) {
+	inp = argv[0];
+	oup = (argc >= 2) ? argv[1] : "site/content/";
+
+	paths = NULL;
+	sh_new_strdup(paths);
+
+	populate("");
+
+	if(!scan("", "")) {
+		for(i = 0; i < shlen(paths); i++) free(paths[i].value);
+		shfree(paths);
 		return 1;
 	}
 
+	for(i = 0; i < shlen(paths); i++) free(paths[i].value);
+	shfree(paths);
+
 	return 0;
 }
diff --git a/src/action/site.c b/src/action/site.c
index bc3d186..3d1c2da 100644
--- a/src/action/site.c
+++ b/src/action/site.c
@@ -23,7 +23,7 @@ static int scan(const char* top, int mode, const char* path) {
 			p = u_strvacat(in, d->d_name, NULL);
 			if(io_stat(p, &s) == 0) {
 				if(IO_S_ISDIR(s.st_mode)) {
-					char* p2 = u_strvacat(d->d_name, "/", NULL);
+					char* p2 = u_strvacat(path, d->d_name, "/", NULL);
 					char* t	 = u_strvacat(top, "../", NULL);
 					char* o	 = u_strvacat(out, d->d_name, NULL);