react-native-codepad-lang-markdown 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CodepadLangMarkdown.podspec +28 -0
  2. package/README.md +50 -2
  3. package/android/CMakeLists.txt +19 -0
  4. package/android/build.gradle +61 -0
  5. package/android/consumer-rules.pro +2 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/assets/codepad-languages/markdown +1 -0
  8. package/android/src/main/assets/codepad-languages/markdown_inline +1 -0
  9. package/android/src/main/cpp/lang.c +17 -0
  10. package/android/src/main/java/me/sectiontn/codepad/lang/markdown/CodepadLangMarkdownPackage.kt +13 -0
  11. package/android/src/main/java/me/sectiontn/codepad/lang/markdown/MarkdownLanguage.kt +169 -0
  12. package/android/src/main/java/me/sectiontn/codepad/lang/markdown_inline/MarkdownInlineLanguage.kt +156 -0
  13. package/grammar/LICENSE +21 -0
  14. package/grammar/tree-sitter-markdown/src/parser.c +59787 -0
  15. package/grammar/tree-sitter-markdown/src/scanner.c +1602 -0
  16. package/grammar/tree-sitter-markdown/src/tree_sitter/alloc.h +54 -0
  17. package/grammar/tree-sitter-markdown/src/tree_sitter/array.h +330 -0
  18. package/grammar/tree-sitter-markdown/src/tree_sitter/parser.h +286 -0
  19. package/grammar/tree-sitter-markdown-inline/src/parser.c +75709 -0
  20. package/grammar/tree-sitter-markdown-inline/src/scanner.c +397 -0
  21. package/grammar/tree-sitter-markdown-inline/src/tree_sitter/alloc.h +54 -0
  22. package/grammar/tree-sitter-markdown-inline/src/tree_sitter/array.h +330 -0
  23. package/grammar/tree-sitter-markdown-inline/src/tree_sitter/parser.h +286 -0
  24. package/ios/CPLangMarkdown.h +11 -0
  25. package/ios/CPLangMarkdown.swift +162 -0
  26. package/ios/CPLangMarkdownInline.h +11 -0
  27. package/ios/CPLangMarkdownInline.swift +149 -0
  28. package/package.json +40 -4
  29. package/queries/markdown/highlights.scm +123 -0
  30. package/queries/markdown/indents.scm +1 -0
  31. package/queries/markdown/injections.scm +25 -0
  32. package/queries/markdown_inline/highlights.scm +128 -0
  33. package/queries/markdown_inline/injections.scm +7 -0
  34. package/src/index.ts +2 -0
@@ -0,0 +1,397 @@
1
+ #include "tree_sitter/parser.h"
2
+
3
+ #ifdef _MSC_VER
4
+ #define UNUSED __pragma(warning(suppress : 4101))
5
+ #else
6
+ #define UNUSED __attribute__((unused))
7
+ #endif
8
+
9
+ // For explanation of the tokens see grammar.js
10
+ typedef enum {
11
+ ERROR,
12
+ TRIGGER_ERROR,
13
+ CODE_SPAN_START,
14
+ CODE_SPAN_CLOSE,
15
+ EMPHASIS_OPEN_STAR,
16
+ EMPHASIS_OPEN_UNDERSCORE,
17
+ EMPHASIS_CLOSE_STAR,
18
+ EMPHASIS_CLOSE_UNDERSCORE,
19
+ LAST_TOKEN_WHITESPACE,
20
+ LAST_TOKEN_PUNCTUATION,
21
+ STRIKETHROUGH_OPEN,
22
+ STRIKETHROUGH_CLOSE,
23
+ LATEX_SPAN_START,
24
+ LATEX_SPAN_CLOSE,
25
+ UNCLOSED_SPAN
26
+ } TokenType;
27
+
28
+ // Determines if a character is punctuation as defined by the markdown spec.
29
+ static bool is_punctuation(int32_t chr) {
30
+ return (chr >= '!' && chr <= '/') || (chr >= ':' && chr <= '@') ||
31
+ (chr >= '[' && chr <= '`') || (chr >= '{' && chr <= '~');
32
+ }
33
+
34
+ // State bitflags used with `Scanner.state`
35
+
36
+ // TODO
37
+ static UNUSED const uint8_t STATE_EMPHASIS_DELIMITER_MOD_3 = 0x3;
38
+ // Current delimiter run is opening
39
+ static const uint8_t STATE_EMPHASIS_DELIMITER_IS_OPEN = 0x1 << 2;
40
+
41
+ // Convenience function to emit the error token. This is done to stop invalid
42
+ // parse branches. Specifically:
43
+ // 1. When encountering a newline after a line break that ended a paragraph, and
44
+ // no new block
45
+ // has been opened.
46
+ // 2. When encountering a new block after a soft line break.
47
+ // 3. When a `$._trigger_error` token is valid, which is used to stop parse
48
+ // branches through
49
+ // normal tree-sitter grammar rules.
50
+ //
51
+ // See also the `$._soft_line_break` and `$._paragraph_end_newline` tokens in
52
+ // grammar.js
53
+ static bool error(TSLexer *lexer) {
54
+ lexer->result_symbol = ERROR;
55
+ return true;
56
+ }
57
+
58
+ typedef struct {
59
+ // Parser state flags
60
+ uint8_t state;
61
+ uint8_t code_span_delimiter_length;
62
+ uint8_t latex_span_delimiter_length;
63
+ // The number of characters remaining in the currrent emphasis delimiter
64
+ // run.
65
+ uint8_t num_emphasis_delimiters_left;
66
+
67
+ } Scanner;
68
+
69
+ // Write the whole state of a Scanner to a byte buffer
70
+ static unsigned serialize(Scanner *s, char *buffer) {
71
+ unsigned size = 0;
72
+ buffer[size++] = (char)s->state;
73
+ buffer[size++] = (char)s->code_span_delimiter_length;
74
+ buffer[size++] = (char)s->latex_span_delimiter_length;
75
+ buffer[size++] = (char)s->num_emphasis_delimiters_left;
76
+ return size;
77
+ }
78
+
79
+ // Read the whole state of a Scanner from a byte buffer
80
+ // `serizalize` and `deserialize` should be fully symmetric.
81
+ static void deserialize(Scanner *s, const char *buffer, unsigned length) {
82
+ s->state = 0;
83
+ s->code_span_delimiter_length = 0;
84
+ s->latex_span_delimiter_length = 0;
85
+ s->num_emphasis_delimiters_left = 0;
86
+ if (length > 0) {
87
+ size_t size = 0;
88
+ s->state = (uint8_t)buffer[size++];
89
+ s->code_span_delimiter_length = (uint8_t)buffer[size++];
90
+ s->latex_span_delimiter_length = (uint8_t)buffer[size++];
91
+ s->num_emphasis_delimiters_left = (uint8_t)buffer[size++];
92
+ }
93
+ }
94
+
95
+ static bool parse_leaf_delimiter(TSLexer *lexer, uint8_t *delimiter_length,
96
+ const bool *valid_symbols,
97
+ const char delimiter,
98
+ const TokenType open_token,
99
+ const TokenType close_token) {
100
+ uint8_t level = 0;
101
+ while (lexer->lookahead == delimiter) {
102
+ lexer->advance(lexer, false);
103
+ level++;
104
+ }
105
+ lexer->mark_end(lexer);
106
+ if (level == *delimiter_length && valid_symbols[close_token]) {
107
+ *delimiter_length = 0;
108
+ lexer->result_symbol = close_token;
109
+ return true;
110
+ }
111
+ if (valid_symbols[open_token]) {
112
+ // Parse ahead to check if there is a closing delimiter
113
+ size_t close_level = 0;
114
+ while (!lexer->eof(lexer)) {
115
+ if (lexer->lookahead == delimiter) {
116
+ close_level++;
117
+ } else {
118
+ if (close_level == level) {
119
+ // Found a matching delimiter
120
+ break;
121
+ }
122
+ close_level = 0;
123
+ }
124
+ lexer->advance(lexer, false);
125
+ }
126
+ if (close_level == level) {
127
+ *delimiter_length = level;
128
+ lexer->result_symbol = open_token;
129
+ return true;
130
+ }
131
+ if (valid_symbols[UNCLOSED_SPAN]) {
132
+ lexer->result_symbol = UNCLOSED_SPAN;
133
+ return true;
134
+ }
135
+ }
136
+ return false;
137
+ }
138
+
139
+ static bool parse_backtick(Scanner *s, TSLexer *lexer,
140
+ const bool *valid_symbols) {
141
+ return parse_leaf_delimiter(lexer, &s->code_span_delimiter_length,
142
+ valid_symbols, '`', CODE_SPAN_START,
143
+ CODE_SPAN_CLOSE);
144
+ }
145
+
146
+ static bool parse_dollar(Scanner *s, TSLexer *lexer,
147
+ const bool *valid_symbols) {
148
+ return parse_leaf_delimiter(lexer, &s->latex_span_delimiter_length,
149
+ valid_symbols, '$', LATEX_SPAN_START,
150
+ LATEX_SPAN_CLOSE);
151
+ }
152
+
153
+ static bool parse_star(Scanner *s, TSLexer *lexer, const bool *valid_symbols) {
154
+ lexer->advance(lexer, false);
155
+ // If `num_emphasis_delimiters_left` is not zero then we already decided
156
+ // that this should be part of an emphasis delimiter run, so interpret it as
157
+ // such.
158
+ if (s->num_emphasis_delimiters_left > 0) {
159
+ // The `STATE_EMPHASIS_DELIMITER_IS_OPEN` state flag tells us wether it
160
+ // should be open or close.
161
+ if ((s->state & STATE_EMPHASIS_DELIMITER_IS_OPEN) &&
162
+ valid_symbols[EMPHASIS_OPEN_STAR]) {
163
+ s->state &= (~STATE_EMPHASIS_DELIMITER_IS_OPEN);
164
+ lexer->result_symbol = EMPHASIS_OPEN_STAR;
165
+ s->num_emphasis_delimiters_left--;
166
+ return true;
167
+ }
168
+ if (valid_symbols[EMPHASIS_CLOSE_STAR]) {
169
+ lexer->result_symbol = EMPHASIS_CLOSE_STAR;
170
+ s->num_emphasis_delimiters_left--;
171
+ return true;
172
+ }
173
+ }
174
+ lexer->mark_end(lexer);
175
+ // Otherwise count the number of stars
176
+ uint8_t star_count = 1;
177
+ while (lexer->lookahead == '*') {
178
+ star_count++;
179
+ lexer->advance(lexer, false);
180
+ }
181
+ bool line_end = lexer->lookahead == '\n' || lexer->lookahead == '\r' ||
182
+ lexer->eof(lexer);
183
+ if (valid_symbols[EMPHASIS_OPEN_STAR] ||
184
+ valid_symbols[EMPHASIS_CLOSE_STAR]) {
185
+ // The desicion made for the first star also counts for all the
186
+ // following stars in the delimiter run. Rembemer how many there are.
187
+ s->num_emphasis_delimiters_left = star_count - 1;
188
+ // Look ahead to the next symbol (after the last star) to find out if it
189
+ // is whitespace punctuation or other.
190
+ bool next_symbol_whitespace =
191
+ line_end || lexer->lookahead == ' ' || lexer->lookahead == '\t';
192
+ bool next_symbol_punctuation = is_punctuation(lexer->lookahead);
193
+ // Information about the last token is in valid_symbols. See grammar.js
194
+ // for these tokens for how this is done.
195
+ if (valid_symbols[EMPHASIS_CLOSE_STAR] &&
196
+ !valid_symbols[LAST_TOKEN_WHITESPACE] &&
197
+ (!valid_symbols[LAST_TOKEN_PUNCTUATION] ||
198
+ next_symbol_punctuation || next_symbol_whitespace)) {
199
+ // Closing delimiters take precedence
200
+ s->state &= ~STATE_EMPHASIS_DELIMITER_IS_OPEN;
201
+ lexer->result_symbol = EMPHASIS_CLOSE_STAR;
202
+ return true;
203
+ }
204
+ if (!next_symbol_whitespace && (!next_symbol_punctuation ||
205
+ valid_symbols[LAST_TOKEN_PUNCTUATION] ||
206
+ valid_symbols[LAST_TOKEN_WHITESPACE])) {
207
+ s->state |= STATE_EMPHASIS_DELIMITER_IS_OPEN;
208
+ lexer->result_symbol = EMPHASIS_OPEN_STAR;
209
+ return true;
210
+ }
211
+ }
212
+ return false;
213
+ }
214
+
215
+ static bool parse_tilde(Scanner *s, TSLexer *lexer, const bool *valid_symbols) {
216
+ lexer->advance(lexer, false);
217
+ // If `num_emphasis_delimiters_left` is not zero then we already decided
218
+ // that this should be part of an emphasis delimiter run, so interpret it as
219
+ // such.
220
+ if (s->num_emphasis_delimiters_left > 0) {
221
+ // The `STATE_EMPHASIS_DELIMITER_IS_OPEN` state flag tells us wether it
222
+ // should be open or close.
223
+ if ((s->state & STATE_EMPHASIS_DELIMITER_IS_OPEN) &&
224
+ valid_symbols[STRIKETHROUGH_OPEN]) {
225
+ s->state &= (~STATE_EMPHASIS_DELIMITER_IS_OPEN);
226
+ lexer->result_symbol = STRIKETHROUGH_OPEN;
227
+ s->num_emphasis_delimiters_left--;
228
+ return true;
229
+ }
230
+ if (valid_symbols[STRIKETHROUGH_CLOSE]) {
231
+ lexer->result_symbol = STRIKETHROUGH_CLOSE;
232
+ s->num_emphasis_delimiters_left--;
233
+ return true;
234
+ }
235
+ }
236
+ lexer->mark_end(lexer);
237
+ // Otherwise count the number of tildes
238
+ uint8_t star_count = 1;
239
+ while (lexer->lookahead == '~') {
240
+ star_count++;
241
+ lexer->advance(lexer, false);
242
+ }
243
+ bool line_end = lexer->lookahead == '\n' || lexer->lookahead == '\r' ||
244
+ lexer->eof(lexer);
245
+ if (valid_symbols[STRIKETHROUGH_OPEN] ||
246
+ valid_symbols[STRIKETHROUGH_CLOSE]) {
247
+ // The desicion made for the first star also counts for all the
248
+ // following stars in the delimiter run. Rembemer how many there are.
249
+ s->num_emphasis_delimiters_left = star_count - 1;
250
+ // Look ahead to the next symbol (after the last star) to find out if it
251
+ // is whitespace punctuation or other.
252
+ bool next_symbol_whitespace =
253
+ line_end || lexer->lookahead == ' ' || lexer->lookahead == '\t';
254
+ bool next_symbol_punctuation = is_punctuation(lexer->lookahead);
255
+ // Information about the last token is in valid_symbols. See grammar.js
256
+ // for these tokens for how this is done.
257
+ if (valid_symbols[STRIKETHROUGH_CLOSE] &&
258
+ !valid_symbols[LAST_TOKEN_WHITESPACE] &&
259
+ (!valid_symbols[LAST_TOKEN_PUNCTUATION] ||
260
+ next_symbol_punctuation || next_symbol_whitespace)) {
261
+ // Closing delimiters take precedence
262
+ s->state &= ~STATE_EMPHASIS_DELIMITER_IS_OPEN;
263
+ lexer->result_symbol = STRIKETHROUGH_CLOSE;
264
+ return true;
265
+ }
266
+ if (!next_symbol_whitespace && (!next_symbol_punctuation ||
267
+ valid_symbols[LAST_TOKEN_PUNCTUATION] ||
268
+ valid_symbols[LAST_TOKEN_WHITESPACE])) {
269
+ s->state |= STATE_EMPHASIS_DELIMITER_IS_OPEN;
270
+ lexer->result_symbol = STRIKETHROUGH_OPEN;
271
+ return true;
272
+ }
273
+ }
274
+ return false;
275
+ }
276
+
277
+ static bool parse_underscore(Scanner *s, TSLexer *lexer,
278
+ const bool *valid_symbols) {
279
+ lexer->advance(lexer, false);
280
+ // If `num_emphasis_delimiters_left` is not zero then we already decided
281
+ // that this should be part of an emphasis delimiter run, so interpret it as
282
+ // such.
283
+ if (s->num_emphasis_delimiters_left > 0) {
284
+ // The `STATE_EMPHASIS_DELIMITER_IS_OPEN` state flag tells us wether it
285
+ // should be open or close.
286
+ if ((s->state & STATE_EMPHASIS_DELIMITER_IS_OPEN) &&
287
+ valid_symbols[EMPHASIS_OPEN_UNDERSCORE]) {
288
+ s->state &= (~STATE_EMPHASIS_DELIMITER_IS_OPEN);
289
+ lexer->result_symbol = EMPHASIS_OPEN_UNDERSCORE;
290
+ s->num_emphasis_delimiters_left--;
291
+ return true;
292
+ }
293
+ if (valid_symbols[EMPHASIS_CLOSE_UNDERSCORE]) {
294
+ lexer->result_symbol = EMPHASIS_CLOSE_UNDERSCORE;
295
+ s->num_emphasis_delimiters_left--;
296
+ return true;
297
+ }
298
+ }
299
+ lexer->mark_end(lexer);
300
+ // Otherwise count the number of stars
301
+ uint8_t underscore_count = 1;
302
+ while (lexer->lookahead == '_') {
303
+ underscore_count++;
304
+ lexer->advance(lexer, false);
305
+ }
306
+ bool line_end = lexer->lookahead == '\n' || lexer->lookahead == '\r' ||
307
+ lexer->eof(lexer);
308
+ if (valid_symbols[EMPHASIS_OPEN_UNDERSCORE] ||
309
+ valid_symbols[EMPHASIS_CLOSE_UNDERSCORE]) {
310
+ // The desicion made for the first underscore also counts for all the
311
+ // following underscores in the delimiter run. Rembemer how many there are.
312
+ s->num_emphasis_delimiters_left = underscore_count - 1;
313
+ // Look ahead to the next symbol (after the last underscore) to find out if it
314
+ // is whitespace punctuation or other.
315
+ bool next_symbol_whitespace =
316
+ line_end || lexer->lookahead == ' ' || lexer->lookahead == '\t';
317
+ bool next_symbol_punctuation = is_punctuation(lexer->lookahead);
318
+ // Information about the last token is in valid_symbols. See grammar.js
319
+ // for these tokens for how this is done.
320
+ if (valid_symbols[EMPHASIS_CLOSE_UNDERSCORE] &&
321
+ !valid_symbols[LAST_TOKEN_WHITESPACE] &&
322
+ (!valid_symbols[LAST_TOKEN_PUNCTUATION] ||
323
+ next_symbol_punctuation || next_symbol_whitespace)) {
324
+ // Closing delimiters take precedence
325
+ s->state &= ~STATE_EMPHASIS_DELIMITER_IS_OPEN;
326
+ lexer->result_symbol = EMPHASIS_CLOSE_UNDERSCORE;
327
+ return true;
328
+ }
329
+ if (!next_symbol_whitespace && (!next_symbol_punctuation ||
330
+ valid_symbols[LAST_TOKEN_PUNCTUATION] ||
331
+ valid_symbols[LAST_TOKEN_WHITESPACE])) {
332
+ s->state |= STATE_EMPHASIS_DELIMITER_IS_OPEN;
333
+ lexer->result_symbol = EMPHASIS_OPEN_UNDERSCORE;
334
+ return true;
335
+ }
336
+ }
337
+ return false;
338
+ }
339
+
340
+ static bool scan(Scanner *s, TSLexer *lexer, const bool *valid_symbols) {
341
+ // A normal tree-sitter rule decided that the current branch is invalid and
342
+ // now "requests" an error to stop the branch
343
+ if (valid_symbols[TRIGGER_ERROR]) {
344
+ return error(lexer);
345
+ }
346
+
347
+ // Decide which tokens to consider based on the first non-whitespace
348
+ // character
349
+ switch (lexer->lookahead) {
350
+ case '`':
351
+ // A backtick could mark the beginning or ending of a code span or a
352
+ // fenced code block.
353
+ return parse_backtick(s, lexer, valid_symbols);
354
+ case '$':
355
+ return parse_dollar(s, lexer, valid_symbols);
356
+ case '*':
357
+ // A star could either mark the beginning or ending of emphasis, a
358
+ // list item or thematic break. This code is similar to the code for
359
+ // '_' and '+'.
360
+ return parse_star(s, lexer, valid_symbols);
361
+ case '_':
362
+ return parse_underscore(s, lexer, valid_symbols);
363
+ case '~':
364
+ return parse_tilde(s, lexer, valid_symbols);
365
+ }
366
+ return false;
367
+ }
368
+
369
+ void *tree_sitter_markdown_inline_external_scanner_create() {
370
+ Scanner *s = (Scanner *)malloc(sizeof(Scanner));
371
+ deserialize(s, NULL, 0);
372
+ return s;
373
+ }
374
+
375
+ bool tree_sitter_markdown_inline_external_scanner_scan(
376
+ void *payload, TSLexer *lexer, const bool *valid_symbols) {
377
+ Scanner *scanner = (Scanner *)payload;
378
+ return scan(scanner, lexer, valid_symbols);
379
+ }
380
+
381
+ unsigned tree_sitter_markdown_inline_external_scanner_serialize(void *payload,
382
+ char *buffer) {
383
+ Scanner *scanner = (Scanner *)payload;
384
+ return serialize(scanner, buffer);
385
+ }
386
+
387
+ void tree_sitter_markdown_inline_external_scanner_deserialize(void *payload,
388
+ const char *buffer,
389
+ unsigned length) {
390
+ Scanner *scanner = (Scanner *)payload;
391
+ deserialize(scanner, buffer, length);
392
+ }
393
+
394
+ void tree_sitter_markdown_inline_external_scanner_destroy(void *payload) {
395
+ Scanner *scanner = (Scanner *)payload;
396
+ free(scanner);
397
+ }
@@ -0,0 +1,54 @@
1
+ #ifndef TREE_SITTER_ALLOC_H_
2
+ #define TREE_SITTER_ALLOC_H_
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ #include <stdbool.h>
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+
12
+ // Allow clients to override allocation functions
13
+ #ifdef TREE_SITTER_REUSE_ALLOCATOR
14
+
15
+ extern void *(*ts_current_malloc)(size_t size);
16
+ extern void *(*ts_current_calloc)(size_t count, size_t size);
17
+ extern void *(*ts_current_realloc)(void *ptr, size_t size);
18
+ extern void (*ts_current_free)(void *ptr);
19
+
20
+ #ifndef ts_malloc
21
+ #define ts_malloc ts_current_malloc
22
+ #endif
23
+ #ifndef ts_calloc
24
+ #define ts_calloc ts_current_calloc
25
+ #endif
26
+ #ifndef ts_realloc
27
+ #define ts_realloc ts_current_realloc
28
+ #endif
29
+ #ifndef ts_free
30
+ #define ts_free ts_current_free
31
+ #endif
32
+
33
+ #else
34
+
35
+ #ifndef ts_malloc
36
+ #define ts_malloc malloc
37
+ #endif
38
+ #ifndef ts_calloc
39
+ #define ts_calloc calloc
40
+ #endif
41
+ #ifndef ts_realloc
42
+ #define ts_realloc realloc
43
+ #endif
44
+ #ifndef ts_free
45
+ #define ts_free free
46
+ #endif
47
+
48
+ #endif
49
+
50
+ #ifdef __cplusplus
51
+ }
52
+ #endif
53
+
54
+ #endif // TREE_SITTER_ALLOC_H_