private function __addBin($phar, $binary = 'bin/markdown-extended') { $content = Helper::readFile($this->root_dir . '/bin/markdown-extended'); $content = preg_replace('{^#!/usr/bin/env php\\s*}', '', $content); $this->_logs[] = sprintf('Adding binary file "%s" from source (length %d)', $binary, strlen($content)); $phar->addFromString($binary, $content); return $this; }
/** * Find defined inclusion blocks * * @param string $text * @return string */ public function transform($text) { $mask = Kernel::getConfig('block_inclusion_mask'); if (!empty($mask)) { $regex = Helper::buildRegex($mask); $text = preg_replace_callback($regex, array($this, '_callback'), $text); } return $text; }
/** * Process the fenced code blocks * * @param array $matches Results form the `transform()` function * @return string */ protected function _callback($matches) { $language = $matches[2]; $codeblock = Helper::escapeCodeContent($matches[3]); $codeblock = preg_replace_callback('/^\\n+/', array($this, '_newlines'), $codeblock); $attributes = array(); if (!empty($language)) { $attributes['language'] = $language; } $codeblock = Kernel::get('OutputFormatBag')->buildTag('preformatted', $codeblock, $attributes); return "\n\n" . parent::hashBlock($codeblock) . "\n\n"; }
/** * Loads a new formatter * * @param string $format The formatter name * @throws \MarkdownExtended\Exception\InvalidArgumentException if the class can not be found */ public function load($format) { $cls_name = $format; if (!class_exists($cls_name)) { $cls_name = '\\MarkdownExtended\\OutputFormat\\' . Helper::toCamelCase($format); } if (!class_exists($cls_name)) { throw new InvalidArgumentException(sprintf('Output format "%s" not found', $format)); } $cls = new $cls_name(); if (Kernel::validate($cls, Kernel::TYPE_OUTPUTFORMAT, $format)) { $this->setFormatter($cls); } }
/** * This will try to call a method `build{TagName}()` if it exists, then will try to use * the object `$tags_map` static to automatically find what to do, and then call the * default `getTagString()` method passing it the arguments. * * @param string $tag_name * @param string $content * @param array $attributes An array of attributes constructed like "variable=>value" pairs * * @return string */ public function buildTag($tag_name, $content = null, array $attributes = array()) { $_method = 'build' . Helper::toCamelCase($tag_name); if (isset($this->tags_map[$tag_name]) && isset($this->tags_map[$tag_name]['prefix'])) { $attributes['mde-prefix'] = $this->tags_map[$tag_name]['prefix']; } if (method_exists($this, $_method)) { return call_user_func_array(array($this, $_method), array($content, $attributes)); } $closable = false; if (isset($this->tags_map[$tag_name])) { $closable = isset($this->tags_map[$tag_name]['closable']) ? $this->tags_map[$tag_name]['closable'] : false; $tag_name = isset($this->tags_map[$tag_name]['tag']) ? $this->tags_map[$tag_name]['tag'] : $tag_name; } return call_user_func_array(array($this, 'getTagString'), array($content, $tag_name, $attributes, $closable)); }
/** * Gets the array of parameters to pass in the template based on a content object * * @param \MarkdownExtended\API\ContentInterface $content * * @return array * * @throws \MarkdownExtended\Exception\UnexpectedValueException if a keyword can not be found in the content object */ public function getParams(ContentInterface $content) { $params = array(); $keywords = $this->config->get('keywords'); // all options keywords foreach ($keywords as $var => $word) { $mask = $this->_buildKeywordMask($word); $method = 'get' . Helper::toCamelCase($var); if (!method_exists($content, $method)) { throw new UnexpectedValueException(sprintf('Template keyword "%s" not found in content', $var)); } $method_tostring = $method . 'Formatted'; $params[$mask] = function () use($content, $method, $method_tostring) { return call_user_func(array($content, method_exists($content, $method_tostring) ? $method_tostring : $method)); }; } // all metadata: META:name $meta = $content->getMetadata(); if (!empty($meta) && isset($keywords['metadata'])) { foreach ($meta as $name => $value) { $mask = $this->_buildKeywordMask($keywords['metadata'] . ':' . $name); $params[$mask] = function () use($value) { return Helper::getSafeString($value); }; } } return $params; }
/** * @param array $matches A set of results of the `transform` function * @return string */ protected function _reference_callback($matches) { $whole_match = $matches[1]; $alt_text = $matches[2]; $link_id = strtolower($matches[3]); if ($link_id == "") { $link_id = strtolower($alt_text); // for shortcut links like ![this][]. } $urls = Kernel::getConfig('urls'); $titles = Kernel::getConfig('titles'); $predef_attributes = Kernel::getConfig('attributes'); $alt_text = Lexer::runGamut(GamutLoader::TOOL_ALIAS . ':EncodeAttribute', $alt_text); if (isset($urls[$link_id])) { $attributes = array(); $attributes['alt'] = $alt_text; $attributes['id'] = Helper::header2Label($link_id); $attributes['src'] = Lexer::runGamut(GamutLoader::TOOL_ALIAS . ':EncodeAttribute', $urls[$link_id]); if (!empty($titles[$link_id])) { $attributes['title'] = Lexer::runGamut(GamutLoader::TOOL_ALIAS . ':EncodeAttribute', $titles[$link_id]); } if (!empty($predef_attributes[$link_id])) { $attributes = array_merge(Lexer::runGamut(GamutLoader::TOOL_ALIAS . ':ExtractAttributes', $predef_attributes[$link_id]), $attributes); } $block = Kernel::get('OutputFormatBag')->buildTag('image', null, $attributes); $result = parent::hashPart($block); } else { // If there's no such link ID, leave intact $result = $whole_match; } return $result; }
/** * Be sure to have a full attributes set (add a title if needed) * * @param array $attributes Passed by reference */ protected function _validateLinkAttributes(array &$attributes, &$text) { if (isset($attributes['email'])) { list($address_link, $address_text) = Helper::encodeEmailAddress($attributes['email']); if (!isset($attributes['href']) || empty($attributes['href'])) { $attributes['href'] = $address_link; } if ($this->getConfig('mailto_title_mask') && empty($attributes['title'])) { $attributes['title'] = Helper::fillPlaceholders($this->getConfig('mailto_title_mask'), $address_text); } unset($attributes['email']); $text = $address_text; } if (empty($attributes['title']) && isset($attributes['href'])) { $first_char = substr($attributes['href'], 0, 1); if ($first_char === '#' && $this->getConfig('anchor_title_mask')) { $attributes['title'] = Helper::fillPlaceholders($this->getConfig('anchor_title_mask'), $attributes['href']); } elseif ($this->getConfig('link_title_mask')) { $attributes['title'] = Helper::fillPlaceholders($this->getConfig('link_title_mask'), !empty($attributes['href']) ? $attributes['href'] : ''); } } }
/** * Form HTML tables: parses table contents * * @param array $matches * @return string */ protected function _callback($matches) { $attributes = array(); //self::doDebug($matches); // The head string may have a begin slash $caption = count($matches) > 3 ? $matches[1] : null; $head = count($matches) > 3 ? preg_replace('/^ *[|]/m', '', $matches[2]) : preg_replace('/^ *[|]/m', '', $matches[1]); $underline = count($matches) > 3 ? $matches[3] : $matches[2]; $content = count($matches) > 3 ? preg_replace('/^ *[|]/m', '', $matches[4]) : preg_replace('/^ *[|]/m', '', $matches[3]); // Remove any tailing pipes for each line. $underline = preg_replace('/[|] *$/m', '', $underline); $content = preg_replace('/[|] *$/m', '', $content); // Reading alignement from header underline. $separators = preg_split('/ *[|] */', $underline); foreach ($separators as $n => $s) { $attributes[$n] = array(); if (preg_match('/^ *-+: *$/', $s)) { $attributes[$n]['style'] = 'text-align:right;'; } elseif (preg_match('/^ *:-+: *$/', $s)) { $attributes[$n]['style'] = 'text-align:center;'; } elseif (preg_match('/^ *:-+ *$/', $s)) { $attributes[$n]['style'] = 'text-align:left;'; } } // Split content by row. $headers = explode("\n", trim($head, "\n")); $text = ''; if (!empty($caption)) { $this->table_id = Helper::header2Label($caption); $text .= preg_replace_callback('/\\[(.*)\\]/', array($this, '_doCaption'), Lexer::runGamut('span_gamut', $caption)); } $lines = ''; foreach ($headers as $_header) { $line = ''; // Parsing span elements, including code spans, character escapes, // and inline HTML tags, so that pipes inside those gets ignored. $_header = Lexer::runGamut('filter:Span', $_header); // Split row by cell. $_header = preg_replace('/[|] *$/m', '', $_header); $_headers = preg_split('/[|]/', $_header); $col_count = count($_headers); // Write column headers. // we first loop for colspans $headspans = array(); foreach ($_headers as $_i => $_cell) { if ($_cell == '') { if ($_i == 0) { $headspans[1] = 2; } else { if (isset($headspans[$_i - 1])) { $headspans[$_i - 1]++; } else { $headspans[$_i - 1] = 2; } } } } foreach ($_headers as $n => $__header) { if ($__header != '') { $cell_attributes = $attributes[$n]; if (isset($headspans[$n])) { $cell_attributes['colspan'] = $headspans[$n]; } $line .= Kernel::get('OutputFormatBag')->buildTag('table_cell_head', Lexer::runGamut('span_gamut', trim($__header)), $cell_attributes) . "\n"; } } $lines .= Kernel::get('OutputFormatBag')->buildTag('table_line', $line) . "\n"; } $text .= Kernel::get('OutputFormatBag')->buildTag('table_header', $lines); // Split content by row. $rows = explode("\n", trim($content, "\n")); $lines = ''; foreach ($rows as $row) { $line = ''; // Parsing span elements, including code spans, character escapes, // and inline HTML tags, so that pipes inside those gets ignored. $row = Lexer::runGamut('filter:Span', $row); // Split row by cell. $row_cells = preg_split('/ *[|] */', $row, $col_count); $row_cells = array_pad($row_cells, $col_count, ''); // we first loop for colspans $colspans = array(); foreach ($row_cells as $_i => $_cell) { if ($_cell == '') { if ($_i == 0) { $colspans[1] = 2; } else { if (isset($colspans[$_i - 1])) { $colspans[$_i - 1]++; } else { $colspans[$_i - 1] = 2; } } } } foreach ($row_cells as $n => $cell) { if ($cell != '') { $cell_attributes = $attributes[$n]; if (isset($colspans[$n])) { $cell_attributes['colspan'] = $colspans[$n]; } $line .= Kernel::get('OutputFormatBag')->buildTag('table_cell', Lexer::runGamut('span_gamut', trim($cell)), $cell_attributes) . "\n"; } } $lines .= Kernel::get('OutputFormatBag')->buildTag('table_line', $line) . "\n"; } $text .= Kernel::get('OutputFormatBag')->buildTag('table_body', $lines); $table = Kernel::get('OutputFormatBag')->buildTag('table', $text); return parent::hashBlock($table) . "\n"; }
/** * Dumps the composer.json file */ protected function runTaskManifest() { if (file_exists($manifest = MDE_BASE_PATH . self::MANIFEST_FILE)) { $content = json_decode(Helper::readFile($manifest), true); foreach (array('extra', 'autoload', 'autoload-dev', 'config', 'scripts', 'archive') as $entry) { if (isset($content[$entry])) { unset($content[$entry]); } } if (isset($content['keywords']) && is_array($content['keywords'])) { $content['keywords'] = implode(',', $content['keywords']); } if (isset($content['authors'])) { foreach ($content['authors'] as $i => $author) { if (is_array($author)) { $content['authors'][$i] = implode(', ', $author); } } } $this->_writeTask($content, 'Manifest'); } else { $this->stream->writeln('Manifest file not found', Stream::IO_STDERR); } }
/** * App's default settings * * @return array */ public static function getDefaults() { return array('escaped_characters' => "0`*_{}[]()<>#+-.!:|\\", 'tab_width' => 4, 'nested_brackets_depth' => 6, 'nested_parenthesis_depth' => 4, 'no_markup' => false, 'no_entities' => false, 'special_metadata' => array('baseheaderlevel', 'quoteslanguage', 'last_update', 'file_name'), 'block_inclusion_mask' => '<!-- @([^ @]+)@ -->', 'base_path' => array(getcwd()), 'footnote_id_prefix' => '', 'glossarynote_id_prefix' => '', 'bibliographynote_id_prefix' => '', 'date_to_string' => function (\DateTime $date) { return $date->format(DATE_W3C); }, 'filepath_to_title' => function ($path) { return \MarkdownExtended\Util\Helper::humanReadable(pathinfo($path, PATHINFO_FILENAME)); }, 'output_format' => 'html', 'output_format_options' => array('html' => array('html_empty_element_suffix' => ' />', 'anchor_title_mask' => 'Reach inpage section %%', 'link_title_mask' => 'See online %%', 'mailto_title_mask' => 'Contact %%', 'codeblock_language_attribute' => 'class', 'codeblock_attribute_mask' => 'language-%%', 'fn_link_title_mask' => 'See footnote %%', 'fn_backlink_title_mask' => 'Return to content', 'fn_link_class' => 'footnote', 'fn_backlink_class' => 'reverse_footnote', 'fng_link_title_mask' => 'See glossary entry %%', 'fng_backlink_title_mask' => 'Return to content', 'fng_link_class' => 'footnote_glossary', 'fng_backlink_class' => 'reverse_footnote_glossary', 'fnb_link_title_mask' => 'See bibliography reference %%', 'fnb_backlink_title_mask' => 'Return to content', 'fnb_link_class' => 'footnote_bibliography', 'fnb_backlink_class' => 'reverse_footnote_bibliography', 'math_type' => 'mathjax', 'default_template' => 'html5')), 'predefined_urls' => array(), 'predefined_titles' => array(), 'predefined_attributes' => array(), 'predefined_abbr' => array(), 'template' => 'auto', 'template_options' => array('keywords_mask' => "{%% ?%s ?%%}", 'keywords' => array('body' => 'BODY', 'notes' => 'NOTES', 'metadata' => 'META', 'charset' => 'CHARSET', 'title' => 'TITLE'), 'inline_template' => "{% META %}\n{% BODY %}\n{% NOTES %}"), 'initial_gamut' => array('filter:Detab:init' => '5', 'filter:Emphasis:prepare' => '10'), 'transform_gamut' => array('tool:RemoveUtf8Marker' => '5', 'tool:StandardizeLineEnding' => '10', 'tool:AppendEndingNewLines' => '15', 'filter:Detab' => '20', 'filter:HTML' => '25', 'tool:StripSpacedLines' => '30'), 'document_gamut' => array('tool:prepareOutputFormat' => '0', 'filter:MetaData:strip' => '1', 'filter:FencedCodeBlock' => '5', 'filter:Note:strip' => '10', 'filter:LinkDefinition:strip' => '20', 'filter:Abbreviation:strip' => '25', 'block_gamut' => '30', 'filter:MetaData:append' => '35', 'filter:Note:append' => '40', 'filter:BlockInclusion' => '50', 'tool:teardownOutputFormat' => '70'), 'span_gamut' => array('filter:Span' => '-30', 'filter:Note' => '5', 'filter:Image' => '10', 'filter:Anchor' => '20', 'filter:AutoLink' => '30', 'tool:EncodeAmpAndAngle' => '40', 'filter:Emphasis' => '50', 'filter:HardBreak' => '60', 'filter:Abbreviation' => '70'), 'block_gamut' => array('filter:FencedCodeBlock' => '5', 'filter:Header' => '10', 'filter:Table' => '15', 'filter:HorizontalRule' => '20', 'filter:ListItem' => '40', 'filter:DefinitionList' => '45', 'filter:CodeBlock' => '50', 'filter:BlockQuote' => '60', 'filter:Maths' => '70', 'tool:RebuildParagraph' => '100'), 'html_block_gamut' => array('filter:HTML' => '10', 'block_gamut' => '20')); }
/** * Create a code span markup for $code. Called from handleSpanToken. * * @param string $code * @return string */ public function span($code) { $codeblock = Kernel::get('OutputFormatBag')->buildTag('code', Helper::escapeCodeContent(trim($code))); return parent::hashPart($codeblock); }
public function buildMetaData($text = null, array $attributes = array()) { $text = $this->escapeString($text); if (!empty($attributes['name'])) { if (empty($attributes['content']) && !empty($text)) { $attributes['content'] = $text; } return '.\\" ' . $attributes['name'] . ': ' . Helper::getSafeString($attributes['content']); } return '.\\" ' . $text; }
private function _hardDebugContent(ContentInterface $content) { echo Helper::debug($content->getBody(), 'content body'); echo Helper::debug($content->getNotes(), 'content notes', false); echo Helper::debug($content->getMetadata(), 'content metadata', false); }
/** * Finds an internal resource file by type * * @param string $name * @param string $type * @return null|string */ public static function getResourcePath($name, $type) { if ($type === self::RESOURCE_CONFIG || $type === self::RESOURCE_TEMPLATE) { $local_path = realpath(Helper::getPath(array(dirname(__DIR__), 'Resources', strtolower($type)))); if (file_exists($local = $local_path . DIRECTORY_SEPARATOR . $name)) { return $local; } $mask = $type === self::RESOURCE_TEMPLATE ? self::RESOURCE_TEMPLATE_MASK : self::RESOURCE_CONFIG_MASK; $final_name = sprintf($mask, $name); if (file_exists($final = $local_path . DIRECTORY_SEPARATOR . $final_name)) { return $final; } } return null; }
/** * Process ATX-style headers * * @param array $matches The results from the `transform()` function * @return string */ protected function _atx_callback($matches) { $level = strlen($matches[1]) + $this->_getRebasedHeaderLevel(); $domid = !empty($matches[3]) ? $matches[3] : Helper::header2Label($matches[2]); $domid = Kernel::get('DomId')->set($domid); $title = Lexer::runGamut('span_gamut', $matches[2]); Kernel::addConfig('menu', array('level' => $level, 'text' => parent::unhash($title)), $domid); $block = Kernel::get('OutputFormatBag')->buildTag('title', $title, array('level' => $level, 'id' => $domid)); $this->_setContentTitle($title); return "\n" . parent::hashBlock($block) . "\n\n"; }
private function _hardDebug() { $short_options = $this->getFilteredOptions('short_option'); $long_options = $this->getFilteredOptions('long_option'); echo Helper::debug(array_values($short_options), 'short options', false); echo Helper::debug(array_values($long_options), 'long options', false); echo Helper::debug($this->getFilteredOptions('_default'), 'defaults', false); echo Helper::debug($this->user_options->original, 'input user options', false); echo Helper::debug($this->user_options->remaining, 'remaining arguments', false); echo Helper::debug($this->user_options->options, 'final full options', false); }