thephpleague / commonmark

Highly-extensible PHP Markdown parser which fully supports the CommonMark and GFM specs.
https://commonmark.thephpleague.com
BSD 3-Clause "New" or "Revised" License
2.75k stars 194 forks source link

Exception when setting unordered_list_markers; exception when *not* setting unordered_list_markers #1015

Open GarrettAlbright opened 8 months ago

GarrettAlbright commented 8 months ago

Version(s) affected

2.4.2

Description

The attached code, when run on PHP 8.1.27, will produce:

Uncaught Nette\Schema\ValidationException: Unexpected item 'commonmark › unordered_list_markers'. in /[…]/vendor/nette/schema/src/Schema/Processor.php:85

If line 18 is changed so no config array is passed ($env = new Environment();), the code produces:

Uncaught Dflydev\DotAccessData\Exception\MissingPathException: No data exists at the given path: "commonmark » unordered_list_markers" in /[…]/vendor/dflydev/dot-access-data/src/Data.php:132

Context: We're using code similar to this to limit the MD features that untrusted users can use when leaving comments on pages on our site, so I'm not using the CommonMarkCoreExtension(). Instead I'm using the InlinesOnlyExtension() and then adding a couple blocks we want to allow. Lists are one of the things we want to allow, but after (finally) upgrading from 1.x, I've run into this issue.

How to reproduce

<?php

require __DIR__ . '/vendor/autoload.php';

use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\Node\Block as NodeBlock;
use League\CommonMark\Extension\CommonMark\Parser\Block as ParserBlock;
use League\CommonMark\Extension\CommonMark\Renderer\Block as RendererBlock;
use League\CommonMark\Extension\InlinesOnly\InlinesOnlyExtension;
use League\CommonMark\MarkdownConverter;

$config = [
    'commonmark' => [
        'unordered_list_markers' => ['*', '+', '-'],
    ],
];

$env = new Environment($config);

$env->addExtension(new InlinesOnlyExtension())
    ->addBlockStartParser(new ParserBlock\ListBlockStartParser())
    ->addRenderer(NodeBlock\ListBlock::class, new RendererBlock\ListBlockRenderer())
    ->addRenderer(NodeBlock\ListItem::class, new RendererBlock\ListItemRenderer());

$conv = new MarkdownConverter($env);

$doc = <<<END
Hello

- A
- B
- C

Goodbye
END;

echo $conv->convert($doc);

Possible solution

The default configuration should be used if no configuration is present when creating the Environment. Either way no exception should be thrown. I'm afraid I don't really understand how that config package works to suggest something less obvious than this.

Additional context

No response

Did this project help you today? Did it make you happy in any way?

<3

colinodell commented 7 months ago

Yeah, the problem is that the unordered_list_markers setting is defined as part of the CommonMarkCoreExtension but not the InlinesOnlyExtension: https://github.com/thephpleague/commonmark/blob/91c24291965bd6d7c46c46a12ba7492f83b1cadf/src/Extension/CommonMark/CommonMarkCoreExtension.php#L32-L38

https://github.com/thephpleague/commonmark/blob/91c24291965bd6d7c46c46a12ba7492f83b1cadf/src/Extension/InlinesOnly/InlinesOnlyExtension.php#L28-L33

For your use case I'd recommend copying InlinesOnlyExtension into your own custom extension and adding the missing config option (plus the additional parser/renderers too)

The default configuration should be used if no configuration is present when creating the Environment.

Yeah, this is one of the few reasons I'm not super happy with how configuration works today. I'm hoping to revisit the configuration implementation for v3, but I have no ETA on that.