clone url: git://git.m455.casa/mth
main.c
1 | #include <stdlib.h> |
2 | #include <stdio.h> |
3 | #include <string.h> |
4 | #include <ctype.h> |
5 |
|
6 | enum states { RESET, P, PRE, CODE }; |
7 |
|
8 | static void print_sanitized_character(char c) { |
9 | switch(c) { |
10 | case '&': |
11 | printf("&"); |
12 | break; |
13 | case '<': |
14 | printf("<"); |
15 | break; |
16 | case '>': |
17 | printf(">"); |
18 | break; |
19 | case '"': |
20 | printf("""); |
21 | break; |
22 | case '\'': |
23 | printf("'"); |
24 | break; |
25 | default: |
26 | printf("%c", c); |
27 | } |
28 | } |
29 |
|
30 | static void print_converted_characters(char *line, int state) { |
31 | int i; |
32 |
|
33 | i = 0; |
34 | while(i < (int)strlen(line)) { |
35 | switch(state) { |
36 | case RESET: |
37 | if (line[i] == '`') { |
38 | printf("<code>"); |
39 | state = CODE; |
40 | } |
41 | else { |
42 | print_sanitized_character(line[i]); |
43 | } |
44 | break; |
45 | case CODE: |
46 | if (line[i] == '`') { |
47 | printf("</code>"); |
48 | state = RESET; |
49 | } |
50 | else { |
51 | print_sanitized_character(line[i]); |
52 | } |
53 | break; |
54 | default: |
55 | print_sanitized_character(line[i]); |
56 | } |
57 | i++; |
58 | } |
59 | } |
60 |
|
61 | static void print_converted_lines(FILE *fp) { |
62 | int state; |
63 | /* a size big enough for wrapping english or chinese text at 80 characters |
64 | * wide */ |
65 | char line_buf[128]; |
66 | char *found_str; |
67 |
|
68 | state = RESET; |
69 | while(fgets(line_buf, (int)sizeof(line_buf), fp) != NULL) { |
70 | switch(state) { |
71 | case RESET: |
72 | if ((found_str = strstr(line_buf, "title: ")) != NULL) { |
73 | char *h1_text = found_str + (strlen("title: ")); |
74 | h1_text[strlen(h1_text) - 1] = '\0'; |
75 | printf("\n<h1>"); |
76 | print_converted_characters(h1_text, RESET); |
77 | printf("</h1>"); |
78 | } |
79 | else if ((found_str = strstr(line_buf, "# ")) != NULL) { |
80 | char *h2_text = found_str + (strlen("# ")); |
81 | h2_text[strlen(h2_text) - 1] = '\0'; |
82 | printf("\n<h2>"); |
83 | print_converted_characters(h2_text, RESET); |
84 | printf("</h2>"); |
85 | } |
86 | else if (strstr(line_buf, "```") != NULL) { |
87 | (void) puts("\n<pre>"); |
88 | state = PRE; |
89 | } |
90 | /* the check for the return value of 0 actually checks if |
91 | * something is not a space */ |
92 | else if (isspace(line_buf[0]) == 0) { |
93 | (void) puts("\n<p>"); |
94 | print_converted_characters(line_buf, P); |
95 | state = P; |
96 | } |
97 | break; |
98 |
|
99 | case PRE: |
100 | if (strstr(line_buf, "```") != NULL) { |
101 | (void) puts("</pre>"); |
102 | state = RESET; |
103 | } |
104 | else { |
105 | print_converted_characters(line_buf, PRE); |
106 | } |
107 | break; |
108 |
|
109 | case P: |
110 | /* the check for the return value of 0 actually checks if |
111 | * something is not a space */ |
112 | if (isspace(line_buf[0]) == 0) { |
113 | print_converted_characters(line_buf, P); |
114 | } |
115 | else { |
116 | (void) puts("</p>"); |
117 | state = RESET; |
118 | } |
119 | } |
120 | } |
121 | /* handle paragraphs that end on the last line of the file */ |
122 | if (feof(fp) != 0) { |
123 | if (state == P) { |
124 | (void) puts("</p>"); |
125 | } |
126 | } |
127 | } |
128 |
|
129 | int main(int argc, char *argv[]) { |
130 | if (argc < 2) { |
131 | (void) puts("no input file"); |
132 | } |
133 | else { |
134 | FILE *fp; |
135 | int r_fclose; |
136 |
|
137 | fp = fopen(argv[1], "r"); |
138 | if (fp == NULL) { |
139 | perror("fopen()"); |
140 | return 1; |
141 | } |
142 |
|
143 | (void) puts( |
144 | "<!DOCTYPE html>\n" |
145 | "<html lang=\"en\">\n" |
146 | "<head>\n" |
147 | "<meta charset=\"utf-8\">\n" |
148 | "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=yes\">\n" |
149 | "<link rel=\"icon\" type=\"image/x-icon\" href=\"/assets/favicon.ico\">\n" |
150 | "<link rel=\"alternate\" type=\"application/rss+xml\" href=\"https://m455.casa/feed.rss\">\n" |
151 | "<title>m455's interspace on the webternet</title>\n" |
152 | "<style>body{margin:0 auto;line-height:1.6;max-width:600px;font-family:system-ui,sans-serif;}code,pre{background-color:#eee;}</style>\n" |
153 | "</head>\n" |
154 | "<body>\n" |
155 | "<main>" |
156 | ); |
157 |
|
158 | print_converted_lines(fp); |
159 |
|
160 | (void) puts( |
161 | "</main>\n" |
162 | "</body>\n" |
163 | "</html>" |
164 | ); |
165 |
|
166 | r_fclose = fclose(fp); |
167 | if (r_fclose == EOF) { |
168 | perror("fclose()"); |
169 | return 1; |
170 | } |
171 | } |
172 | return 0; |
173 | } |