Fossil

Check-in [3363ab42c0]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:More refinement of the token selection for #hashtag and @name references.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | markdown-tagrefs
Files: files | file ages | folders
SHA3-256: 3363ab42c0bb1ac83c8e66df5b4e344cb67c62b81f73df3629651170dd2d7589
User & Date: stephan 2021-09-21 17:34:09.774
Context
2021-09-21
17:36
Removed a bogus unreached return statement. check-in: 4b98f9e791 user: stephan tags: markdown-tagrefs
17:34
More refinement of the token selection for #hashtag and @name references. check-in: 3363ab42c0 user: stephan tags: markdown-tagrefs
16:42
Fixed a paren nesting bug that prevented multi-character hashtags from being processed. It would stop at the second character. check-in: e211f1ab42 user: wyoung tags: markdown-tagrefs
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/markdown.c.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
** using an external renderer.
*/

#include "config.h"
#include "markdown.h"

#include <assert.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define MKD_LI_END 8  /* internal list flag */

/********************
 * TYPE DEFINITIONS *







<







19
20
21
22
23
24
25

26
27
28
29
30
31
32
** using an external renderer.
*/

#include "config.h"
#include "markdown.h"

#include <assert.h>

#include <string.h>
#include <stdlib.h>

#define MKD_LI_END 8  /* internal list flag */

/********************
 * TYPE DEFINITIONS *
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  MKDA_EXPLICIT_EMAIL,  /* e-mail link with explicit mailto: */
  MKDA_IMPLICIT_EMAIL   /* e-mail link without mailto: */
};

/* mkd_tagspan -- type of tagged <span> */
enum mkd_tagspan {
  MKDT_ATREF,           /* @name references, as in /chat attention targeting */
  MKDT_HASH,            /* #hash tags, message IDs, etc. */
};

/* mkd_renderer -- functions for rendering parsed data */
struct mkd_renderer {
  /* document level callbacks */
  void (*prolog)(struct Blob *ob, void *opaque);
  void (*epilog)(struct Blob *ob, void *opaque);







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  MKDA_EXPLICIT_EMAIL,  /* e-mail link with explicit mailto: */
  MKDA_IMPLICIT_EMAIL   /* e-mail link without mailto: */
};

/* mkd_tagspan -- type of tagged <span> */
enum mkd_tagspan {
  MKDT_ATREF,           /* @name references, as in /chat attention targeting */
  MKDT_HASHTAG,         /* #hash tags, message IDs, etc. */
};

/* mkd_renderer -- functions for rendering parsed data */
struct mkd_renderer {
  /* document level callbacks */
  void (*prolog)(struct Blob *ob, void *opaque);
  void (*epilog)(struct Blob *ob, void *opaque);
889
890
891
892
893
894
895






896
897











898

899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916





917

918








919

920
921
922

923
924
925
926
927
928
929
  char *data,
  size_t offset,
  size_t size
){
  size_t end;
  struct Blob work = BLOB_INITIALIZER;







  if (size < 2 || !isalpha(data[1])) return 0;
  for (end = 2; (end < size) && isalnum(data[end]); ++end) /* */ ;











    

  blob_init(&work, data + 1, end - 1);
  rndr->make.tagspan(ob, &work, MKDT_ATREF, rndr->make.opaque);
  return end;
}


/* char_hashref_tag -- '#' followed by "word" characters to tag
 * post numbers, hashtags, etc. */
static size_t char_hashref_tag(
  struct Blob *ob,
  struct render *rndr,
  char *data,
  size_t offset,
  size_t size
){
  size_t end;
  struct Blob work = BLOB_INITIALIZER;






  if (size < 2 || !isalnum(data[1])) return 0;

  for (end = 2; (end < size) && (isalnum(data[end]) || data[end] == '.'); ++end) /* */ ;








    

  blob_init(&work, data + 1, end - 1);
  rndr->make.tagspan(ob, &work, MKDT_HASH, rndr->make.opaque);
  return end;

}


/* char_langle_tag -- '<' when tags or autolinks are allowed */
static size_t char_langle_tag(
  struct Blob *ob,
  struct render *rndr,







>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
|
>




<













>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
|
>

|

>







888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
  char *data,
  size_t offset,
  size_t size
){
  size_t end;
  struct Blob work = BLOB_INITIALIZER;

  if(offset>0 && !fossil_isspace(data[-1])){
    /* Only ever match if the *previous* character is
       whitespace or we're at the start of the input. */
    return 0;
  }
  /*fprintf(stderr,"@-REF: %.*s\n", (int)size, data);*/
  if (size < 2 || !fossil_isalpha(data[1])) return 0;
  for (end = 2; (end < size)
         && (fossil_isalnum(data[end])
             /* TODO: email addresses are legal fossil user names, but
                parsing those is beyond our current ambitions.
                Similarly, non-ASCII names are legal, but not
                currently handled here. */
             /*|| data[end] == '.' || data[end] == '_'
               || data[end] == '-'*/);
       ++end);
  if(end<size){
    if(!fossil_isspace(data[end])){
      return 0;
    }
  }
  blob_init(&work, data + 1, end - 1);
  rndr->make.tagspan(ob, &work, MKDT_ATREF, rndr->make.opaque);
  return end;
}


/* char_hashref_tag -- '#' followed by "word" characters to tag
 * post numbers, hashtags, etc. */
static size_t char_hashref_tag(
  struct Blob *ob,
  struct render *rndr,
  char *data,
  size_t offset,
  size_t size
){
  size_t end;
  struct Blob work = BLOB_INITIALIZER;

  if(offset>0 && !fossil_isspace(data[-1])){
    /* Only ever match if the *previous* character is
       whitespace or we're at the start of the input. */
    return 0;
  }
  if(size < 2 || !fossil_isalnum(data[1])) return 0;
  /*fprintf(stderr,"HASHREF: %.*s\n", (int)size, data);*/
  for (end = 2; (end < size) && fossil_isalnum(data[end]); ++end);
  /*TODO: in order to support detection of forum post-style
    references, we need to recognize #X.Y, but only when X and Y are
    both purely numeric and Y ends on a word/sentence
    boundary.*/
  if(end<size){
    /* Only match if we end at a dot or space or end of input */
    if(data[end]!='.' && !fossil_isspace(data[end])){
      return 0;
    }
  }
  blob_init(&work, data + 1, end - 1);
  rndr->make.tagspan(ob, &work, MKDT_HASHTAG, rndr->make.opaque);
  return end;
  return 0;
}


/* char_langle_tag -- '<' when tags or autolinks are allowed */
static size_t char_langle_tag(
  struct Blob *ob,
  struct render *rndr,
Changes to src/markdown_html.c.
545
546
547
548
549
550
551
552
553
554

555

556
557
558
559
560
561
562
563
564
565
566
567
568
  struct Blob *text,      /* The word after the tag character */
  enum mkd_tagspan type,  /* Which type of tagspan we're creating */
  void *opaque
){
  if( text==0 ){
    /* no-op */
  }else{
    char c;
    BLOB_APPEND_LITERAL(ob, "<span data-");
    switch (type) {

        case MKDT_ATREF: c='@'; BLOB_APPEND_LITERAL(ob, "atref"); break;

        case MKDT_HASH:  c='#'; BLOB_APPEND_LITERAL(ob, "hash");  break;
    }
    BLOB_APPEND_LITERAL(ob, "=\"");
    html_quote(ob, blob_buffer(text), blob_size(text));
    BLOB_APPEND_LITERAL(ob, "\"");
    blob_appendf(ob, ">%c%b</span>", c, text);
  }
  return 1;
}

static int html_triple_emphasis(
  struct Blob *ob,
  struct Blob *text,







|


>
|
>
|




|







545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
  struct Blob *text,      /* The word after the tag character */
  enum mkd_tagspan type,  /* Which type of tagspan we're creating */
  void *opaque
){
  if( text==0 ){
    /* no-op */
  }else{
    char cPrefix = '!';
    BLOB_APPEND_LITERAL(ob, "<span data-");
    switch (type) {
      case MKDT_ATREF:
        cPrefix = '@'; BLOB_APPEND_LITERAL(ob, "atref"); break;
      case MKDT_HASHTAG:
        cPrefix = '#'; BLOB_APPEND_LITERAL(ob, "hashtag");  break;
    }
    BLOB_APPEND_LITERAL(ob, "=\"");
    html_quote(ob, blob_buffer(text), blob_size(text));
    BLOB_APPEND_LITERAL(ob, "\"");
    blob_appendf(ob, ">%c%b</span>", cPrefix,text);
  }
  return 1;
}

static int html_triple_emphasis(
  struct Blob *ob,
  struct Blob *text,