Developer-Dashboard
view release on metacpan or search on metacpan
lib/Developer/Dashboard/PageDocument.pm view on Meta::CPAN
return "{\n " . join( ",\n ", map { sprintf "%s => %s", $_, _legacy_value( $value->{$_} ) } sort keys %$value ) . "\n}";
}
return $value =~ /\A-?\d+(?:\.\d+)?\z/ ? $value : "'" . _legacy_quote($value) . "'";
}
# _legacy_quote($text)
# Escapes a scalar string for older single-quoted stash serialization.
# Input: text string.
# Output: escaped string.
sub _legacy_quote {
my ($text) = @_;
$text =~ s/\\/\\\\/g;
$text =~ s/'/\\'/g;
return $text;
}
# _template_value($path, $context)
# Resolves a simple dot path from template context for placeholder expansion.
# Input: placeholder path string and context hash reference.
# Output: scalar string.
sub _template_value {
my ( $path, $context ) = @_;
my @parts = grep { defined && $_ ne '' } split /\./, _trim($path);
my $value = $context;
for my $part (@parts) {
return '' if ref($value) ne 'HASH' || !exists $value->{$part};
$value = $value->{$part};
}
return '' if !defined $value || ref($value);
return $value;
}
# _legacy_bootstrap()
# Returns the older client bootstrap helpers used by old bookmark pages.
# Input: none.
# Output: JavaScript bootstrap string.
sub _legacy_bootstrap {
return <<'JS';
<script>
function set_chain_value(obj, path, value) {
let keys = (path || '').split('.');
let current = obj;
for (let i = 0; i < keys.length - 1; i++) {
if (!current[keys[i]]) current[keys[i]] = {};
current = current[keys[i]];
}
current[keys[keys.length - 1]] = value;
}
function dashboard_ajax_singleton_cleanup(name) {
if (!name) return;
if (!window.__dashboardAjaxSingletons) window.__dashboardAjaxSingletons = {};
if (window.__dashboardAjaxSingletons[name]) return;
window.__dashboardAjaxSingletons[name] = true;
window.addEventListener('pagehide', function() {
let url = '/ajax/singleton/stop?singleton=' + encodeURIComponent(name);
if (navigator.sendBeacon) {
navigator.sendBeacon(url, '');
return;
}
if (window.fetch) {
fetch(url, { method: 'POST', keepalive: true, credentials: 'same-origin' }).catch(function () {});
}
});
}
function dashboard_target_nodes(target) {
if (!target) return [];
if (typeof target === 'string') return Array.prototype.slice.call(document.querySelectorAll(target));
if (target instanceof Element) return [target];
if (target.length && typeof target !== 'string') return Array.prototype.slice.call(target);
return [];
}
function dashboard_render_value(value, options, formatter) {
let rendered = value;
if (options && options.type === 'json' && typeof value === 'string' && value !== '') {
try {
rendered = JSON.parse(value);
} catch (error) {
rendered = null;
}
}
if (typeof formatter === 'function') return formatter(rendered);
if (rendered === null || typeof rendered === 'undefined') return '';
if (typeof rendered === 'object') return JSON.stringify(rendered);
return String(rendered);
}
function dashboard_write_target(target, value, options, formatter) {
let nodes = dashboard_target_nodes(target);
let rendered = dashboard_render_value(value, options || {}, formatter);
nodes.forEach(function(node) {
if (options && options.type === 'html') {
node.innerHTML = rendered;
return;
}
if (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA') {
node.value = rendered;
return;
}
node.textContent = rendered;
});
return rendered;
}
function fetch_value(url, target, options, formatter) {
if (!url || !window.fetch) return Promise.resolve('');
let settings = Object.assign({ credentials: 'same-origin' }, (options && options.fetch) || {});
return window.fetch(url, settings).then(function(response) {
if (!response.ok) throw new Error('Request failed with status ' + response.status);
if (options && options.type === 'json') return response.text();
return response.text();
}).then(function(value) {
return dashboard_write_target(target, value, options || {}, formatter);
});
}
function dashboard_stream_settings(options) {
let fetchOptions = (options && options.fetch) || {};
let method = fetchOptions.method || options.method || 'GET';
let body = typeof fetchOptions.body !== 'undefined' ? fetchOptions.body : (typeof options.body !== 'undefined' ? options.body : null);
let headers = fetchOptions.headers || options.headers || {};
let credentials = fetchOptions.credentials || options.credentials || 'same-origin';
return {
method: method,
body: body,
( run in 0.551 second using v1.01-cache-2.11-cpan-39bf76dae61 )