Skip to content

Commit

Permalink
Extended advaced settings section "compress html output" (now named "…
Browse files Browse the repository at this point in the history
…html Output") into now having 3 radio options: default (=no alteration of generated html), compress (remove all whitespace), beautify (=indent html correctly, allowing to easily find markup errors)
  • Loading branch information
kstenschke committed May 23, 2015
1 parent 07e27e0 commit 302fb16
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 14 deletions.
13 changes: 12 additions & 1 deletion application/config/ionize.php
Expand Up @@ -145,8 +145,19 @@
| To remove useless whitespace from generated HTML
|
*/
$config['compress_html_output'] = '0';
$config['compress_html_output'] = false;



/*
|--------------------------------------------------------------------------
| Beautify HTML output
|--------------------------------------------------------------------------
|
| To remove double whitespace lines and indent generated HTML correctly
|
*/
$config['beautify_html_output'] = true;

/* End of file ionize.php */
/* Location: ./application/config/ionize.php */
14 changes: 11 additions & 3 deletions application/controllers/admin/setting.php
Expand Up @@ -12,6 +12,9 @@

class Setting extends MY_admin
{
/** @var Config_model */
public $config_model;

/**
* Fields on wich no XSS filtering is done
*
Expand Down Expand Up @@ -915,14 +918,19 @@ function save_maintenance()
// ------------------------------------------------------------------------

/**
* Saves Compress HTML Output Setting
* Saves HTML Output Setting: Default (unaltered) / Compressed / Beautified
*
*/
function save_compress_html_output()
function save_html_output()
{
if ($this->config_model->change('ionize.php', 'compress_html_output', $this->input->post('compress_html_output')) == FALSE)
$html_output_mode = (int) $_REQUEST['html_output']; // 0= default, 1= compressed, 2= beautified

if ( $this->config_model->change('ionize.php', 'compress_html_output', $html_output_mode === 1) == FALSE
|| $this->config_model->change('ionize.php', 'beautify_html_output', $html_output_mode === 2) == FALSE
)
$this->error(lang('ionize_message_error_writing_ionize_file'));


// UI panel to update after saving
$this->update[] = array(
'element' => 'mainPanel',
Expand Down
7 changes: 7 additions & 0 deletions application/language/en/admin_lang.php
Expand Up @@ -651,9 +651,16 @@
$lang['ionize_label_your_ip'] = 'your IP';
$lang['ionize_label_maintenance_page_help'] = 'This page must be set before activating the maintenance mode in order to let Ionize build correctly the plain HTML page.';
$lang['ionize_message_maintenance_page_curl_error'] = 'The cURL PHP extension needs to be installed';
$lang['ionize_title_html_output'] = 'HTML Output';
$lang['ionize_title_default_html_output'] = 'Default HTML Output';
$lang['ionize_label_default_html_output'] = 'Default HTML Output';
$lang['ionize_label_default_html_output_help'] = 'Generates HTML from the view files without any reformatting (best during debugging).';
$lang['ionize_title_compress_html_output'] = 'Compress HTML Output';
$lang['ionize_label_compress_html_output'] = 'Compress HTML Output';
$lang['ionize_label_compress_html_output_help'] = 'To remove useless whitespace from generated HTML.';
$lang['ionize_title_beautify_html_output'] = 'Beautify HTML Output';
$lang['ionize_label_beautify_html_output'] = 'Beautify HTML Output';
$lang['ionize_label_beautify_html_output_help'] = 'Remove whitespace and correctly indent generated HTML.';
$lang['ionize_label_thumb_automatic'] = 'Automatic';
$lang['ionize_label_files_path'] = 'Media base folder';
$lang['ionize_label_media_type_picture'] = 'Images extensions';
Expand Down
11 changes: 8 additions & 3 deletions application/libraries/Tagmanager.php
Expand Up @@ -660,13 +660,18 @@ public static function render($view = NULL, $return = FALSE)
*/
}

if(config_item('beautify_html_output') == 1) {
require_once(APPPATH . 'third_party/indenter.php');
$indenter = new \Gajus\Dindent\Indenter();
$parsed = $indenter->indent($parsed);
}

// Returns the result or output it directly
if ($return)
if ($return) {
return $parsed;
else
} else {
self::$ci->output->set_output($parsed);

}
}


Expand Down
179 changes: 179 additions & 0 deletions application/third_party/indenter.php
@@ -0,0 +1,179 @@
<?php
namespace Gajus\Dindent;

/**
* @link https://github.com/gajus/dindent for the canonical source repository
* @license https://github.com/gajus/dindent/blob/master/LICENSE BSD 3-Clause
*/
class Indenter {
private
$log = array(),
$options = array(
'indentation_character' => ' '
),
$inline_elements = array('b', 'big', 'i', 'small', 'tt', 'abbr', 'acronym', 'cite', 'code', 'dfn', 'em', 'kbd', 'strong', 'samp', 'var', 'a', 'bdo', 'br', 'img', 'span', 'sub', 'sup'),
$temporary_replacements_script = array(),
$temporary_replacements_inline = array();

const ELEMENT_TYPE_BLOCK = 0;
const ELEMENT_TYPE_INLINE = 1;

const MATCH_INDENT_NO = 0;
const MATCH_INDENT_DECREASE = 1;
const MATCH_INDENT_INCREASE = 2;
const MATCH_DISCARD = 3;

/**
* @param array $options
*/
public function __construct (array $options = array()) {
foreach ($options as $name => $value) {
if (!array_key_exists($name, $this->options)) {
throw new Exception\InvalidArgumentException('Unrecognized option.');
}

$this->options[$name] = $value;
}
}

/**
* @param string $element_name Element name, e.g. "b".
* @param ELEMENT_TYPE_BLOCK|ELEMENT_TYPE_INLINE $type
* @return null
*/
public function setElementType ($element_name, $type) {
if ($type === static::ELEMENT_TYPE_BLOCK) {
$this->inline_elements = array_diff($this->inline_elements, array($element_name));
} else if ($type === static::ELEMENT_TYPE_INLINE) {
$this->inline_elements[] = $element_name;
} else {
throw new Exception\InvalidArgumentException('Unrecognized element type.');
}

$this->inline_elements = array_unique($this->inline_elements);
}

/**
* @param string $input HTML input.
* @return string Indented HTML.
*/
public function indent ($input) {
$this->log = array();

// Dindent does not indent <script> body. Instead, it temporary removes it from the code, indents the input, and restores the script body.
if (preg_match_all('/<script\b[^>]*>([\s\S]*?)<\/script>/mi', $input, $matches)) {
$this->temporary_replacements_script = $matches[0];
foreach ($matches[0] as $i => $match) {
$input = str_replace($match, '<script>' . ($i + 1) . '</script>', $input);
}
}

// Removing double whitespaces to make the source code easier to read.
// With exception of <pre>/ CSS white-space changing the default behaviour, double whitespace is meaningless in HTML output.
// This reason alone is sufficient not to use Dindent in production.
$input = str_replace("\t", '', $input);
$input = preg_replace('/\s{2,}/', ' ', $input);

// Remove inline elements and replace them with text entities.
if (preg_match_all('/<(' . implode('|', $this->inline_elements) . ')[^>]*>(?:[^<]*)<\/\1>/', $input, $matches)) {
$this->temporary_replacements_inline = $matches[0];
foreach ($matches[0] as $i => $match) {
$input = str_replace($match, 'ᐃ' . ($i + 1) . 'ᐃ', $input);
}
}

$subject = $input;

$output = '';

$next_line_indentation_level = 0;

do {
$indentation_level = $next_line_indentation_level;

$patterns = array(
// block tag
'/^(<([a-z]+)(?:[^>]*)>(?:[^<]*)<\/(?:\2)>)/' => static::MATCH_INDENT_NO,
// DOCTYPE
'/^<!([^>]*)>/' => static::MATCH_INDENT_NO,
// tag with implied closing
'/^<(input|link|meta|base|br|img|hr)([^>]*)>/' => static::MATCH_INDENT_NO,
// opening tag
'/^<[^\/]([^>]*)>/' => static::MATCH_INDENT_INCREASE,
// closing tag
'/^<\/([^>]*)>/' => static::MATCH_INDENT_DECREASE,
// self-closing tag
'/^<(.+)\/>/' => static::MATCH_INDENT_DECREASE,
// whitespace
'/^(\s+)/' => static::MATCH_DISCARD,
// text node
'/([^<]+)/' => static::MATCH_INDENT_NO
);
$rules = array('NO', 'DECREASE', 'INCREASE', 'DISCARD');

foreach ($patterns as $pattern => $rule) {
if ($match = preg_match($pattern, $subject, $matches)) {
$this->log[] = array(
'rule' => $rules[$rule],
'pattern' => $pattern,
'subject' => $subject,
'match' => $matches[0]
);

$subject = mb_substr($subject, mb_strlen($matches[0]));

if ($rule === static::MATCH_DISCARD) {
break;
}

if ($rule === static::MATCH_INDENT_NO) {

} else if ($rule === static::MATCH_INDENT_DECREASE) {
$next_line_indentation_level--;
$indentation_level--;
} else {
$next_line_indentation_level++;
}

if ($indentation_level < 0) {
$indentation_level = 0;
}

$output .= str_repeat($this->options['indentation_character'], $indentation_level) . $matches[0] . "\n";

break;
}
}
} while ($match);

$interpreted_input = '';
foreach ($this->log as $e) {
$interpreted_input .= $e['match'];
}

if ($interpreted_input !== $input) {
throw new Exception\RuntimeException('Did not reproduce the exact input.');
}

$output = preg_replace('/(<(\w+)[^>]*>)\s*(<\/\2>)/', '\\1\\3', $output);

foreach ($this->temporary_replacements_script as $i => $original) {
$output = str_replace('<script>' . ($i + 1) . '</script>', $original, $output);
}

foreach ($this->temporary_replacements_inline as $i => $original) {
$output = str_replace('ᐃ' . ($i + 1) . 'ᐃ', $original, $output);
}

return trim($output);
}

/**
* Debugging utility. Get log for the last indent operation.
*
* @return array
*/
public function getLog () {
return $this->log;
}
}
30 changes: 23 additions & 7 deletions themes/admin/views/setting/technical.php
Expand Up @@ -187,8 +187,8 @@


</div>
</form>

</form>

</div>

Expand Down Expand Up @@ -741,19 +741,35 @@
</div>

<!-- Compress HTML Output -->
<h3 class="toggler"><?php echo lang('ionize_title_compress_html_output'); ?></h3>
<h3 class="toggler"><?php echo lang('ionize_title_html_output'); ?></h3>

<div class="element">

<form name="compressHtmlOutputForm" id="compressHtmlOutputForm" method="post" action="<?php echo admin_url(); ?>setting/save_compress_html_output" class="mb20">
<form name="compressHtmlOutputForm" id="compressHtmlOutputForm" method="post" action="<?php echo admin_url(); ?>setting/save_html_output" class="mb20">

<!-- Maintenance ? -->
<dl>
<dt>
<label for="default_html_output" title="<?php echo lang('ionize_label_default_html_output_help'); ?>"><?php echo lang('ionize_label_default_html_output'); ?></label>
</dt>
<dd>
<input <?php if (config_item('compress_html_output') == '0' && config_item('beautify_html_output') == '0'):?>checked="checked"<?php endif;?> type="radio" name="html_output" id="default_html_output" value="0" />
</dd>
</dl>
<dl>
<dt>
<label for="compress_html_output" title="<?php echo lang('ionize_label_compress_html_output_help'); ?>"><?php echo lang('ionize_label_compress_html_output'); ?></label>
</dt>
<dd>
<input class="inputcheckbox" <?php if (config_item('compress_html_output') == '1'):?>checked="checked"<?php endif;?> type="checkbox" name="compress_html_output" id="compress_html_output" value="1" />
<input <?php if (config_item('compress_html_output') == '1'):?>checked="checked"<?php endif;?> type="radio" name="html_output" id="compress_html_output" value="1" />
</dd>
</dl>
<dl>
<dt>
<label for="beautify_html_output" title="<?php echo lang('ionize_label_beautify_html_output_help'); ?>"><?php echo lang('ionize_label_beautify_html_output'); ?></label>
</dt>
<dd>
<input <?php if (config_item('beautify_html_output') == '1'):?>checked="checked"<?php endif;?> type="radio" name="html_output" id="beautify_html_output" value="2" />
</dd>
</dl>

Expand Down Expand Up @@ -797,7 +813,7 @@
ION.setFormSubmit('emailForm', 'submit_email', 'setting/save_emails_settings/true');
ION.setFormSubmit('cacheForm', 'submit_cache', 'setting/save_cache');
ION.setFormSubmit('maintenanceForm', 'submit_maintenance', 'setting/save_maintenance');
ION.setFormSubmit('compressHtmlOutputForm', 'submit_compress_html_output', 'setting/save_compress_html_output');
ION.setFormSubmit('compressHtmlOutputForm', 'submit_compress_html_output', 'setting/save_html_output');
ION.setFormSubmit('settingsMediasForm', 'settingsMediasFormSubmit', 'setting/save_medias');
ION.setFormSubmit('articleSettingsForm', 'articleSettingsFormSubmit', 'setting/save_article');
ION.setFormSubmit('keysSettingsForm', 'keysSettingsFormSubmit', 'setting/save_keys');
Expand All @@ -814,7 +830,7 @@ function()
},
Lang.get('ionize_confirm_change_admin_url')
);

$('antispamRefresh').addEvent('click', function(e)
{
e.stop();
Expand Down

0 comments on commit 302fb16

Please sign in to comment.