1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-10 00:37:02 +02:00

Additional updates for ProcessModule README viewer for processwire/processwire-requests#498. Now if you have a ModuleName.README.md file, it will display automatically above the module config settings. This update also makes any relative <a href=/url/> or <img src=file.jpg automatically point to the module's /site/modules/ location, so that an <img src="file.jpg"> automatically updates to <img src="/site/modules/ModuleName/file.jpg">. Links to README.md or CHANGES.md are updated to use the built in-viewer. Other links are converted to target=_blank links, so that they don't take over the iframe used by the modal. You can use {MODULE_INFO.NAME}, {MODULE_INFO.TITLE}, and so on for any module info property, to have it convert automatically to the appropriate value (this was requested by Bernhard). Lastly, this update also adds support for text-only files like README.txt, CHANGELOG.txt, LICENSE.txt.

This commit is contained in:
Ryan Cramer
2024-02-06 12:06:38 -05:00
parent a3f884146f
commit 0a926b58fa

View File

@@ -135,9 +135,12 @@ class ProcessModule extends Process {
*
*/
protected $readmeFiles = array(
'readme' => 'README.md',
'changelog' => 'CHANGELOG.md',
'license' => 'LICENSE.md'
'readme.md' => 'README.md',
'readme.txt' => 'README.txt',
'changelog.md' => 'CHANGELOG.md',
'changelog.txt' => 'CHANGELOG.txt',
'license.md' => 'LICENSE.md',
'license.txt' => 'LICENSE.txt'
);
/**
@@ -1982,6 +1985,26 @@ class ProcessModule extends Process {
$readmePath = $config->paths($moduleName);
$supportFiles = [];
$readmeNowFile = $readmePath . "$moduleName.README.md";
if(file_exists($readmeNowFile)) {
$f = $form->InputfieldMarkup;
$f->attr('id+name', '_readmeNow');
$f->attr('title', basename($readmeNowFile));
$f->label = basename($readmeNowFile);
$f->themeOffset = 1;
$readmeNow = $this->renderReadme($moduleName, $readmeNowFile);
if(!empty($readmeNow)) {
if(preg_match('!\s*<h1>(.+?)</h1>!i', $readmeNow, $matches)) {
$f->label = $sanitizer->unentities($matches[1]);
$readmeNow = str_replace($matches[0], '', $readmeNow);
}
$f->val($readmeNow);
$f->icon = !empty($moduleInfo['icon']) ? $moduleInfo['icon'] : 'file-text-o';
$form->prepend($f);
}
}
foreach($this->readmeFiles as $readmeType => $basename) {
$readmeFile = $readmePath . $basename;
if(!file_exists($readmeFile)) continue;
@@ -2003,12 +2026,14 @@ class ProcessModule extends Process {
$field->attr('value', $table->render());
$field->label = $this->labels['module_information'];
$field->icon = 'info-circle';
$field->themeOffset = 1;
if($config->advanced) {
$field->appendMarkup .= "<p class='detail' style='text-align:right'>* " . $this->_('Options available in advanced mode only.') . "</p>";
}
if($collapseInfo) $field->collapsed = Inputfield::collapsedYes;
$form->prepend($field);
$form->prepend($field);
$out .= $form->render();
return $out;
@@ -2033,7 +2058,7 @@ class ProcessModule extends Process {
}
/**
* Execute view of supported README type markdown file
* Execute view of supported README type markdown or txt file
*
* @return string
* @since 3.0.236
@@ -2041,34 +2066,95 @@ class ProcessModule extends Process {
*/
public function ___executeReadme() {
$files = $this->wire()->files;
$input = $this->wire()->input;
$sanitizer = $this->wire()->sanitizer;
$modules = $this->wire()->modules;
$moduleName = $input->get->fieldName('name');
$name = basename(strtolower($input->get->fieldName('type')), '.md');
$path = $this->wire()->config->paths($moduleName);
$name = basename(strtolower($input->get->name('type')));
if(empty($moduleName) || !$modules->isInstalled($moduleName)) throw new WireException('Unknown module');
if(empty($name) || empty($path) || !isset($this->readmeFiles[$name])) throw new WireException("Unknown or unsupported file");
$fileName = $path . $this->readmeFiles[$name];
if(!$files->exists($fileName)) throw new WireException("File not found");
/** @var TextformatterMarkdownExtra $markdown */
$markdown = $modules->get('TextformatterMarkdownExtra');
if(!$markdown) throw new WireException('Cannot find Markdown module');
$out = $files->fileGetContents($fileName);
$out = $markdown->markdownSafe($out);
$out = $sanitizer->purify($out);
if(empty($name) || !isset($this->readmeFiles[$name])) throw new WireException("Unknown or unsupported file");
$out = $this->renderReadme($moduleName, $this->readmeFiles[$name]);
if(empty($out)) wire404();
$this->headline($this->readmeFiles[$name]);
$this->browserTitle("$moduleName - " . $this->readmeFiles[$name]);
return $out;
}
/**
* Render a readme file
*
* @param string $moduleName Module name
* @param string $readmeFile File basename
* @return string|false
*
*/
protected function renderReadme($moduleName, $readmeFile) {
$files = $this->wire()->files;
$sanitizer = $this->wire()->sanitizer;
$modules = $this->wire()->modules;
$config = $this->wire()->config;
$readmeFile = basename($readmeFile);
$path = $config->paths($moduleName);
if(empty($path) || strlen($readmeFile) < 4) return false;
$fileName = $path . $readmeFile;
if(!$files->exists($fileName)) return false;
$ext = pathinfo($fileName, PATHINFO_EXTENSION);
$out = $files->fileGetContents($fileName);
// allow for {MODULE_INFO.PROPERTY} to be replaced with actual module info value
if(stripos($out, '{MODULE_INFO.') !== false) {
$moduleInfo = $modules->getModuleInfoVerbose($moduleName);
foreach($moduleInfo as $key => $value) {
$find = "{MODULE_INFO.$key}";
if(stripos($out, $find) === false) continue;
$out = str_ireplace($find, (string) $value, $out);
}
}
if($ext !== 'md') return '<pre>' . $sanitizer->entities($out) . '</pre>';
/** @var TextformatterMarkdownExtra $md*/
$md = $modules->get('TextformatterMarkdownExtra');
$out = $sanitizer->purify($md->markdownSafe($out));
// if there are no <img> or <a> tags then we are finished
if(strpos($out, '<img') === false && !strpos($out, '</a>')) return $out;
$moduleUrl = $config->urls($moduleName);
$readmeUrl = str_replace('/edit', '/readme', $modules->getModuleEditUrl($moduleName));
// make <img src=...> and <a href=...> attributes relative to module's URL, so that
// src="file.jpg" converts to src="/site/modules/ModuleName/file.jpg"
if(preg_match_all('!<(?:a|img)\s[^<>]*?(?:src|href)=["\']([^/#][^"\']+)["\']!', $out, $matches)) {
foreach($matches[0] as $key => $tagOld) {
$valOld = $matches[1][$key];
if(strpos($valOld, '//') !== false) continue;
$valNew = $moduleUrl . ltrim($valOld, './');
$tagNew = str_replace($valOld, $valNew, $tagOld);
$out = str_replace($tagOld, $tagNew, $out);
}
}
// if there's a link to a supported README file, then update it to use our viewer
foreach($this->readmeFiles as $type => $readmeFile) {
$href = 'href="' . $moduleUrl . $readmeFile . '"';
if(strpos($out, $href) === false) continue;
$out = str_replace($href, "class=\"pw-modal\" href=\"$readmeUrl&amp;type=$type\"", $out);
}
// make any links open in blank target
$out = str_replace('<a ', '<a target="_blank"', $out);
return $out;
}
public function ___executeInstallConfirm() {