', ''), '', $pre_content); 18 | 19 | /* 20 | * Checking for the code tag. 21 | * Usually pre tags are used along with code tags. This conditional will check for already converted code tags, 22 | * which use backticks, and if those backticks are at the beginning and at the end of the string it means 23 | * there's no more information to convert. 24 | */ 25 | 26 | $firstBacktick = strpos(trim($pre_content), '`'); 27 | $lastBacktick = strrpos(trim($pre_content), '`'); 28 | if ($firstBacktick === 0 && $lastBacktick === strlen(trim($pre_content)) - 1) { 29 | return $pre_content . "\n\n"; 30 | } 31 | 32 | // If the execution reaches this point it means it's just a pre tag, with no code tag nested 33 | 34 | // Empty lines are a special case 35 | if ($pre_content === '') { 36 | return "```\n```\n\n"; 37 | } 38 | 39 | // Normalizing new lines 40 | $pre_content = preg_replace('/\r\n|\r|\n/', "\n", $pre_content); 41 | 42 | // Ensure there's a newline at the end 43 | if (strrpos($pre_content, "\n") !== strlen($pre_content) - strlen("\n")) { 44 | $pre_content .= "\n"; 45 | } 46 | 47 | // Use three backticks 48 | return "```\n" . $pre_content . "```\n\n"; 49 | } 50 | 51 | /** 52 | * @return string[] 53 | */ 54 | public function getSupportedTags() 55 | { 56 | return array('pre'); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /vendor/league/html-to-markdown/src/Configuration.php: -------------------------------------------------------------------------------- 1 | config = $config; 15 | 16 | $this->checkForDeprecatedOptions($config); 17 | } 18 | 19 | /** 20 | * @param array $config 21 | */ 22 | public function merge(array $config = array()) 23 | { 24 | $this->checkForDeprecatedOptions($config); 25 | $this->config = array_replace_recursive($this->config, $config); 26 | } 27 | 28 | /** 29 | * @param array $config 30 | */ 31 | public function replace(array $config = array()) 32 | { 33 | $this->checkForDeprecatedOptions($config); 34 | $this->config = $config; 35 | } 36 | 37 | /** 38 | * @param string $key 39 | * @param mixed $value 40 | */ 41 | public function setOption($key, $value) 42 | { 43 | $this->checkForDeprecatedOptions(array($key => $value)); 44 | $this->config[$key] = $value; 45 | } 46 | 47 | /** 48 | * @param string|null $key 49 | * @param mixed|null $default 50 | * 51 | * @return mixed|null 52 | */ 53 | public function getOption($key = null, $default = null) 54 | { 55 | if ($key === null) { 56 | return $this->config; 57 | } 58 | 59 | if (!isset($this->config[$key])) { 60 | return $default; 61 | } 62 | 63 | return $this->config[$key]; 64 | } 65 | 66 | private function checkForDeprecatedOptions(array $config) 67 | { 68 | foreach ($config as $key => $value) { 69 | if ($key === 'bold_style' && $value !== '**') { 70 | @trigger_error('Customizing the bold_style option is deprecated and may be removed in the next major version', E_USER_DEPRECATED); 71 | } elseif ($key === 'italic_style' && $value !== '*') { 72 | @trigger_error('Customizing the italic_style option is deprecated and may be removed in the next major version', E_USER_DEPRECATED); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /vendor/league/html-to-markdown/src/Converter/HeaderConverter.php: -------------------------------------------------------------------------------- 1 | config = $config; 25 | } 26 | 27 | /** 28 | * @param ElementInterface $element 29 | * 30 | * @return string 31 | */ 32 | public function convert(ElementInterface $element) 33 | { 34 | $level = (int) substr($element->getTagName(), 1, 1); 35 | $style = $this->config->getOption('header_style', self::STYLE_SETEXT); 36 | 37 | if (strlen($element->getValue()) === 0) { 38 | return "\n"; 39 | } 40 | 41 | if (($level === 1 || $level === 2) && !$element->isDescendantOf('blockquote') && $style === self::STYLE_SETEXT) { 42 | return $this->createSetextHeader($level, $element->getValue()); 43 | } 44 | 45 | return $this->createAtxHeader($level, $element->getValue()); 46 | } 47 | 48 | /** 49 | * @return string[] 50 | */ 51 | public function getSupportedTags() 52 | { 53 | return array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'); 54 | } 55 | 56 | /** 57 | * @param int $level 58 | * @param string $content 59 | * 60 | * @return string 61 | */ 62 | private function createSetextHeader($level, $content) 63 | { 64 | $length = function_exists('mb_strlen') ? mb_strlen($content, 'utf-8') : strlen($content); 65 | $underline = ($level === 1) ? '=' : '-'; 66 | 67 | return $content . "\n" . str_repeat($underline, $length) . "\n\n"; 68 | } 69 | 70 | /** 71 | * @param int $level 72 | * @param string $content 73 | * 74 | * @return string 75 | */ 76 | private function createAtxHeader($level, $content) 77 | { 78 | $prefix = str_repeat('#', $level) . ' '; 79 | 80 | return $prefix . $content . "\n\n"; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /vendor/league/html-to-markdown/src/Converter/LinkConverter.php: -------------------------------------------------------------------------------- 1 | config = $config; 21 | } 22 | 23 | /** 24 | * @param ElementInterface $element 25 | * 26 | * @return string 27 | */ 28 | public function convert(ElementInterface $element) 29 | { 30 | $href = $element->getAttribute('href'); 31 | $title = $element->getAttribute('title'); 32 | $text = trim($element->getValue(), "\t\n\r\0\x0B"); 33 | 34 | if ($title !== '') { 35 | $markdown = '[' . $text . '](' . $href . ' "' . $title . '")'; 36 | } elseif ($href === $text && $this->isValidAutolink($href)) { 37 | $markdown = '<' . $href . '>'; 38 | } elseif ($href === 'mailto:' . $text && $this->isValidEmail($text)) { 39 | $markdown = '<' . $text . '>'; 40 | } else { 41 | if (stristr($href, ' ')) { 42 | $href = '<'.$href.'>'; 43 | } 44 | $markdown = '[' . $text . '](' . $href . ')'; 45 | } 46 | 47 | if (!$href) { 48 | $markdown = html_entity_decode($element->getChildrenAsString()); 49 | } 50 | 51 | return $markdown; 52 | } 53 | 54 | /** 55 | * @return string[] 56 | */ 57 | public function getSupportedTags() 58 | { 59 | return array('a'); 60 | } 61 | 62 | /** 63 | * @param string $href 64 | * 65 | * @return bool 66 | */ 67 | private function isValidAutolink($href) 68 | { 69 | $useAutolinks = $this->config->getOption('use_autolinks'); 70 | return $useAutolinks && (preg_match('/^[A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]*/i', $href) === 1); 71 | } 72 | 73 | /** 74 | * @param string $email 75 | * 76 | * @return bool 77 | */ 78 | private function isValidEmail($email) 79 | { 80 | // Email validation is messy business, but this should cover most cases 81 | return filter_var($email, FILTER_VALIDATE_EMAIL); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /vendor/league/html-to-markdown/bin/html-to-markdown: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | $arg) { 9 | if ($i === 0) { 10 | continue; 11 | } 12 | 13 | if (substr($arg, 0, 1) === '-') { 14 | switch ($arg) { 15 | case '-h': 16 | case '--help': 17 | echo getHelpText(); 18 | exit(0); 19 | default: 20 | fail('Unknown option: ' . $arg); 21 | } 22 | } else { 23 | $src = $argv[1]; 24 | } 25 | } 26 | 27 | if (isset($src)) { 28 | if (!file_exists($src)) { 29 | fail('File not found: ' . $src); 30 | } 31 | 32 | $html = file_get_contents($src); 33 | } else { 34 | $stdin = fopen('php://stdin', 'r'); 35 | stream_set_blocking($stdin, false); 36 | $html = stream_get_contents($stdin); 37 | fclose($stdin); 38 | 39 | if (empty($html)) { 40 | fail(getHelpText()); 41 | } 42 | } 43 | 44 | 45 | $converter = new League\HTMLToMarkdown\HtmlConverter(); 46 | echo $converter->convert($html); 47 | 48 | /** 49 | * Get help and usage info 50 | * 51 | * @return string 52 | */ 53 | function getHelpText() 54 | { 55 | return <<
]*>/', '', $code);
39 | $code = str_replace('', '', $code);
40 |
41 | // Checking if it's a code block or span
42 | if ($this->shouldBeBlock($element, $code)) {
43 | // Code block detected, newlines will be added in parent
44 | $markdown .= '```' . $language . "\n" . $code . "\n" . '```';
45 | } else {
46 | // One line of code, wrapping it on one backtick, removing new lines
47 | $markdown .= '`' . preg_replace('/\r\n|\r|\n/', '', $code) . '`';
48 | }
49 |
50 | return $markdown;
51 | }
52 |
53 | /**
54 | * @return string[]
55 | */
56 | public function getSupportedTags()
57 | {
58 | return array('code');
59 | }
60 |
61 | /**
62 | * @param ElementInterface $element
63 | * @param string $code
64 | *
65 | * @return bool
66 | */
67 | private function shouldBeBlock(ElementInterface $element, $code)
68 | {
69 | if ($element->getParent()->getTagName() == 'pre') {
70 | return true;
71 | }
72 |
73 | if (preg_match('/[^\s]` `/', $code)) {
74 | return true;
75 | }
76 |
77 | return false;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/vendor/league/html-to-markdown/src/Converter/ListItemConverter.php:
--------------------------------------------------------------------------------
1 | config = $config;
27 | }
28 |
29 | /**
30 | * @param ElementInterface $element
31 | *
32 | * @return string
33 | */
34 | public function convert(ElementInterface $element)
35 | {
36 | // If parent is an ol, use numbers, otherwise, use dashes
37 | $list_type = $element->getParent()->getTagName();
38 |
39 | // Add spaces to start for nested list items
40 | $level = $element->getListItemLevel($element);
41 |
42 | $prefixForParagraph = str_repeat(' ', $level + 1);
43 | $value = trim(implode("\n" . $prefixForParagraph, explode("\n", trim($element->getValue()))));
44 |
45 | // If list item is the first in a nested list, add a newline before it
46 | $prefix = '';
47 | if ($level > 0 && $element->getSiblingPosition() === 1) {
48 | $prefix = "\n";
49 | }
50 |
51 | if ($list_type === 'ul') {
52 | $list_item_style = $this->config->getOption('list_item_style', '-');
53 | $list_item_style_alternate = $this->config->getOption('list_item_style_alternate');
54 | if (!isset($this->listItemStyle)) {
55 | $this->listItemStyle = $list_item_style_alternate ? $list_item_style_alternate : $list_item_style;
56 | }
57 |
58 | if ($list_item_style_alternate && $level == 0 && $element->getSiblingPosition() === 1) {
59 | $this->listItemStyle = $this->listItemStyle == $list_item_style ? $list_item_style_alternate : $list_item_style;
60 | }
61 |
62 | return $prefix . $this->listItemStyle . ' ' . $value . "\n";
63 | }
64 |
65 | if ($list_type === 'ol' && $start = $element->getParent()->getAttribute('start')) {
66 | $number = $start + $element->getSiblingPosition() - 1;
67 | } else {
68 | $number = $element->getSiblingPosition();
69 | }
70 |
71 | return $prefix . $number . '. ' . $value . "\n";
72 | }
73 |
74 | /**
75 | * @return string[]
76 | */
77 | public function getSupportedTags()
78 | {
79 | return array('li');
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/vendor/composer/installed.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "league/html-to-markdown",
4 | "version": "4.10.0",
5 | "version_normalized": "4.10.0.0",
6 | "source": {
7 | "type": "git",
8 | "url": "https://github.com/thephpleague/html-to-markdown.git",
9 | "reference": "0868ae7a552e809e5cd8f93ba022071640408e88"
10 | },
11 | "dist": {
12 | "type": "zip",
13 | "url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/0868ae7a552e809e5cd8f93ba022071640408e88",
14 | "reference": "0868ae7a552e809e5cd8f93ba022071640408e88",
15 | "shasum": ""
16 | },
17 | "require": {
18 | "ext-dom": "*",
19 | "ext-xml": "*",
20 | "php": ">=5.3.3"
21 | },
22 | "require-dev": {
23 | "mikehaertl/php-shellcommand": "~1.1.0",
24 | "phpunit/phpunit": "^4.8|^5.7",
25 | "scrutinizer/ocular": "~1.1"
26 | },
27 | "time": "2020-07-01T00:34:03+00:00",
28 | "bin": [
29 | "bin/html-to-markdown"
30 | ],
31 | "type": "library",
32 | "extra": {
33 | "branch-alias": {
34 | "dev-master": "4.10-dev"
35 | }
36 | },
37 | "installation-source": "dist",
38 | "autoload": {
39 | "psr-4": {
40 | "League\\HTMLToMarkdown\\": "src/"
41 | }
42 | },
43 | "notification-url": "https://packagist.org/downloads/",
44 | "license": [
45 | "MIT"
46 | ],
47 | "authors": [
48 | {
49 | "name": "Colin O'Dell",
50 | "email": "colinodell@gmail.com",
51 | "homepage": "https://www.colinodell.com",
52 | "role": "Lead Developer"
53 | },
54 | {
55 | "name": "Nick Cernis",
56 | "email": "nick@cern.is",
57 | "homepage": "http://modernnerd.net",
58 | "role": "Original Author"
59 | }
60 | ],
61 | "description": "An HTML-to-markdown conversion helper for PHP",
62 | "homepage": "https://github.com/thephpleague/html-to-markdown",
63 | "keywords": [
64 | "html",
65 | "markdown"
66 | ],
67 | "funding": [
68 | {
69 | "url": "https://www.colinodell.com/sponsor",
70 | "type": "custom"
71 | },
72 | {
73 | "url": "https://www.paypal.me/colinpodell/10.00",
74 | "type": "custom"
75 | },
76 | {
77 | "url": "https://github.com/colinodell",
78 | "type": "github"
79 | },
80 | {
81 | "url": "https://www.patreon.com/colinodell",
82 | "type": "patreon"
83 | }
84 | ]
85 | }
86 | ]
87 |
--------------------------------------------------------------------------------
/vendor/league/html-to-markdown/src/Converter/ParagraphConverter.php:
--------------------------------------------------------------------------------
1 | getValue();
17 |
18 | $markdown = '';
19 |
20 | $lines = preg_split('/\r\n|\r|\n/', $value);
21 | foreach ($lines as $line) {
22 | /*
23 | * Some special characters need to be escaped based on the position that they appear
24 | * The following function will deal with those special cases.
25 | */
26 | $markdown .= $this->escapeSpecialCharacters($line);
27 | $markdown .= "\n";
28 | }
29 |
30 | return trim($markdown) !== '' ? rtrim($markdown) . "\n\n" : '';
31 | }
32 |
33 | /**
34 | * @return string[]
35 | */
36 | public function getSupportedTags()
37 | {
38 | return array('p');
39 | }
40 |
41 | /**
42 | * @param string $line
43 | *
44 | * @return string
45 | */
46 | private function escapeSpecialCharacters($line)
47 | {
48 | $line = $this->escapeFirstCharacters($line);
49 | $line = $this->escapeOtherCharacters($line);
50 | $line = $this->escapeOtherCharactersRegex($line);
51 |
52 | return $line;
53 | }
54 |
55 | /**
56 | * @param string $line
57 | *
58 | * @return string
59 | */
60 | private function escapeFirstCharacters($line)
61 | {
62 | $escapable = array(
63 | '>',
64 | '- ',
65 | '+ ',
66 | '--',
67 | '~~~',
68 | '---',
69 | '- - -'
70 | );
71 |
72 | foreach ($escapable as $i) {
73 | if (strpos(ltrim($line), $i) === 0) {
74 | // Found a character that must be escaped, adding a backslash before
75 | return '\\' . ltrim($line);
76 | }
77 | }
78 |
79 | return $line;
80 | }
81 |
82 | /**
83 | * @param string $line
84 | *
85 | * @return string
86 | */
87 | private function escapeOtherCharacters($line)
88 | {
89 | $escapable = array(
90 | '';
104 | $markdown = $converter->convert($html); // $markdown now contains "Turnips!"
105 | ```
106 |
107 | To preserve only specific comments, set `preserve_comments` with an array of strings, like this:
108 |
109 | ```php
110 | $converter = new HtmlConverter(array('preserve_comments' => array('Eggs!')));
111 |
112 | $html = 'Turnips!';
113 | $markdown = $converter->convert($html); // $markdown now contains "Turnips!"
114 | ```
115 |
116 | ### Style options
117 |
118 | By default bold tags are converted using the asterisk syntax, and italic tags are converted using the underlined syntax. Change these by using the `bold_style` and `italic_style` options.
119 |
120 | ```php
121 | $converter = new HtmlConverter();
122 | $converter->getConfig()->setOption('italic_style', '*');
123 | $converter->getConfig()->setOption('bold_style', '__');
124 |
125 | $html = 'Italic and a bold';
126 | $markdown = $converter->convert($html); // $markdown now contains "*Italic* and a __bold__"
127 | ```
128 |
129 | ### Line break options
130 |
131 | By default, `br` tags are converted to two spaces followed by a newline character as per [traditional Markdown](https://daringfireball.net/projects/markdown/syntax#p). Set `hard_break` to `true` to omit the two spaces, as per GitHub Flavored Markdown (GFM).
132 |
133 | ```php
134 | $converter = new HtmlConverter();
135 | $html = 'test
line break
` tags (#174, #178)
23 |
24 | ## [4.8.2] - 2019-08-02
25 | ### Fixed
26 | - Fixed headers not being placed onto a new line in some cases (#172)
27 | - Fixed handling of links containing spaces (#175)
28 |
29 | ### Removed
30 | - Removed support for HHVM
31 |
32 | ## [4.8.1] - 2018-12-24
33 | ### Added
34 | - Added support for PHP 7.3
35 |
36 | ### Fixed
37 | - Fixed paragraphs following tables (#165, #166)
38 | - Fixed incorrect list item escaping (#168, #169)
39 |
40 | ## [4.8.0] - 2018-09-18
41 | ### Added
42 | - Added support for email auto-linking
43 | - Added a new interface (`HtmlConverterInterface`) for the main `HtmlConverter` class
44 | - Added additional test cases (#14)
45 |
46 | ### Changed
47 | - The `italic_style` option now defaults to `'*'` so that in-word emphasis is handled properly (#75)
48 |
49 | ### Fixed
50 | - Fixed several issues of `` and `` tags not converting to blocks or inlines properly (#26, #70, #102, #140, #161, #162)
51 | - Fixed in-word emphasis using underscores as delimiter (#75)
52 | - Fixed character escaping inside of `` elements
53 | - Fixed header edge cases
54 |
55 | ### Deprecated
56 | - The `bold_style` and `italic_style` options have been deprecated (#75)
57 |
58 | ## [4.7.0] - 2018-05-19
59 | ### Added
60 | - Added `setOptions()` function for chainable calling (#149)
61 | - Added new `list_item_style_alternate` option for converting every-other list with a different character (#155)
62 |
63 | ### Fixed
64 | - Fixed insufficient newlines after code blocks (#144, #148)
65 | - Fixed trailing spaces not being preserved in link anchors (#157)
66 | - Fixed list-like lines not being escaped inside of lists items (#159)
67 |
68 | ## [4.6.2]
69 | ### Fixed
70 | - Fixed issue with emphasized spaces (#146)
71 |
72 | ## [4.6.1]
73 | ### Fixed
74 | - Fixed conversion of `` tags (#145)
75 |
76 | ## [4.6.0]
77 | ### Added
78 | - Added support for ordered lists starting at numbers other than 1
79 |
80 | ### Fixed
81 | - Fixed overly-eager escaping of list-like text (#141)
82 |
83 | ## [4.5.0]
84 | ### Added
85 | - Added configuration option for list item style (#135, #136)
86 |
87 | ## [4.4.1]
88 |
89 | ### Fixed
90 | - Fixed autolinking of invalid URLs (#129)
91 |
92 | ## [4.4.0]
93 |
94 | ### Added
95 | - Added `hard_break` configuration option (#112, #115)
96 | - The `HtmlConverter` can now be instantiated with an `Environment` (#118)
97 |
98 | ### Fixed
99 | - Fixed handling of paragraphs in list item elements (#47, #110)
100 | - Fixed phantom spaces when newlines follow `br` elements (#116, #117)
101 | - Fixed link converter not sanitizing inner spaces properly (#119, #120)
102 |
103 | ## [4.3.1]
104 | ### Changed
105 | - Revised the sanitization implementation (#109)
106 |
107 | ### Fixed
108 | - Fixed tag-like content not being escaped (#67, #109)
109 | - Fixed thematic break-like content not being escaped (#65, #109)
110 | - Fixed codefence-like content not being escaped (#64, #109)
111 |
112 | ## [4.3.0]
113 | ### Added
114 | - Added full support for PHP 7.0 and 7.1
115 |
116 | ### Changed
117 | - Changed `` and `` conversions to use backticks instead of indendation (#102)
118 |
119 | ### Fixed
120 | - Fixed issue where specified code language was not preserved (#70, #102)
121 | - Fixed issue where `` tags nested in `` was not converted properly (#70, #102)
122 | - Fixed header-like content not being escaped (#76, #105)
123 | - Fixed blockquote-like content not being escaped (#77, #103)
124 | - Fixed ordered list-like content not being escaped (#73, #106)
125 | - Fixed unordered list-like content not being escaped (#71, #107)
126 |
127 | ## [4.2.2]
128 | ### Fixed
129 | - Fixed sanitization bug which sometimes removes desired content (#63, #101)
130 |
131 | ## [4.2.1]
132 | ### Fixed
133 | - Fixed path to autoload.php when used as a library (#98)
134 | - Fixed edge case for tags containing only whitespace (#99)
135 |
136 | ### Removed
137 | - Removed double HTML entity decoding, as this is not desireable (#60)
138 |
139 | ## [4.2.0]
140 |
141 | ### Added
142 | - Added the ability to invoke HtmlConverter objects as functions (#85)
143 |
144 | ### Fixed
145 | - Fixed improper handling of nested list items (#19 and #84)
146 | - Fixed preceeding or trailing spaces within emphasis tags (#83)
147 |
148 | ## [4.1.1]
149 |
150 | ### Fixed
151 | - Fixed conversion of empty paragraphs (#78)
152 | - Fixed `preg_replace` so it wouldn't break UTF-8 characters (#79)
153 |
154 | ## [4.1.0]
155 |
156 | ### Added
157 | - Added `bin/html-to-markdown` script
158 |
159 | ### Changed
160 | - Changed default italic character to `_` (#58)
161 |
162 | ## [4.0.1]
163 |
164 | ### Fixed
165 | - Added escaping to avoid * and _ in a text being rendered as emphasis (#48)
166 |
167 | ### Removed
168 | - Removed the demo (#51)
169 | - `.styleci.yml` and `CONTRIBUTING.md` are no longer included in distributions (#50)
170 |
171 | ## [4.0.0]
172 |
173 | This release changes the visibility of several methods/properties. #42 and #43 brought to light that some visiblities were
174 | not ideally set, so this releases fixes that. Moving forwards this should reduce the chance of introducing BC-breaking changes.
175 |
176 | ### Added
177 | - Added new `HtmlConverter::getEnvironment()` method to expose the `Environment` (#42, #43)
178 |
179 | ### Changed
180 | - Changed `Environment::addConverter()` from `protected` to `public`, enabling custom converters to be added (#42, #43)
181 | - Changed `HtmlConverter::createDOMDocument()` from `protected` to `private`
182 | - Changed `Element::nextCached` from `protected` to `private`
183 | - Made the `Environment` class `final`
184 |
185 | ## [3.1.1]
186 | ### Fixed
187 | - Empty HTML strings now result in empty Markdown documents (#40, #41)
188 |
189 | ## [3.1.0]
190 | ### Added
191 | - Added new `equals` method to `Element` to check for equality
192 |
193 | ### Changes
194 | - Use Linux line endings consistently instead of plaform-specific line endings (#36)
195 |
196 | ### Fixed
197 | - Cleaned up code style
198 |
199 | ## [3.0.0]
200 | ### Changed
201 | - Changed namespace to `League\HTMLToMarkdown`
202 | - Changed packagist name to `league/html-to-markdown`
203 | - Re-organized code into several separate classes
204 | - `` tags with identical href and inner text are now rendered using angular bracket syntax (#31)
205 | - `` elements are now treated as block-level elements (#33)
206 |
207 | ## [2.2.2]
208 | ### Added
209 | - Added support for PHP 5.6 and HHVM
210 | - Enabled testing against PHP 7 nightlies
211 | - Added this CHANGELOG.md
212 |
213 | ### Fixed
214 | - Fixed whitespace preservation between inline elements (#9 and #10)
215 |
216 | ## [2.2.1]
217 | ### Fixed
218 | - Preserve placeholder links (#22)
219 |
220 | ## [2.2.0]
221 | ### Added
222 | - Added CircleCI config
223 |
224 | ### Changed
225 | - `` blocks are now treated as code elements
226 |
227 | ### Removed
228 | - Dropped support for PHP 5.2
229 | - Removed incorrect README comment regarding `#text` nodes (#17)
230 |
231 | ## [2.1.2]
232 | ### Added
233 | - Added the ability to blacklist/remove specific node types (#11)
234 |
235 | ### Changed
236 | - Line breaks are now placed after divs instead of before them
237 | - Newlines inside of link texts are now removed
238 | - Updated the minimum PHPUnit version to 4.*
239 |
240 | ## [2.1.1]
241 | ### Added
242 | - Added options to customize emphasis characters
243 |
244 | ## [2.1.0]
245 | ### Added
246 | - Added option to strip HTML tags without Markdown equivalents
247 | - Added `convert()` method for converter reuse
248 | - Added ability to set options after instance construction
249 | - Documented the required PHP extensions (#4)
250 |
251 | ### Changed
252 | - ATX style now used for h1 and h2 tags inside blockquotes
253 |
254 | ### Fixed
255 | - Newlines inside blockquotes are now started with a bracket
256 | - Fixed some incorrect docblocks
257 | - `__toString()` now returns an empty string if input is empty
258 | - Convert head tag if body tag is empty (#7)
259 | - Preserve special characters inside tags without md equivalents (#6)
260 |
261 |
262 | ## [2.0.1]
263 | ### Fixed
264 | - Fixed first line indentation for multi-line code blocks
265 | - Fixed consecutive anchors get separating spaces stripped (#3)
266 |
267 | ## [2.0.0]
268 | ### Added
269 | - Initial release
270 |
271 | [unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.10.0...master
272 | [4.10.0]: https://github.com/thephpleague/html-to-markdown/compare/4.9.1...4.10.0
273 | [4.9.1]: https://github.com/thephpleague/html-to-markdown/compare/4.9.0...4.9.1
274 | [4.9.0]: https://github.com/thephpleague/html-to-markdown/compare/4.8.3...4.9.0
275 | [4.8.3]: https://github.com/thephpleague/html-to-markdown/compare/4.8.2...4.8.3
276 | [4.8.2]: https://github.com/thephpleague/html-to-markdown/compare/4.8.1...4.8.2
277 | [4.8.1]: https://github.com/thephpleague/html-to-markdown/compare/4.8.0...4.8.1
278 | [4.8.0]: https://github.com/thephpleague/html-to-markdown/compare/4.7.0...4.8.0
279 | [4.7.0]: https://github.com/thephpleague/html-to-markdown/compare/4.6.2...4.7.0
280 | [4.6.2]: https://github.com/thephpleague/html-to-markdown/compare/4.6.1...4.6.2
281 | [4.6.1]: https://github.com/thephpleague/html-to-markdown/compare/4.6.0...4.6.1
282 | [4.6.0]: https://github.com/thephpleague/html-to-markdown/compare/4.5.0...4.6.0
283 | [4.5.0]: https://github.com/thephpleague/html-to-markdown/compare/4.4.1...4.5.0
284 | [4.4.1]: https://github.com/thephpleague/html-to-markdown/compare/4.4.0...4.4.1
285 | [4.4.0]: https://github.com/thephpleague/html-to-markdown/compare/4.3.1...4.4.0
286 | [4.3.1]: https://github.com/thephpleague/html-to-markdown/compare/4.3.0...4.3.1
287 | [4.3.0]: https://github.com/thephpleague/html-to-markdown/compare/4.2.2...4.3.0
288 | [4.2.2]: https://github.com/thephpleague/html-to-markdown/compare/4.2.1...4.2.2
289 | [4.2.1]: https://github.com/thephpleague/html-to-markdown/compare/4.2.0...4.2.1
290 | [4.2.0]: https://github.com/thephpleague/html-to-markdown/compare/4.1.1...4.2.0
291 | [4.1.1]: https://github.com/thephpleague/html-to-markdown/compare/4.1.0...4.1.1
292 | [4.1.0]: https://github.com/thephpleague/html-to-markdown/compare/4.0.1...4.1.0
293 | [4.0.1]: https://github.com/thephpleague/html-to-markdown/compare/4.0.0...4.0.1
294 | [4.0.0]: https://github.com/thephpleague/html-to-markdown/compare/3.1.1...4.0.0
295 | [3.1.1]: https://github.com/thephpleague/html-to-markdown/compare/3.1.0...3.1.1
296 | [3.1.0]: https://github.com/thephpleague/html-to-markdown/compare/3.0.0...3.1.0
297 | [3.0.0]: https://github.com/thephpleague/html-to-markdown/compare/2.2.2...3.0.0
298 | [2.2.2]: https://github.com/thephpleague/html-to-markdown/compare/2.2.1...2.2.2
299 | [2.2.1]: https://github.com/thephpleague/html-to-markdown/compare/2.2.0...2.2.1
300 | [2.2.0]: https://github.com/thephpleague/html-to-markdown/compare/2.1.2...2.2.0
301 | [2.1.2]: https://github.com/thephpleague/html-to-markdown/compare/2.1.1...2.1.2
302 | [2.1.1]: https://github.com/thephpleague/html-to-markdown/compare/2.1.0...2.1.1
303 | [2.1.0]: https://github.com/thephpleague/html-to-markdown/compare/2.0.1...2.1.0
304 | [2.0.1]: https://github.com/thephpleague/html-to-markdown/compare/2.0.0...2.0.1
305 | [2.0.0]: https://github.com/thephpleague/html-to-markdown/compare/775f91e...2.0.0
306 |
307 |
--------------------------------------------------------------------------------
/vendor/composer/ClassLoader.php:
--------------------------------------------------------------------------------
1 |
7 | * Jordi Boggiano
8 | *
9 | * For the full copyright and license information, please view the LICENSE
10 | * file that was distributed with this source code.
11 | */
12 |
13 | namespace Composer\Autoload;
14 |
15 | /**
16 | * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17 | *
18 | * $loader = new \Composer\Autoload\ClassLoader();
19 | *
20 | * // register classes with namespaces
21 | * $loader->add('Symfony\Component', __DIR__.'/component');
22 | * $loader->add('Symfony', __DIR__.'/framework');
23 | *
24 | * // activate the autoloader
25 | * $loader->register();
26 | *
27 | * // to enable searching the include path (eg. for PEAR packages)
28 | * $loader->setUseIncludePath(true);
29 | *
30 | * In this example, if you try to use a class in the Symfony\Component
31 | * namespace or one of its children (Symfony\Component\Console for instance),
32 | * the autoloader will first look for the class under the component/
33 | * directory, and it will then fallback to the framework/ directory if not
34 | * found before giving up.
35 | *
36 | * This class is loosely based on the Symfony UniversalClassLoader.
37 | *
38 | * @author Fabien Potencier
39 | * @author Jordi Boggiano
40 | * @see http://www.php-fig.org/psr/psr-0/
41 | * @see http://www.php-fig.org/psr/psr-4/
42 | */
43 | class ClassLoader
44 | {
45 | // PSR-4
46 | private $prefixLengthsPsr4 = array();
47 | private $prefixDirsPsr4 = array();
48 | private $fallbackDirsPsr4 = array();
49 |
50 | // PSR-0
51 | private $prefixesPsr0 = array();
52 | private $fallbackDirsPsr0 = array();
53 |
54 | private $useIncludePath = false;
55 | private $classMap = array();
56 | private $classMapAuthoritative = false;
57 | private $missingClasses = array();
58 | private $apcuPrefix;
59 |
60 | public function getPrefixes()
61 | {
62 | if (!empty($this->prefixesPsr0)) {
63 | return call_user_func_array('array_merge', $this->prefixesPsr0);
64 | }
65 |
66 | return array();
67 | }
68 |
69 | public function getPrefixesPsr4()
70 | {
71 | return $this->prefixDirsPsr4;
72 | }
73 |
74 | public function getFallbackDirs()
75 | {
76 | return $this->fallbackDirsPsr0;
77 | }
78 |
79 | public function getFallbackDirsPsr4()
80 | {
81 | return $this->fallbackDirsPsr4;
82 | }
83 |
84 | public function getClassMap()
85 | {
86 | return $this->classMap;
87 | }
88 |
89 | /**
90 | * @param array $classMap Class to filename map
91 | */
92 | public function addClassMap(array $classMap)
93 | {
94 | if ($this->classMap) {
95 | $this->classMap = array_merge($this->classMap, $classMap);
96 | } else {
97 | $this->classMap = $classMap;
98 | }
99 | }
100 |
101 | /**
102 | * Registers a set of PSR-0 directories for a given prefix, either
103 | * appending or prepending to the ones previously set for this prefix.
104 | *
105 | * @param string $prefix The prefix
106 | * @param array|string $paths The PSR-0 root directories
107 | * @param bool $prepend Whether to prepend the directories
108 | */
109 | public function add($prefix, $paths, $prepend = false)
110 | {
111 | if (!$prefix) {
112 | if ($prepend) {
113 | $this->fallbackDirsPsr0 = array_merge(
114 | (array) $paths,
115 | $this->fallbackDirsPsr0
116 | );
117 | } else {
118 | $this->fallbackDirsPsr0 = array_merge(
119 | $this->fallbackDirsPsr0,
120 | (array) $paths
121 | );
122 | }
123 |
124 | return;
125 | }
126 |
127 | $first = $prefix[0];
128 | if (!isset($this->prefixesPsr0[$first][$prefix])) {
129 | $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130 |
131 | return;
132 | }
133 | if ($prepend) {
134 | $this->prefixesPsr0[$first][$prefix] = array_merge(
135 | (array) $paths,
136 | $this->prefixesPsr0[$first][$prefix]
137 | );
138 | } else {
139 | $this->prefixesPsr0[$first][$prefix] = array_merge(
140 | $this->prefixesPsr0[$first][$prefix],
141 | (array) $paths
142 | );
143 | }
144 | }
145 |
146 | /**
147 | * Registers a set of PSR-4 directories for a given namespace, either
148 | * appending or prepending to the ones previously set for this namespace.
149 | *
150 | * @param string $prefix The prefix/namespace, with trailing '\\'
151 | * @param array|string $paths The PSR-4 base directories
152 | * @param bool $prepend Whether to prepend the directories
153 | *
154 | * @throws \InvalidArgumentException
155 | */
156 | public function addPsr4($prefix, $paths, $prepend = false)
157 | {
158 | if (!$prefix) {
159 | // Register directories for the root namespace.
160 | if ($prepend) {
161 | $this->fallbackDirsPsr4 = array_merge(
162 | (array) $paths,
163 | $this->fallbackDirsPsr4
164 | );
165 | } else {
166 | $this->fallbackDirsPsr4 = array_merge(
167 | $this->fallbackDirsPsr4,
168 | (array) $paths
169 | );
170 | }
171 | } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172 | // Register directories for a new namespace.
173 | $length = strlen($prefix);
174 | if ('\\' !== $prefix[$length - 1]) {
175 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176 | }
177 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
179 | } elseif ($prepend) {
180 | // Prepend directories for an already registered namespace.
181 | $this->prefixDirsPsr4[$prefix] = array_merge(
182 | (array) $paths,
183 | $this->prefixDirsPsr4[$prefix]
184 | );
185 | } else {
186 | // Append directories for an already registered namespace.
187 | $this->prefixDirsPsr4[$prefix] = array_merge(
188 | $this->prefixDirsPsr4[$prefix],
189 | (array) $paths
190 | );
191 | }
192 | }
193 |
194 | /**
195 | * Registers a set of PSR-0 directories for a given prefix,
196 | * replacing any others previously set for this prefix.
197 | *
198 | * @param string $prefix The prefix
199 | * @param array|string $paths The PSR-0 base directories
200 | */
201 | public function set($prefix, $paths)
202 | {
203 | if (!$prefix) {
204 | $this->fallbackDirsPsr0 = (array) $paths;
205 | } else {
206 | $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207 | }
208 | }
209 |
210 | /**
211 | * Registers a set of PSR-4 directories for a given namespace,
212 | * replacing any others previously set for this namespace.
213 | *
214 | * @param string $prefix The prefix/namespace, with trailing '\\'
215 | * @param array|string $paths The PSR-4 base directories
216 | *
217 | * @throws \InvalidArgumentException
218 | */
219 | public function setPsr4($prefix, $paths)
220 | {
221 | if (!$prefix) {
222 | $this->fallbackDirsPsr4 = (array) $paths;
223 | } else {
224 | $length = strlen($prefix);
225 | if ('\\' !== $prefix[$length - 1]) {
226 | throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227 | }
228 | $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229 | $this->prefixDirsPsr4[$prefix] = (array) $paths;
230 | }
231 | }
232 |
233 | /**
234 | * Turns on searching the include path for class files.
235 | *
236 | * @param bool $useIncludePath
237 | */
238 | public function setUseIncludePath($useIncludePath)
239 | {
240 | $this->useIncludePath = $useIncludePath;
241 | }
242 |
243 | /**
244 | * Can be used to check if the autoloader uses the include path to check
245 | * for classes.
246 | *
247 | * @return bool
248 | */
249 | public function getUseIncludePath()
250 | {
251 | return $this->useIncludePath;
252 | }
253 |
254 | /**
255 | * Turns off searching the prefix and fallback directories for classes
256 | * that have not been registered with the class map.
257 | *
258 | * @param bool $classMapAuthoritative
259 | */
260 | public function setClassMapAuthoritative($classMapAuthoritative)
261 | {
262 | $this->classMapAuthoritative = $classMapAuthoritative;
263 | }
264 |
265 | /**
266 | * Should class lookup fail if not found in the current class map?
267 | *
268 | * @return bool
269 | */
270 | public function isClassMapAuthoritative()
271 | {
272 | return $this->classMapAuthoritative;
273 | }
274 |
275 | /**
276 | * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277 | *
278 | * @param string|null $apcuPrefix
279 | */
280 | public function setApcuPrefix($apcuPrefix)
281 | {
282 | $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
283 | }
284 |
285 | /**
286 | * The APCu prefix in use, or null if APCu caching is not enabled.
287 | *
288 | * @return string|null
289 | */
290 | public function getApcuPrefix()
291 | {
292 | return $this->apcuPrefix;
293 | }
294 |
295 | /**
296 | * Registers this instance as an autoloader.
297 | *
298 | * @param bool $prepend Whether to prepend the autoloader or not
299 | */
300 | public function register($prepend = false)
301 | {
302 | spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303 | }
304 |
305 | /**
306 | * Unregisters this instance as an autoloader.
307 | */
308 | public function unregister()
309 | {
310 | spl_autoload_unregister(array($this, 'loadClass'));
311 | }
312 |
313 | /**
314 | * Loads the given class or interface.
315 | *
316 | * @param string $class The name of the class
317 | * @return bool|null True if loaded, null otherwise
318 | */
319 | public function loadClass($class)
320 | {
321 | if ($file = $this->findFile($class)) {
322 | includeFile($file);
323 |
324 | return true;
325 | }
326 | }
327 |
328 | /**
329 | * Finds the path to the file where the class is defined.
330 | *
331 | * @param string $class The name of the class
332 | *
333 | * @return string|false The path if found, false otherwise
334 | */
335 | public function findFile($class)
336 | {
337 | // class map lookup
338 | if (isset($this->classMap[$class])) {
339 | return $this->classMap[$class];
340 | }
341 | if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342 | return false;
343 | }
344 | if (null !== $this->apcuPrefix) {
345 | $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346 | if ($hit) {
347 | return $file;
348 | }
349 | }
350 |
351 | $file = $this->findFileWithExtension($class, '.php');
352 |
353 | // Search for Hack files if we are running on HHVM
354 | if (false === $file && defined('HHVM_VERSION')) {
355 | $file = $this->findFileWithExtension($class, '.hh');
356 | }
357 |
358 | if (null !== $this->apcuPrefix) {
359 | apcu_add($this->apcuPrefix.$class, $file);
360 | }
361 |
362 | if (false === $file) {
363 | // Remember that this class does not exist.
364 | $this->missingClasses[$class] = true;
365 | }
366 |
367 | return $file;
368 | }
369 |
370 | private function findFileWithExtension($class, $ext)
371 | {
372 | // PSR-4 lookup
373 | $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374 |
375 | $first = $class[0];
376 | if (isset($this->prefixLengthsPsr4[$first])) {
377 | $subPath = $class;
378 | while (false !== $lastPos = strrpos($subPath, '\\')) {
379 | $subPath = substr($subPath, 0, $lastPos);
380 | $search = $subPath . '\\';
381 | if (isset($this->prefixDirsPsr4[$search])) {
382 | $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383 | foreach ($this->prefixDirsPsr4[$search] as $dir) {
384 | if (file_exists($file = $dir . $pathEnd)) {
385 | return $file;
386 | }
387 | }
388 | }
389 | }
390 | }
391 |
392 | // PSR-4 fallback dirs
393 | foreach ($this->fallbackDirsPsr4 as $dir) {
394 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395 | return $file;
396 | }
397 | }
398 |
399 | // PSR-0 lookup
400 | if (false !== $pos = strrpos($class, '\\')) {
401 | // namespaced class name
402 | $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403 | . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404 | } else {
405 | // PEAR-like class name
406 | $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407 | }
408 |
409 | if (isset($this->prefixesPsr0[$first])) {
410 | foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411 | if (0 === strpos($class, $prefix)) {
412 | foreach ($dirs as $dir) {
413 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414 | return $file;
415 | }
416 | }
417 | }
418 | }
419 | }
420 |
421 | // PSR-0 fallback dirs
422 | foreach ($this->fallbackDirsPsr0 as $dir) {
423 | if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424 | return $file;
425 | }
426 | }
427 |
428 | // PSR-0 include paths.
429 | if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430 | return $file;
431 | }
432 |
433 | return false;
434 | }
435 | }
436 |
437 | /**
438 | * Scope isolated include.
439 | *
440 | * Prevents access to $this/self from included files.
441 | */
442 | function includeFile($file)
443 | {
444 | include $file;
445 | }
446 |
--------------------------------------------------------------------------------