App-mdee

 view release on metacpan or  search on metacpan

CLAUDE.md  view on Meta::CPAN

```

The `code_block` label includes `;E` (erase line) for full-width background on fenced code blocks. `code_tick` has background color matching `code_inline` for visual continuity, with dimmer foreground. `code_inline` has explicit foreground (`L00`/`L2...

Inline code backticks are displayed as `` `content´ `` using `code_tick` color for the markers. Multi-backtick delimiters (``` `` ```, ```` ``` ````, etc.) are collapsed to a single pair, with optional surrounding spaces stripped per CommonMark. The...

Regex patterns used by the md module:

Fenced code blocks ([CommonMark](https://spec.commonmark.org/0.31.2/#fenced-code-blocks)):
```
^ {0,3}(?<bt>(?<fc>[`~])\g{fc}{2,}+)(.*)\n((?s:.*?))^ {0,3}\g{bt}\g{fc}*+\h*$
```

The closing fence is the same character as the opening one and at least as long, followed only by spaces or tabs; it is shown as written.  The `code_blocks` step uses the same rule with numbered captures.  A fence that is never closed is not treated ...

ATX headings ([CommonMark](https://spec.commonmark.org/0.31.2/#atx-headings)), for each level `$hdr` from `######` down to `#`: `^( {0,3}$hdr(?:\h+.*)?)$`.  Up to 3 spaces of indentation are allowed, and a line of `#`s alone is an empty heading; `#fo...

Inline code ([CommonMark Code Spans](https://spec.commonmark.org/0.31.2/#code-spans)) uses the `$CODE` pattern, which matches both single and multi-backtick spans. For multi-backtick (2+), optional leading/trailing spaces are stripped per CommonMark ...

### Front Matter

CLAUDE.md  view on Meta::CPAN

for name in "${!show[@]}"; do
    [[ $name == all ]] && continue
    md_opts+=(--show "${name}=${show[$name]}")
done
```

The md module's `active()` function checks show flags and skips regex substitutions entirely for disabled fields.

### Emphasis Patterns (CommonMark)

Bold/italic/strike patterns use `$SKIP_CODE` as first alternative to skip code spans. Named captures `(?<m>...)` (markers) and `(?<t>...)` (content) with `\g{m}` backreference prevent mixing (`**...__`).

- `(?<![\\\w])` / `(?!\w)`: Word boundaries for `_`/`__` (prevents `foo_bar_baz`)
- `(?<!\*)` / `(?!\*)`: Distinguishes `*italic*` from `**bold**`
- `flanking($delim)`: returns the opener and closer patterns of `*` or `**`, left-flanking and right-flanking as in CommonMark (so `L*=50, a*=68` is not italic, while `2*3*4` is), or by the markdown-cjk-friendly rules with `cjk_friendly=1`; see "Flan...
- `mark_color($type, $text)`: Uses `${type}_mark` if in colormap, falls back to `emphasis_mark`
- `/p` flag with `${^MATCH}`: Safe alternative to `$&` (used by `$SKIP_CODE`)

### OSC 8 Hyperlinks

Links are converted to OSC 8 terminal hyperlinks. Three types (in processing order): `image_link` (`[![alt](img)](url)`), `image` (`![alt](img)`), `link` (`[text](url)`). Each is colored, wrapped in OSC 8, and protected. Disable with `config(osc8=0)`...

docs/plans/2026-02-16-greple-md-implementation.md  view on Meta::CPAN

    $s =~ s/\x00(\d+)\x00/$protected[$1]/g;
    $s;
}

sub colorize {
    @protected = ();

    # ... code block handling (return early) ...

    # Inline code: protect from further processing
    s/((`++)(?:(?!\g{-2}).)+\g{-2})/protect(main::color('inline_code', $1))/ge;

    # HTML comments: protect from further processing
    s/(^<!--(?![->]).*?-->)/protect(main::color('comment', $1))/gme;

    # (links, headings, emphasis in later tasks)

    $_ = restore($_);
    $_;
}
```

lib/App/Greple/md.pm  view on Meta::CPAN

#

my $LT = qr/(?:`[^`\n]*+`|\\.|[^`\\\n\]]++)+/;

# Code span pattern (both single and multi-backtick).
# Captures: _bt (backtick delimiter), _content (code body).
# Used directly in inline_code step and as basis for $SKIP_CODE.
my $CODE = qr{(?x)
    (?<_bt> `++ )               # opening backtick(s)
    (?<_content>
        (?: (?! \g{_bt} ) . )+? # content (not containing same-length backticks)
    )
    \g{_bt}                     # closing backtick(s) matching opener
};

# Skip code spans in link/image patterns.
# Used as the first alternative in s{$SKIP_CODE|<link pattern>}{...}ge
# so that code spans are matched and skipped, preventing link/image
# patterns from matching inside them.
my $SKIP_CODE = qr{$CODE (*SKIP)(*FAIL)}x;

# Delimiters of * and ** emphasis (CommonMark 0.31.2, 6.2): an opener
# must be left-flanking and a closer right-flanking, so that

lib/App/Greple/md.pm  view on Meta::CPAN

                protect(md_color("h$n", restore($line)));
            }mge;
        }
    }),

    horizontal_rules => Step(horizontal_rule => sub {
        s/^([ ]{0,3}(?:[-*_][ ]*){3,})$/protect(md_color('horizontal_rule', $1))/mge;
    }),

    bold_italic => Step(bold => sub {
        s{$SKIP_CODE|(?<!\\)(?<m>\*\*\*)(?<t>.*?)(?<!\\)\g{m}}{
            protect(mark_color('bold', $+{m}) . md_color('bold', md_color('italic', $+{t})) . mark_color('bold', $+{m}))
        }gep;
        s{$SKIP_CODE|(?<![\\\w])(?<m>___)(?<t>.*?)(?<!\\)\g{m}(?!\w)}{
            protect(mark_color('bold', $+{m}) . md_color('bold', md_color('italic', $+{t})) . mark_color('bold', $+{m}))
        }gep;
    }),

    bold => Step(bold => sub {
        my($open, $close) = flanking('**');
        # no opener inside, so that a closer pairs with the nearest opener
        s{$SKIP_CODE|(?<!\\)(?<m>$open)(?<t>(?:(?!$open).)*?)(?<!\\)$close}{
            mark_color('bold', $+{m}) . md_color('bold', $+{t}) . mark_color('bold', $+{m})
        }gep;
        s{$SKIP_CODE|(?<![\\\w])(?<m>__)(?<t>.*?)(?<!\\)\g{m}(?!\w)}{
            mark_color('bold', $+{m}) . md_color('bold', $+{t}) . mark_color('bold', $+{m})
        }gep;
    }),

    italic => Step(italic => sub {
        my($open, $close) = flanking('*');
        s{$SKIP_CODE|(?<![\\\w])(?<m>_)(?<t>(?:(?!_).)+)(?<!\\)\g{m}(?!\w)}{
            mark_color('italic', $+{m}) . md_color('italic', $+{t}) . mark_color('italic', $+{m})
        }gep;
        s{$SKIP_CODE|(?<![\\*])(?<m>$open)(?<t>(?:(?!\*).)+)(?<!\\)$close(?!\*)}{
            mark_color('italic', $+{m}) . md_color('italic', $+{t}) . mark_color('italic', $+{m})
        }gep;
    }),

    strike => Step(strike => sub {
        s{$SKIP_CODE|(?<!\\)(?<m>~~)(?<t>.+?)(?<!\\)\g{m}}{
            mark_color('strike', $+{m}) . md_color('strike', $+{t}) . mark_color('strike', $+{m})
        }gep;
    }),

    blockquotes => Step(blockquote => sub {
        s/^( {0,3})((?:>\h?)+)(.*)$/$1 . md_color('blockquote', $2) . $3/mge;
    }),
);

#

lib/App/Greple/md.pm  view on Meta::CPAN

}

1;

__DATA__

option default \
    -G --filter --filestyle=once --color=always \
    --begin &__PACKAGE__::begin

define {CODE_BLOCK}  ^ {0,3}(?<bt>(?<fc>[`~])\g{fc}{2,}+)(.*)\n((?s:.*?))^ {0,3}\g{bt}\g{fc}*+\h*$
define {COMMENT}     ^<!--(?![->])(?s:.+?)-->
define {SGR}         (?:\e\[[\d:;]*[mK])*
define {SGR_END}     (?:\e\[[0;]*[mK])*
define {LIST_MARKER} (?:[*+-]|(?:\d+|#)[.)])
define {LIST_ITEM}   ^\h*{LIST_MARKER}\h+.*\n
define {QUOTE_LINE}  ^ {0,3}(?:{SGR}>\h?)+.*\n
# The prefix of a folded line's continuation lines: the quote markers
# (named group, repeated by ansifold --keepindent=named), then the indent,
# a list marker or a definition colon, which become spaces of the same
# width.  Every line matches (all parts may be empty), so that every line

lib/App/Greple/md/widen.pm  view on Meta::CPAN


This software is released under the MIT License.
L<https://opensource.org/licenses/MIT>

=cut

# Where the text must stay as written: fenced code with a language, code
# spans, and the addresses of links.
my $SKIP = qr{
    (?:
        ^ [ ]{0,3} (?<_fence> (?<_fc>[`~]) \g{_fc}{2,}+ ) \h* \S .* \n
        (?s:.*?)
        ^ [ ]{0,3} \g{_fence} \g{_fc}*+ \h* $
    |
        (?<_bt> `++ ) (?: (?! \g{_bt} ) . )+? \g{_bt}
    |
        \] \( [^)\n]* \)
    |
        < [a-zA-Z][\w+.-]*: [^>\s]* >
    )
    (*SKIP)(*FAIL)
}xm;

sub class {
    my $spec = shift;



( run in 0.832 second using v1.01-cache-2.11-cpan-99fa8243a42 )