Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge

This commit is contained in:
zotlabs 2017-03-05 11:02:19 -08:00
commit 384db9d10d
22 changed files with 5259 additions and 4768 deletions

View File

@ -29,7 +29,8 @@
"ext-xml" : "*",
"ext-openssl" : "*",
"sabre/dav" : "~3.2",
"michelf/php-markdown" : "^1.7"
"michelf/php-markdown" : "^1.7",
"pixel418/markdownify": "^2.2"
},
"require-dev" : {
"php" : ">=5.6",

58
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "4b24468c1f8babe7c8804fba8ee602f7",
"content-hash": "c0cafbf9fd702be588f6b392b9742cb6",
"packages": [
{
"name": "michelf/php-markdown",
@ -57,6 +57,62 @@
],
"time": "2016-10-29T18:58:20+00:00"
},
{
"name": "pixel418/markdownify",
"version": "v2.2.1",
"source": {
"type": "git",
"url": "https://github.com/Elephant418/Markdownify.git",
"reference": "0160677f04c784550dd10fd72fdf3994967db848"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Elephant418/Markdownify/zipball/0160677f04c784550dd10fd72fdf3994967db848",
"reference": "0160677f04c784550dd10fd72fdf3994967db848",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
},
"type": "lib",
"autoload": {
"psr-4": {
"Markdownify\\": "src",
"Test\\Markdownify\\": "test"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Peter Kruithof",
"email": "pkruithof@gmail.com",
"homepage": "http://pkruithof.tumblr.com/"
},
{
"name": "Milian Wolff",
"email": "mail@milianw.de",
"homepage": "http://milianw.de"
},
{
"name": "Thomas Zilliox",
"email": "hello@tzi.fr",
"homepage": "http://tzi.fr"
}
],
"description": "The HTML to Markdown converter for PHP ",
"homepage": "https://github.com/elephant418/Markdownify",
"keywords": [
"markdown",
"markdownify"
],
"time": "2016-09-21T13:01:43+00:00"
},
{
"name": "psr/log",
"version": "1.0.2",

View File

@ -5,12 +5,12 @@
*/
use Michelf\MarkdownExtra;
use Markdownify\Converter;
require_once("include/oembed.php");
require_once("include/event.php");
require_once("include/html2bbcode.php");
require_once("include/bbcode.php");
require_once("library/markdownify/markdownify.php");
function get_bb_tag_pos($s, $name, $occurance = 1) {
@ -367,7 +367,6 @@ function bb2diaspora_itemwallwall(&$item,$uplink = false) {
function bb2diaspora_itembody($item, $force_update = false, $have_channel = false, $uplink = false) {
if(! get_iconfig($item,'diaspora','fields')) {
$force_update = true;
}
@ -454,7 +453,7 @@ function bb2diaspora_itembody($item, $force_update = false, $have_channel = fals
return html_entity_decode($body);
}
function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
function bb2diaspora($Text, $preserve_nl = false, $fordiaspora = true) {
// Re-enabling the converter again.
// The bbcode parser now handles youtube-links (and the other stuff) correctly.
@ -496,11 +495,10 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
$Text = str_replace(array('<','>','&'),array('&_lt_;','&_gt_;','&_amp_;'),$Text);
// Now convert HTML to Markdown
$md = new Markdownify(false, false, false);
$md = new Converter(Converter::LINK_AFTER_CONTENT, false, false);
$Text = $md->parseString($Text);
// It also adds backslashes to our attempt at getting around the html entity preservation for some weird reason.
$Text = str_replace(array('&\\_lt\\_;','&\\_gt\\_;','&\\_amp\\_;'),array('<','>','&'),$Text);
@ -522,7 +520,7 @@ function bb2diaspora($Text,$preserve_nl = false, $fordiaspora = true) {
$Text = trim($Text);
call_hooks('bb2diaspora',$Text);
call_hooks('bb2diaspora', $Text);
return $Text;
}

View File

@ -1,29 +0,0 @@
Markdownify
===========
* handle non-markdownifiable lists (i.e. `<ul><li id="foobar">asdf</li></ul>`)
* organize methods better (i.e. flushlinebreaks & setlinebreaks close to each other)
* take a look at function names etc.
* is the new (in rev. 93) lastclosedtag property needed?
* word wrapping (some work is done but it's still very buggy)
Markdownify Extra
=================
* handle table alignment with KEEP_HTML=false
* handle tables without headings when KEEP_HTML=false is set
* handle Markdown inside non-markdownable tags
Implementation Thoughts
=======================
* non-markdownifiable lists and markdown inside non-markdownable tags as well as the current
table implementation could be rewritten by using a rollback mechanism.
example:
<ul><li>asdf</li><li id="foobar">asdf</li></ul>
we come to `<ul>`, know that this might fail and create a snapshot of our current parser
we keep on parsing and when we reach `<li id="foobar">` we gotta rollback and keep this
list in HTML format.

View File

@ -1,51 +0,0 @@
<?php
error_reporting(E_ALL);
if (!empty($_POST['input'])) {
include 'markdownify_extra.php';
if (!isset($_POST['leap'])) {
$leap = MDFY_LINKS_EACH_PARAGRAPH;
} else {
$leap = $_POST['leap'];
}
if (!isset($_POST['keepHTML'])) {
$keephtml = MDFY_KEEPHTML;
} else {
$keephtml = $_POST['keepHTML'];
}
if (!empty($_POST['extra'])) {
$md = new Markdownify_Extra($leap, MDFY_BODYWIDTH, $keephtml);
} else {
$md = new Markdownify($leap, MDFY_BODYWIDTH, $keephtml);
}
if (ini_get('magic_quotes_gpc')) {
$_POST['input'] = stripslashes($_POST['input']);
}
$output = $md->parseString($_POST['input']);
} else {
$_POST['input'] = '';
}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>HTML to Markdown Converter</title>
</head>
<body>
<?php if (empty($_POST['input'])): ?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
<fieldset>
<legend>HTML Input</legend>
<textarea style="width:100%;" cols="85" rows="40" name="input"><?php echo htmlspecialchars($_POST['input'], ENT_NOQUOTES, 'UTF-8'); ?></textarea>
</fieldset>
<label for="extra">Markdownify Extra: <input name="extra" checked="checked" id="extra" type="checkbox" value="1" /></label>
<label for="leap">Links after each block elem: <input name="leap" id="leap" type="checkbox" value="1" /></label>
<label for="keepHTML">keep HTML: <input name="keepHTML" id="keepHTML" type="checkbox" value="1" checked="checked" /></label>
<input type="submit" name="submit" value="submit" />
</form>
<?php else: ?>
<h1 style="text-align:right;"><a href="<?php echo $_SERVER['PHP_SELF']; ?>">BACK</a></h1>
<pre><?php echo htmlspecialchars($output, ENT_NOQUOTES, 'UTF-8'); ?></pre>
<?php endif; ?>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -1,33 +0,0 @@
#!/usr/bin/php
<?php
require dirname(__FILE__) .'/markdownify_extra.php';
function param($name, $default = false) {
if (!in_array('--'.$name, $_SERVER['argv']))
return $default;
reset($_SERVER['argv']);
while (each($_SERVER['argv'])) {
if (current($_SERVER['argv']) == '--'.$name)
break;
}
$value = next($_SERVER['argv']);
if ($value === false || substr($value, 0, 2) == '--')
return true;
else
return $value;
}
$input = stream_get_contents(STDIN);
$linksAfterEachParagraph = param('links');
$bodyWidth = param('width');
$keepHTML = param('html', true);
if (param('no_extra')) {
$parser = new Markdownify($linksAfterEachParagraph, $bodyWidth, $keepHTML);
} else {
$parser = new Markdownify_Extra($linksAfterEachParagraph, $bodyWidth, $keepHTML);
}
echo $parser->parseString($input) ."\n";

View File

@ -1,489 +0,0 @@
<?php
/**
* Class to convert HTML to Markdown with PHP Markdown Extra syntax support.
*
* @version 1.0.0 alpha
* @author Milian Wolff (<mail@milianw.de>, <http://milianw.de>)
* @license LGPL, see LICENSE_LGPL.txt and the summary below
* @copyright (C) 2007 Milian Wolff
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* standard Markdownify class
*/
require_once dirname(__FILE__).'/markdownify.php';
class Markdownify_Extra extends Markdownify {
/**
* table data, including rows with content and the maximum width of each col
*
* @var array
*/
var $table = array();
/**
* current col
*
* @var int
*/
var $col = -1;
/**
* current row
*
* @var int
*/
var $row = 0;
/**
* constructor, see Markdownify::Markdownify() for more information
*/
function Markdownify_Extra($linksAfterEachParagraph = MDFY_LINKS_EACH_PARAGRAPH, $bodyWidth = MDFY_BODYWIDTH, $keepHTML = MDFY_KEEPHTML) {
parent::Markdownify($linksAfterEachParagraph, $bodyWidth, $keepHTML);
### new markdownable tags & attributes
# header ids: # foo {bar}
$this->isMarkdownable['h1']['id'] = 'optional';
$this->isMarkdownable['h2']['id'] = 'optional';
$this->isMarkdownable['h3']['id'] = 'optional';
$this->isMarkdownable['h4']['id'] = 'optional';
$this->isMarkdownable['h5']['id'] = 'optional';
$this->isMarkdownable['h6']['id'] = 'optional';
# tables
$this->isMarkdownable['table'] = array();
$this->isMarkdownable['th'] = array(
'align' => 'optional',
);
$this->isMarkdownable['td'] = array(
'align' => 'optional',
);
$this->isMarkdownable['tr'] = array();
array_push($this->ignore, 'thead');
array_push($this->ignore, 'tbody');
array_push($this->ignore, 'tfoot');
# definition lists
$this->isMarkdownable['dl'] = array();
$this->isMarkdownable['dd'] = array();
$this->isMarkdownable['dt'] = array();
# footnotes
$this->isMarkdownable['fnref'] = array(
'target' => 'required',
);
$this->isMarkdownable['footnotes'] = array();
$this->isMarkdownable['fn'] = array(
'name' => 'required',
);
$this->parser->blockElements['fnref'] = false;
$this->parser->blockElements['fn'] = true;
$this->parser->blockElements['footnotes'] = true;
# abbr
$this->isMarkdownable['abbr'] = array(
'title' => 'required',
);
# build RegEx lookahead to decide wether table can pe parsed or not
$inlineTags = array_keys($this->parser->blockElements, false);
$colContents = '(?:[^<]|<(?:'.implode('|', $inlineTags).'|[^a-z]))+';
$this->tableLookaheadHeader = '{
^\s*(?:<thead\s*>)?\s* # open optional thead
<tr\s*>\s*(?: # start required row with headers
<th(?:\s+align=("|\')(?:left|center|right)\1)?\s*> # header with optional align
\s*'.$colContents.'\s* # contents
</th>\s* # close header
)+</tr> # close row with headers
\s*(?:</thead>)? # close optional thead
}sxi';
$this->tdSubstitute = '\s*'.$colContents.'\s* # contents
</td>\s*';
$this->tableLookaheadBody = '{
\s*(?:<tbody\s*>)?\s* # open optional tbody
(?:<tr\s*>\s* # start row
%s # cols to be substituted
</tr>)+ # close row
\s*(?:</tbody>)? # close optional tbody
\s*</table> # close table
}sxi';
}
/**
* handle header tags (<h1> - <h6>)
*
* @param int $level 1-6
* @return void
*/
function handleHeader($level) {
static $id = null;
if ($this->parser->isStartTag) {
if (isset($this->parser->tagAttributes['id'])) {
$id = $this->parser->tagAttributes['id'];
}
} else {
if (!is_null($id)) {
$this->out(' {#'.$id.'}');
$id = null;
}
}
parent::handleHeader($level);
}
/**
* handle <abbr> tags
*
* @param void
* @return void
*/
function handleTag_abbr() {
if ($this->parser->isStartTag) {
$this->stack();
$this->buffer();
} else {
$tag = $this->unstack();
$tag['text'] = $this->unbuffer();
$add = true;
foreach ($this->stack['abbr'] as $stacked) {
if ($stacked['text'] == $tag['text']) {
/** TODO: differing abbr definitions, i.e. different titles for same text **/
$add = false;
break;
}
}
$this->out($tag['text']);
if ($add) {
array_push($this->stack['abbr'], $tag);
}
}
}
/**
* flush stacked abbr tags
*
* @param void
* @return void
*/
function flushStacked_abbr() {
$out = array();
foreach ($this->stack['abbr'] as $k => $tag) {
if (!isset($tag['unstacked'])) {
array_push($out, ' *['.$tag['text'].']: '.$tag['title']);
$tag['unstacked'] = true;
$this->stack['abbr'][$k] = $tag;
}
}
if (!empty($out)) {
$this->out("\n\n".implode("\n", $out));
}
}
/**
* handle <table> tags
*
* @param void
* @return void
*/
function handleTag_table() {
if ($this->parser->isStartTag) {
# check if upcoming table can be converted
if ($this->keepHTML) {
if (preg_match($this->tableLookaheadHeader, $this->parser->html, $matches)) {
# header seems good, now check body
# get align & number of cols
preg_match_all('#<th(?:\s+align=("|\')(left|right|center)\1)?\s*>#si', $matches[0], $cols);
$regEx = '';
$i = 1;
$aligns = array();
foreach ($cols[2] as $align) {
$align = strtolower($align);
array_push($aligns, $align);
if (empty($align)) {
$align = 'left'; # default value
}
$td = '\s+align=("|\')'.$align.'\\'.$i;
$i++;
if ($align == 'left') {
# look for empty align or left
$td = '(?:'.$td.')?';
}
$td = '<td'.$td.'\s*>';
$regEx .= $td.$this->tdSubstitute;
}
$regEx = sprintf($this->tableLookaheadBody, $regEx);
if (preg_match($regEx, $this->parser->html, $matches, null, strlen($matches[0]))) {
# this is a markdownable table tag!
$this->table = array(
'rows' => array(),
'col_widths' => array(),
'aligns' => $aligns,
);
$this->row = 0;
} else {
# non markdownable table
$this->handleTagToText();
}
} else {
# non markdownable table
$this->handleTagToText();
}
} else {
$this->table = array(
'rows' => array(),
'col_widths' => array(),
'aligns' => array(),
);
$this->row = 0;
}
} else {
# finally build the table in Markdown Extra syntax
$separator = array();
# seperator with correct align identifikators
foreach($this->table['aligns'] as $col => $align) {
if (!$this->keepHTML && !isset($this->table['col_widths'][$col])) {
break;
}
$left = ' ';
$right = ' ';
switch ($align) {
case 'left':
$left = ':';
break;
case 'center':
$right = ':';
$left = ':';
case 'right':
$right = ':';
break;
}
array_push($separator, $left.str_repeat('-', $this->table['col_widths'][$col]).$right);
}
$separator = '|'.implode('|', $separator).'|';
$rows = array();
# add padding
array_walk_recursive($this->table['rows'], array(&$this, 'alignTdContent'));
$header = array_shift($this->table['rows']);
array_push($rows, '| '.implode(' | ', $header).' |');
array_push($rows, $separator);
foreach ($this->table['rows'] as $row) {
array_push($rows, '| '.implode(' | ', $row).' |');
}
$this->out(implode("\n".$this->indent, $rows));
$this->table = array();
$this->setLineBreaks(2);
}
}
/**
* properly pad content so it is aligned as whished
* should be used with array_walk_recursive on $this->table['rows']
*
* @param string &$content
* @param int $col
* @return void
*/
function alignTdContent(&$content, $col) {
switch ($this->table['aligns'][$col]) {
default:
case 'left':
$content .= str_repeat(' ', $this->table['col_widths'][$col] - $this->strlen($content));
break;
case 'right':
$content = str_repeat(' ', $this->table['col_widths'][$col] - $this->strlen($content)).$content;
break;
case 'center':
$paddingNeeded = $this->table['col_widths'][$col] - $this->strlen($content);
$left = floor($paddingNeeded / 2);
$right = $paddingNeeded - $left;
$content = str_repeat(' ', $left).$content.str_repeat(' ', $right);
break;
}
}
/**
* handle <tr> tags
*
* @param void
* @return void
*/
function handleTag_tr() {
if ($this->parser->isStartTag) {
$this->col = -1;
} else {
$this->row++;
}
}
/**
* handle <td> tags
*
* @param void
* @return void
*/
function handleTag_td() {
if ($this->parser->isStartTag) {
$this->col++;
if (!isset($this->table['col_widths'][$this->col])) {
$this->table['col_widths'][$this->col] = 0;
}
$this->buffer();
} else {
$buffer = trim($this->unbuffer());
$this->table['col_widths'][$this->col] = max($this->table['col_widths'][$this->col], $this->strlen($buffer));
$this->table['rows'][$this->row][$this->col] = $buffer;
}
}
/**
* handle <th> tags
*
* @param void
* @return void
*/
function handleTag_th() {
if (!$this->keepHTML && !isset($this->table['rows'][1]) && !isset($this->table['aligns'][$this->col+1])) {
if (isset($this->parser->tagAttributes['align'])) {
$this->table['aligns'][$this->col+1] = $this->parser->tagAttributes['align'];
} else {
$this->table['aligns'][$this->col+1] = '';
}
}
$this->handleTag_td();
}
/**
* handle <dl> tags
*
* @param void
* @return void
*/
function handleTag_dl() {
if (!$this->parser->isStartTag) {
$this->setLineBreaks(2);
}
}
/**
* handle <dt> tags
*
* @param void
* @return void
**/
function handleTag_dt() {
if (!$this->parser->isStartTag) {
$this->setLineBreaks(1);
}
}
/**
* handle <dd> tags
*
* @param void
* @return void
*/
function handleTag_dd() {
if ($this->parser->isStartTag) {
if (substr(ltrim($this->parser->html), 0, 3) == '<p>') {
# next comes a paragraph, so we'll need an extra line
$this->out("\n".$this->indent);
} elseif (substr($this->output, -2) == "\n\n") {
$this->output = substr($this->output, 0, -1);
}
$this->out(': ');
$this->indent(' ', false);
} else {
# lookahead for next dt
if (substr(ltrim($this->parser->html), 0, 4) == '<dt>') {
$this->setLineBreaks(2);
} else {
$this->setLineBreaks(1);
}
$this->indent(' ');
}
}
/**
* handle <fnref /> tags (custom footnote references, see markdownify_extra::parseString())
*
* @param void
* @return void
*/
function handleTag_fnref() {
$this->out('[^'.$this->parser->tagAttributes['target'].']');
}
/**
* handle <fn> tags (custom footnotes, see markdownify_extra::parseString()
* and markdownify_extra::_makeFootnotes())
*
* @param void
* @return void
*/
function handleTag_fn() {
if ($this->parser->isStartTag) {
$this->out('[^'.$this->parser->tagAttributes['name'].']:');
$this->setLineBreaks(1);
} else {
$this->setLineBreaks(2);
}
$this->indent(' ');
}
/**
* handle <footnotes> tag (custom footnotes, see markdownify_extra::parseString()
* and markdownify_extra::_makeFootnotes())
*
* @param void
* @return void
*/
function handleTag_footnotes() {
if (!$this->parser->isStartTag) {
$this->setLineBreaks(2);
}
}
/**
* parse a HTML string, clean up footnotes prior
*
* @param string $HTML input
* @return string Markdown formatted output
*/
function parseString($html) {
/** TODO: custom markdown-extra options, e.g. titles & classes **/
# <sup id="fnref:..."><a href"#fn..." rel="footnote">...</a></sup>
# => <fnref target="..." />
$html = preg_replace('@<sup id="fnref:([^"]+)">\s*<a href="#fn:\1" rel="footnote">\s*\d+\s*</a>\s*</sup>@Us', '<fnref target="$1" />', $html);
# <div class="footnotes">
# <hr />
# <ol>
#
# <li id="fn:...">...</li>
# ...
#
# </ol>
# </div>
# =>
# <footnotes>
# <fn name="...">...</fn>
# ...
# </footnotes>
$html = preg_replace_callback('#<div class="footnotes">\s*<hr />\s*<ol>\s*(.+)\s*</ol>\s*</div>#Us', array(&$this, '_makeFootnotes'), $html);
return parent::parseString($html);
}
/**
* replace HTML representation of footnotes with something more easily parsable
*
* @note this is a callback to be used in parseString()
*
* @param array $matches
* @return string
*/
function _makeFootnotes($matches) {
# <li id="fn:1">
# ...
# <a href="#fnref:block" rev="footnote">&#8617;</a></p>
# </li>
# => <fn name="1">...</fn>
# remove footnote link
$fns = preg_replace('@\s*(&#160;\s*)?<a href="#fnref:[^"]+" rev="footnote"[^>]*>&#8617;</a>\s*@s', '', $matches[1]);
# remove empty paragraph
$fns = preg_replace('@<p>\s*</p>@s', '', $fns);
# <li id="fn:1">...</li> -> <footnote nr="1">...</footnote>
$fns = str_replace('<li id="fn:', '<fn name="', $fns);
$fns = '<footnotes>'.$fns.'</footnotes>';
return preg_replace('#</li>\s*(?=(?:<fn|</footnotes>))#s', '</fn>$1', $fns);
}
}

View File

@ -1,618 +0,0 @@
<?php
/**
* parseHTML is a HTML parser which works with PHP 4 and above.
* It tries to handle invalid HTML to some degree.
*
* @version 1.0 beta
* @author Milian Wolff (mail@milianw.de, http://milianw.de)
* @license LGPL, see LICENSE_LGPL.txt and the summary below
* @copyright (C) 2007 Milian Wolff
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
class parseHTML {
/**
* tags which are always empty (<br /> etc.)
*
* @var array<string>
*/
var $emptyTags = array(
'br',
'hr',
'input',
'img',
'area',
'link',
'meta',
'param',
);
/**
* tags with preformatted text
* whitespaces wont be touched in them
*
* @var array<string>
*/
var $preformattedTags = array(
'script',
'style',
'pre',
'code',
);
/**
* supress HTML tags inside preformatted tags (see above)
*
* @var bool
*/
var $noTagsInCode = false;
/**
* html to be parsed
*
* @var string
*/
var $html = '';
/**
* node type:
*
* - tag (see isStartTag)
* - text (includes cdata)
* - comment
* - doctype
* - pi (processing instruction)
*
* @var string
*/
var $nodeType = '';
/**
* current node content, i.e. either a
* simple string (text node), or something like
* <tag attrib="value"...>
*
* @var string
*/
var $node = '';
/**
* wether current node is an opening tag (<a>) or not (</a>)
* set to NULL if current node is not a tag
* NOTE: empty tags (<br />) set this to true as well!
*
* @var bool | null
*/
var $isStartTag = null;
/**
* wether current node is an empty tag (<br />) or not (<a></a>)
*
* @var bool | null
*/
var $isEmptyTag = null;
/**
* tag name
*
* @var string | null
*/
var $tagName = '';
/**
* attributes of current tag
*
* @var array (attribName=>value) | null
*/
var $tagAttributes = null;
/**
* wether the current tag is a block element
*
* @var bool | null
*/
var $isBlockElement = null;
/**
* keep whitespace
*
* @var int
*/
var $keepWhitespace = 0;
/**
* list of open tags
* count this to get current depth
*
* @var array
*/
var $openTags = array();
/**
* list of block elements
*
* @var array
* TODO: what shall we do with <del> and <ins> ?!
*/
var $blockElements = array (
# tag name => <bool> is block
# block elements
'address' => true,
'blockquote' => true,
'center' => true,
'del' => true,
'dir' => true,
'div' => true,
'dl' => true,
'fieldset' => true,
'form' => true,
'h1' => true,
'h2' => true,
'h3' => true,
'h4' => true,
'h5' => true,
'h6' => true,
'hr' => true,
'ins' => true,
'isindex' => true,
'menu' => true,
'noframes' => true,
'noscript' => true,
'ol' => true,
'p' => true,
'pre' => true,
'table' => true,
'ul' => true,
# set table elements and list items to block as well
'thead' => true,
'tbody' => true,
'tfoot' => true,
'td' => true,
'tr' => true,
'th' => true,
'li' => true,
'dd' => true,
'dt' => true,
# header items and html / body as well
'html' => true,
'body' => true,
'head' => true,
'meta' => true,
'link' => true,
'style' => true,
'title' => true,
# unfancy media tags, when indented should be rendered as block
'map' => true,
'object' => true,
'param' => true,
'embed' => true,
'area' => true,
# inline elements
'a' => false,
'abbr' => false,
'acronym' => false,
'applet' => false,
'b' => false,
'basefont' => false,
'bdo' => false,
'big' => false,
'br' => false,
'button' => false,
'cite' => false,
'code' => false,
'del' => false,
'dfn' => false,
'em' => false,
'font' => false,
'i' => false,
'img' => false,
'ins' => false,
'input' => false,
'iframe' => false,
'kbd' => false,
'label' => false,
'q' => false,
'samp' => false,
'script' => false,
'select' => false,
'small' => false,
'span' => false,
'strong' => false,
'sub' => false,
'sup' => false,
'textarea' => false,
'tt' => false,
'var' => false,
);
/**
* get next node, set $this->html prior!
*
* @param void
* @return bool
*/
function nextNode() {
if (empty($this->html)) {
# we are done with parsing the html string
return false;
}
static $skipWhitespace = true;
if ($this->isStartTag && !$this->isEmptyTag) {
array_push($this->openTags, $this->tagName);
if (in_array($this->tagName, $this->preformattedTags)) {
# dont truncate whitespaces for <code> or <pre> contents
$this->keepWhitespace++;
}
}
if ($this->html[0] == '<') {
$token = substr($this->html, 0, 9);
if (substr($token, 0, 2) == '<?') {
# xml prolog or other pi's
/** TODO **/
#trigger_error('this might need some work', E_USER_NOTICE);
$pos = strpos($this->html, '>');
$this->setNode('pi', $pos + 1);
return true;
}
if (substr($token, 0, 4) == '<!--') {
# comment
$pos = strpos($this->html, '-->');
if ($pos === false) {
# could not find a closing -->, use next gt instead
# this is firefox' behaviour
$pos = strpos($this->html, '>') + 1;
} else {
$pos += 3;
}
$this->setNode('comment', $pos);
$skipWhitespace = true;
return true;
}
if ($token == '<!DOCTYPE') {
# doctype
$this->setNode('doctype', strpos($this->html, '>')+1);
$skipWhitespace = true;
return true;
}
if ($token == '<![CDATA[') {
# cdata, use text node
# remove leading <![CDATA[
$this->html = substr($this->html, 9);
$this->setNode('text', strpos($this->html, ']]>')+3);
# remove trailing ]]> and trim
$this->node = substr($this->node, 0, -3);
$this->handleWhitespaces();
$skipWhitespace = true;
return true;
}
if ($this->parseTag()) {
# seems to be a tag
# handle whitespaces
if ($this->isBlockElement) {
$skipWhitespace = true;
} else {
$skipWhitespace = false;
}
return true;
}
}
if ($this->keepWhitespace) {
$skipWhitespace = false;
}
# when we get here it seems to be a text node
$pos = strpos($this->html, '<');
if ($pos === false) {
$pos = strlen($this->html);
}
$this->setNode('text', $pos);
$this->handleWhitespaces();
if ($skipWhitespace && $this->node == ' ') {
return $this->nextNode();
}
$skipWhitespace = false;
return true;
}
/**
* parse tag, set tag name and attributes, see if it's a closing tag and so forth...
*
* @param void
* @return bool
*/
function parseTag() {
static $a_ord, $z_ord, $special_ords;
if (!isset($a_ord)) {
$a_ord = ord('a');
$z_ord = ord('z');
$special_ords = array(
ord(':'), // for xml:lang
ord('-'), // for http-equiv
);
}
$tagName = '';
$pos = 1;
$isStartTag = $this->html[$pos] != '/';
if (!$isStartTag) {
$pos++;
}
# get tagName
while (isset($this->html[$pos])) {
$pos_ord = ord(strtolower($this->html[$pos]));
if (($pos_ord >= $a_ord && $pos_ord <= $z_ord) || (!empty($tagName) && is_numeric($this->html[$pos]))) {
$tagName .= $this->html[$pos];
$pos++;
} else {
$pos--;
break;
}
}
$tagName = strtolower($tagName);
if (empty($tagName) || !isset($this->blockElements[$tagName])) {
# something went wrong => invalid tag
$this->invalidTag();
return false;
}
if ($this->noTagsInCode && end($this->openTags) == 'code' && !($tagName == 'code' && !$isStartTag)) {
# we supress all HTML tags inside code tags
$this->invalidTag();
return false;
}
# get tag attributes
/** TODO: in html 4 attributes do not need to be quoted **/
$isEmptyTag = false;
$attributes = array();
$currAttrib = '';
while (isset($this->html[$pos+1])) {
$pos++;
# close tag
if ($this->html[$pos] == '>' || $this->html[$pos].$this->html[$pos+1] == '/>') {
if ($this->html[$pos] == '/') {
$isEmptyTag = true;
$pos++;
}
break;
}
$pos_ord = ord(strtolower($this->html[$pos]));
if ( ($pos_ord >= $a_ord && $pos_ord <= $z_ord) || in_array($pos_ord, $special_ords)) {
# attribute name
$currAttrib .= $this->html[$pos];
} elseif (in_array($this->html[$pos], array(' ', "\t", "\n"))) {
# drop whitespace
} elseif (in_array($this->html[$pos].$this->html[$pos+1], array('="', "='"))) {
# get attribute value
$pos++;
$await = $this->html[$pos]; # single or double quote
$pos++;
$value = '';
while (isset($this->html[$pos]) && $this->html[$pos] != $await) {
$value .= $this->html[$pos];
$pos++;
}
$attributes[$currAttrib] = $value;
$currAttrib = '';
} else {
$this->invalidTag();
return false;
}
}
if ($this->html[$pos] != '>') {
$this->invalidTag();
return false;
}
if (!empty($currAttrib)) {
# html 4 allows something like <option selected> instead of <option selected="selected">
$attributes[$currAttrib] = $currAttrib;
}
if (!$isStartTag) {
if (!empty($attributes) || $tagName != end($this->openTags)) {
# end tags must not contain any attributes
# or maybe we did not expect a different tag to be closed
$this->invalidTag();
return false;
}
array_pop($this->openTags);
if (in_array($tagName, $this->preformattedTags)) {
$this->keepWhitespace--;
}
}
$pos++;
$this->node = substr($this->html, 0, $pos);
$this->html = substr($this->html, $pos);
$this->tagName = $tagName;
$this->tagAttributes = $attributes;
$this->isStartTag = $isStartTag;
$this->isEmptyTag = $isEmptyTag || in_array($tagName, $this->emptyTags);
if ($this->isEmptyTag) {
# might be not well formed
$this->node = preg_replace('# */? *>$#', ' />', $this->node);
}
$this->nodeType = 'tag';
$this->isBlockElement = $this->blockElements[$tagName];
return true;
}
/**
* handle invalid tags
*
* @param void
* @return void
*/
function invalidTag() {
$this->html = substr_replace($this->html, '&lt;', 0, 1);
}
/**
* update all vars and make $this->html shorter
*
* @param string $type see description for $this->nodeType
* @param int $pos to which position shall we cut?
* @return void
*/
function setNode($type, $pos) {
if ($this->nodeType == 'tag') {
# set tag specific vars to null
# $type == tag should not be called here
# see this::parseTag() for more
$this->tagName = null;
$this->tagAttributes = null;
$this->isStartTag = null;
$this->isEmptyTag = null;
$this->isBlockElement = null;
}
$this->nodeType = $type;
$this->node = substr($this->html, 0, $pos);
$this->html = substr($this->html, $pos);
}
/**
* check if $this->html begins with $str
*
* @param string $str
* @return bool
*/
function match($str) {
return substr($this->html, 0, strlen($str)) == $str;
}
/**
* truncate whitespaces
*
* @param void
* @return void
*/
function handleWhitespaces() {
if ($this->keepWhitespace) {
# <pre> or <code> before...
return;
}
# truncate multiple whitespaces to a single one
$this->node = preg_replace('#\s+#s', ' ', $this->node);
}
/**
* normalize self::node
*
* @param void
* @return void
*/
function normalizeNode() {
$this->node = '<';
if (!$this->isStartTag) {
$this->node .= '/'.$this->tagName.'>';
return;
}
$this->node .= $this->tagName;
foreach ($this->tagAttributes as $name => $value) {
$this->node .= ' '.$name.'="'.str_replace('"', '&quot;', $value).'"';
}
if ($this->isEmptyTag) {
$this->node .= ' /';
}
$this->node .= '>';
}
}
/**
* indent a HTML string properly
*
* @param string $html
* @param string $indent optional
* @return string
*/
function indentHTML($html, $indent = " ", $noTagsInCode = false) {
$parser = new parseHTML;
$parser->noTagsInCode = $noTagsInCode;
$parser->html = $html;
$html = '';
$last = true; # last tag was block elem
$indent_a = array();
while($parser->nextNode()) {
if ($parser->nodeType == 'tag') {
$parser->normalizeNode();
}
if ($parser->nodeType == 'tag' && $parser->isBlockElement) {
$isPreOrCode = in_array($parser->tagName, array('code', 'pre'));
if (!$parser->keepWhitespace && !$last && !$isPreOrCode) {
$html = rtrim($html)."\n";
}
if ($parser->isStartTag) {
$html .= implode($indent_a);
if (!$parser->isEmptyTag) {
array_push($indent_a, $indent);
}
} else {
array_pop($indent_a);
if (!$isPreOrCode) {
$html .= implode($indent_a);
}
}
$html .= $parser->node;
if (!$parser->keepWhitespace && !($isPreOrCode && $parser->isStartTag)) {
$html .= "\n";
}
$last = true;
} else {
if ($parser->nodeType == 'tag' && $parser->tagName == 'br') {
$html .= $parser->node."\n";
$last = true;
continue;
} elseif ($last && !$parser->keepWhitespace) {
$html .= implode($indent_a);
$parser->node = ltrim($parser->node);
}
$html .= $parser->node;
if (in_array($parser->nodeType, array('comment', 'pi', 'doctype'))) {
$html .= "\n";
} else {
$last = false;
}
}
}
return $html;
}
/*
# testcase / example
error_reporting(E_ALL);
$html = '<p>Simple block on one line:</p>
<div>foo</div>
<p>And nested without indentation:</p>
<div>
<div>
<div>
foo
</div>
<div style=">"/>
</div>
<div>bar</div>
</div>
<p>And with attributes:</p>
<div>
<div id="foo">
</div>
</div>
<p>This was broken in 1.0.2b7:</p>
<div class="inlinepage">
<div class="toggleableend">
foo
</div>
</div>';
#$html = '<a href="asdfasdf" title=\'asdf\' foo="bar">asdf</a>';
echo indentHTML($html);
die();
*/

View File

@ -7,6 +7,9 @@ $baseDir = dirname($vendorDir);
return array(
'Hubzilla\\Import\\Import' => $baseDir . '/include/Import/Importer.php',
'Markdownify\\Converter' => $vendorDir . '/pixel418/markdownify/src/Converter.php',
'Markdownify\\ConverterExtra' => $vendorDir . '/pixel418/markdownify/src/ConverterExtra.php',
'Markdownify\\Parser' => $vendorDir . '/pixel418/markdownify/src/Parser.php',
'Michelf\\Markdown' => $vendorDir . '/michelf/php-markdown/Michelf/Markdown.php',
'Michelf\\MarkdownExtra' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownExtra.php',
'Michelf\\MarkdownInterface' => $vendorDir . '/michelf/php-markdown/Michelf/MarkdownInterface.php',
@ -18,6 +21,8 @@ return array(
'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php',
'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php',
'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php',
'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Sabre\\CalDAV\\Backend\\AbstractBackend' => $vendorDir . '/sabre/dav/lib/CalDAV/Backend/AbstractBackend.php',
'Sabre\\CalDAV\\Backend\\BackendInterface' => $vendorDir . '/sabre/dav/lib/CalDAV/Backend/BackendInterface.php',
'Sabre\\CalDAV\\Backend\\NotificationSupport' => $vendorDir . '/sabre/dav/lib/CalDAV/Backend/NotificationSupport.php',
@ -268,7 +273,6 @@ return array(
'Sabre\\HTTP\\URLUtil' => $vendorDir . '/sabre/http/lib/URLUtil.php',
'Sabre\\HTTP\\Util' => $vendorDir . '/sabre/http/lib/Util.php',
'Sabre\\HTTP\\Version' => $vendorDir . '/sabre/http/lib/Version.php',
'Sabre\\Uri\\InvalidUriException' => $vendorDir . '/sabre/uri/lib/InvalidUriException.php',
'Sabre\\Uri\\Version' => $vendorDir . '/sabre/uri/lib/Version.php',
'Sabre\\VObject\\BirthdayCalendarGenerator' => $vendorDir . '/sabre/vobject/lib/BirthdayCalendarGenerator.php',
'Sabre\\VObject\\Cli' => $vendorDir . '/sabre/vobject/lib/Cli.php',
@ -357,6 +361,9 @@ return array(
'Sabre\\Xml\\Writer' => $vendorDir . '/sabre/xml/lib/Writer.php',
'Sabre\\Xml\\XmlDeserializable' => $vendorDir . '/sabre/xml/lib/XmlDeserializable.php',
'Sabre\\Xml\\XmlSerializable' => $vendorDir . '/sabre/xml/lib/XmlSerializable.php',
'Test\\Markdownify\\ConverterExtraTest' => $vendorDir . '/pixel418/markdownify/test/ConverterExtraTest.php',
'Test\\Markdownify\\ConverterTest' => $vendorDir . '/pixel418/markdownify/test/ConverterTest.php',
'Test\\Markdownify\\ConverterTestCase' => $vendorDir . '/pixel418/markdownify/test/ConverterTestCase.php',
'Zotlabs\\Access\\AccessList' => $baseDir . '/Zotlabs/Access/AccessList.php',
'Zotlabs\\Access\\PermissionLimits' => $baseDir . '/Zotlabs/Access/PermissionLimits.php',
'Zotlabs\\Access\\PermissionRoles' => $baseDir . '/Zotlabs/Access/PermissionRoles.php',

View File

@ -7,6 +7,7 @@ $baseDir = dirname($vendorDir);
return array(
'Zotlabs\\' => array($baseDir . '/Zotlabs'),
'Test\\Markdownify\\' => array($vendorDir . '/pixel418/markdownify/test'),
'Sabre\\Xml\\' => array($vendorDir . '/sabre/xml/lib'),
'Sabre\\VObject\\' => array($vendorDir . '/sabre/vobject/lib'),
'Sabre\\Uri\\' => array($vendorDir . '/sabre/uri/lib'),
@ -17,5 +18,6 @@ return array(
'Sabre\\CardDAV\\' => array($vendorDir . '/sabre/dav/lib/CardDAV'),
'Sabre\\CalDAV\\' => array($vendorDir . '/sabre/dav/lib/CalDAV'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Markdownify\\' => array($vendorDir . '/pixel418/markdownify/src'),
'Hubzilla\\' => array($baseDir . '/include'),
);

View File

@ -21,6 +21,10 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
array (
'Zotlabs\\' => 8,
),
'T' =>
array (
'Test\\Markdownify\\' => 17,
),
'S' =>
array (
'Sabre\\Xml\\' => 10,
@ -37,6 +41,10 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
array (
'Psr\\Log\\' => 8,
),
'M' =>
array (
'Markdownify\\' => 12,
),
'H' =>
array (
'Hubzilla\\' => 9,
@ -48,6 +56,10 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
array (
0 => __DIR__ . '/../..' . '/Zotlabs',
),
'Test\\Markdownify\\' =>
array (
0 => __DIR__ . '/..' . '/pixel418/markdownify/test',
),
'Sabre\\Xml\\' =>
array (
0 => __DIR__ . '/..' . '/sabre/xml/lib',
@ -88,6 +100,10 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
array (
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
),
'Markdownify\\' =>
array (
0 => __DIR__ . '/..' . '/pixel418/markdownify/src',
),
'Hubzilla\\' =>
array (
0 => __DIR__ . '/../..' . '/include',
@ -106,6 +122,9 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
public static $classMap = array (
'Hubzilla\\Import\\Import' => __DIR__ . '/../..' . '/include/Import/Importer.php',
'Markdownify\\Converter' => __DIR__ . '/..' . '/pixel418/markdownify/src/Converter.php',
'Markdownify\\ConverterExtra' => __DIR__ . '/..' . '/pixel418/markdownify/src/ConverterExtra.php',
'Markdownify\\Parser' => __DIR__ . '/..' . '/pixel418/markdownify/src/Parser.php',
'Michelf\\Markdown' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/Markdown.php',
'Michelf\\MarkdownExtra' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownExtra.php',
'Michelf\\MarkdownInterface' => __DIR__ . '/..' . '/michelf/php-markdown/Michelf/MarkdownInterface.php',
@ -117,6 +136,8 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php',
'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php',
'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php',
'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
'Sabre\\CalDAV\\Backend\\AbstractBackend' => __DIR__ . '/..' . '/sabre/dav/lib/CalDAV/Backend/AbstractBackend.php',
'Sabre\\CalDAV\\Backend\\BackendInterface' => __DIR__ . '/..' . '/sabre/dav/lib/CalDAV/Backend/BackendInterface.php',
'Sabre\\CalDAV\\Backend\\NotificationSupport' => __DIR__ . '/..' . '/sabre/dav/lib/CalDAV/Backend/NotificationSupport.php',
@ -367,7 +388,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Sabre\\HTTP\\URLUtil' => __DIR__ . '/..' . '/sabre/http/lib/URLUtil.php',
'Sabre\\HTTP\\Util' => __DIR__ . '/..' . '/sabre/http/lib/Util.php',
'Sabre\\HTTP\\Version' => __DIR__ . '/..' . '/sabre/http/lib/Version.php',
'Sabre\\Uri\\InvalidUriException' => __DIR__ . '/..' . '/sabre/uri/lib/InvalidUriException.php',
'Sabre\\Uri\\Version' => __DIR__ . '/..' . '/sabre/uri/lib/Version.php',
'Sabre\\VObject\\BirthdayCalendarGenerator' => __DIR__ . '/..' . '/sabre/vobject/lib/BirthdayCalendarGenerator.php',
'Sabre\\VObject\\Cli' => __DIR__ . '/..' . '/sabre/vobject/lib/Cli.php',
@ -456,6 +476,9 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Sabre\\Xml\\Writer' => __DIR__ . '/..' . '/sabre/xml/lib/Writer.php',
'Sabre\\Xml\\XmlDeserializable' => __DIR__ . '/..' . '/sabre/xml/lib/XmlDeserializable.php',
'Sabre\\Xml\\XmlSerializable' => __DIR__ . '/..' . '/sabre/xml/lib/XmlSerializable.php',
'Test\\Markdownify\\ConverterExtraTest' => __DIR__ . '/..' . '/pixel418/markdownify/test/ConverterExtraTest.php',
'Test\\Markdownify\\ConverterTest' => __DIR__ . '/..' . '/pixel418/markdownify/test/ConverterTest.php',
'Test\\Markdownify\\ConverterTestCase' => __DIR__ . '/..' . '/pixel418/markdownify/test/ConverterTestCase.php',
'Zotlabs\\Access\\AccessList' => __DIR__ . '/../..' . '/Zotlabs/Access/AccessList.php',
'Zotlabs\\Access\\PermissionLimits' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionLimits.php',
'Zotlabs\\Access\\PermissionRoles' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionRoles.php',

View File

@ -518,5 +518,63 @@
"keywords": [
"markdown"
]
},
{
"name": "pixel418/markdownify",
"version": "v2.2.1",
"version_normalized": "2.2.1.0",
"source": {
"type": "git",
"url": "https://github.com/Elephant418/Markdownify.git",
"reference": "0160677f04c784550dd10fd72fdf3994967db848"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Elephant418/Markdownify/zipball/0160677f04c784550dd10fd72fdf3994967db848",
"reference": "0160677f04c784550dd10fd72fdf3994967db848",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
},
"time": "2016-09-21T13:01:43+00:00",
"type": "lib",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Markdownify\\": "src",
"Test\\Markdownify\\": "test"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
],
"authors": [
{
"name": "Peter Kruithof",
"email": "pkruithof@gmail.com",
"homepage": "http://pkruithof.tumblr.com/"
},
{
"name": "Milian Wolff",
"email": "mail@milianw.de",
"homepage": "http://milianw.de"
},
{
"name": "Thomas Zilliox",
"email": "hello@tzi.fr",
"homepage": "http://tzi.fr"
}
],
"description": "The HTML to Markdown converter for PHP ",
"homepage": "https://github.com/elephant418/Markdownify",
"keywords": [
"markdown",
"markdownify"
]
}
]

View File

@ -0,0 +1,76 @@
CHANGELOG
==============
21/09/2016 v2.2.1
--------------
* Fix: Moving trailing whitespace from inline elements outside of the element
* Feature: Use PSR-4
* Feature: PHP 7.0 support in continuous integration
* Doc: Update of the README
07/09/2016 v2.2.0
--------------
* Fix: Reset state between each parsing
19/02/2016 v2.1.11
--------------
* Fix: Empty table cell conversion
10/02/2016 v2.1.10
--------------
* Fix: Handle nested table.
01/04/2015 v2.1.9
--------------
* Fix: Handle HTML breaks & spaces in a less destructive way.
26/03/2015 v2.1.8
--------------
* Fix: Use alternative italic character
* Fix: Handle HTML breaks inside another tag
* Fix: Handle HTML spaces around tags
07/11/2014 v2.1.7
--------------
* Change composer name to "elephant418/markdownify"
14/07/2014 v2.1.6
--------------
* Fix: Simulate a paragraph for inline text preceding block element
* Fix: Nested lists
* Fix: setKeepHTML method
* Feature: PHP 5.5 & 5.6 support in continuous integration
16/03/2014 v2.1.5
--------------
Add display settings
* Test: Add tests for footnotes after every paragraph or not
* Feature: Allow to display link reference in paragraph, without footnotes
27/02/2014 v2.1.4
--------------
Improve how ConverterExtra handle id & class attributes:
* Feature: Allow id & class attributes on links
* Feature: Allow class attributes on headings

63
vendor/pixel418/markdownify/README.md vendored Normal file
View File

@ -0,0 +1,63 @@
# Markdownify
[![Build Status](https://travis-ci.org/Elephant418/Markdownify.png?branch=master)](https://travis-ci.org/Elephant418/Markdownify?branch=master)
[![Total Downloads](https://poser.pugx.org/pixel418/markdownify/downloads)](https://packagist.org/packages/pixel418/markdownify)
[![License LGPL](https://poser.pugx.org/pixel418/markdownify/license)](https://opensource.org/licenses/lgpl-2.1.php)
The HTML to Markdown converter for PHP
[Code example](#code-example) | [How to Install](#how-to-install) | [How to Contribute](#how-to-contribute) | [Author & Community](#author--community)
Code example
--------
### Markdown
```php
$converter = new Markdownify\Converter;
$converter->parseString('<h1>Heading</h1>');
// Returns: # Heading
```
### Markdown Extra [as defined by @michelf](http://michelf.ca/projects/php-markdown/extra/)
```php
$converter = new Markdownify\ConverterExtra;
$converter->parseString('<h1 id="md">Heading</h1>');
// Returns: # Heading {#md}
```
How to Install
--------
This library package requires `PHP 5.3` or later.<br>
Install [Composer](http://getcomposer.org/doc/01-basic-usage.md#installation) and run the following command to get the latest version:
```sh
composer require pixel418/markdownify
```
How to Contribute
--------
1. Fork the Markdownify repository
2. Create a new branch for each feature or improvement
3. Send a pull request from each feature branch to the **v2.x** branch
If you don't know much about pull request, you can read [the Github article](https://help.github.com/articles/using-pull-requests)
Author & Community
--------
Markdownify is under [LGPL License](http://opensource.org/licenses/LGPL-2.1)<br>
It was created by [Milian Wolff](http://milianw.de)<br>
It was converted to a Symfony Bundle by [Peter Kruithof](https://github.com/pkruithof)<br>
It is maintained by [Thomas ZILLIOX](http://tzi.fr)

View File

@ -0,0 +1,38 @@
{
"name": "pixel418/markdownify",
"type": "lib",
"description": "The HTML to Markdown converter for PHP ",
"keywords": ["markdown", "markdownify"],
"license": "LGPL",
"homepage": "https://github.com/elephant418/Markdownify",
"authors": [
{
"name": "Milian Wolff",
"email": "mail@milianw.de",
"homepage": "http://milianw.de"
},
{
"name": "Peter Kruithof",
"email": "pkruithof@gmail.com",
"homepage": "http://pkruithof.tumblr.com/"
},
{
"name": "Thomas Zilliox",
"email": "hello@tzi.fr",
"homepage": "http://tzi.fr"
}
],
"require": {
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8"
},
"autoload": {
"psr-4": {
"Markdownify\\": "src",
"Test\\Markdownify\\": "test"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,573 @@
<?php
/* This file is part of the Markdownify project, which is under LGPL license */
namespace Markdownify;
class ConverterExtra extends Converter
{
/**
* table data, including rows with content and the maximum width of each col
*
* @var array
*/
protected $table = array();
/**
* current col
*
* @var int
*/
protected $col = -1;
/**
* current row
*
* @var int
*/
protected $row = 0;
/**
* constructor, see Markdownify::Markdownify() for more information
*/
public function __construct($linksAfterEachParagraph = self::LINK_AFTER_CONTENT, $bodyWidth = MDFY_BODYWIDTH, $keepHTML = MDFY_KEEPHTML)
{
parent::__construct($linksAfterEachParagraph, $bodyWidth, $keepHTML);
// new markdownable tags & attributes
// header ids: # foo {bar}
$this->isMarkdownable['h1']['id'] = 'optional';
$this->isMarkdownable['h1']['class'] = 'optional';
$this->isMarkdownable['h2']['id'] = 'optional';
$this->isMarkdownable['h2']['class'] = 'optional';
$this->isMarkdownable['h3']['id'] = 'optional';
$this->isMarkdownable['h3']['class'] = 'optional';
$this->isMarkdownable['h4']['id'] = 'optional';
$this->isMarkdownable['h4']['class'] = 'optional';
$this->isMarkdownable['h5']['id'] = 'optional';
$this->isMarkdownable['h5']['class'] = 'optional';
$this->isMarkdownable['h6']['id'] = 'optional';
$this->isMarkdownable['h6']['class'] = 'optional';
// tables
$this->isMarkdownable['table'] = array();
$this->isMarkdownable['th'] = array(
'align' => 'optional',
);
$this->isMarkdownable['td'] = array(
'align' => 'optional',
);
$this->isMarkdownable['tr'] = array();
array_push($this->ignore, 'thead');
array_push($this->ignore, 'tbody');
array_push($this->ignore, 'tfoot');
// definition lists
$this->isMarkdownable['dl'] = array();
$this->isMarkdownable['dd'] = array();
$this->isMarkdownable['dt'] = array();
// link class
$this->isMarkdownable['a']['id'] = 'optional';
$this->isMarkdownable['a']['class'] = 'optional';
// footnotes
$this->isMarkdownable['fnref'] = array(
'target' => 'required',
);
$this->isMarkdownable['footnotes'] = array();
$this->isMarkdownable['fn'] = array(
'name' => 'required',
);
$this->parser->blockElements['fnref'] = false;
$this->parser->blockElements['fn'] = true;
$this->parser->blockElements['footnotes'] = true;
// abbr
$this->isMarkdownable['abbr'] = array(
'title' => 'required',
);
// build RegEx lookahead to decide wether table can pe parsed or not
$inlineTags = array_keys($this->parser->blockElements, false);
$colContents = '(?:[^<]|<(?:' . implode('|', $inlineTags) . '|[^a-z]))*';
$this->tableLookaheadHeader = '{
^\s*(?:<thead\s*>)?\s* # open optional thead
<tr\s*>\s*(?: # start required row with headers
<th(?:\s+align=("|\')(?:left|center|right)\1)?\s*> # header with optional align
\s*' . $colContents . '\s* # contents
</th>\s* # close header
)+</tr> # close row with headers
\s*(?:</thead>)? # close optional thead
}sxi';
$this->tdSubstitute = '\s*' . $colContents . '\s* # contents
</td>\s*';
$this->tableLookaheadBody = '{
\s*(?:<tbody\s*>)?\s* # open optional tbody
(?:<tr\s*>\s* # start row
%s # cols to be substituted
</tr>)+ # close row
\s*(?:</tbody>)? # close optional tbody
\s*</table> # close table
}sxi';
}
/**
* handle header tags (<h1> - <h6>)
*
* @param int $level 1-6
* @return void
*/
protected function handleHeader($level)
{
if ($this->parser->isStartTag) {
$this->parser->tagAttributes['cssSelector'] = $this->getCurrentCssSelector();
$this->stack();
} else {
$tag = $this->unstack();
if (!empty($tag['cssSelector'])) {
// {#id.class}
$this->out(' {' . $tag['cssSelector'] . '}');
}
}
parent::handleHeader($level);
}
/**
* handle <a> tags parsing
*
* @param void
* @return void
*/
protected function handleTag_a_parser()
{
parent::handleTag_a_parser();
$this->parser->tagAttributes['cssSelector'] = $this->getCurrentCssSelector();
}
/**
* handle <a> tags conversion
*
* @param array $tag
* @param string $buffer
* @return string The markdownified link
*/
protected function handleTag_a_converter($tag, $buffer)
{
$output = parent::handleTag_a_converter($tag, $buffer);
if (!empty($tag['cssSelector'])) {
// [This link][id]{#id.class}
$output .= '{' . $tag['cssSelector'] . '}';
}
return $output;
}
/**
* handle <abbr> tags
*
* @param void
* @return void
*/
protected function handleTag_abbr()
{
if ($this->parser->isStartTag) {
$this->stack();
$this->buffer();
} else {
$tag = $this->unstack();
$tag['text'] = $this->unbuffer();
$add = true;
foreach ($this->stack['abbr'] as $stacked) {
if ($stacked['text'] == $tag['text']) {
/** TODO: differing abbr definitions, i.e. different titles for same text **/
$add = false;
break;
}
}
$this->out($tag['text']);
if ($add) {
array_push($this->stack['abbr'], $tag);
}
}
}
/**
* flush stacked abbr tags
*
* @param void
* @return void
*/
protected function flushStacked_abbr()
{
$out = array();
foreach ($this->stack['abbr'] as $k => $tag) {
if (!isset($tag['unstacked'])) {
array_push($out, ' *[' . $tag['text'] . ']: ' . $tag['title']);
$tag['unstacked'] = true;
$this->stack['abbr'][$k] = $tag;
}
}
if (!empty($out)) {
$this->out("\n\n" . implode("\n", $out));
}
}
/**
* handle <table> tags
*
* @param void
* @return void
*/
protected function handleTag_table()
{
if ($this->parser->isStartTag) {
// check if upcoming table can be converted
if ($this->keepHTML) {
if (preg_match($this->tableLookaheadHeader, $this->parser->html, $matches)) {
// header seems good, now check body
// get align & number of cols
preg_match_all('#<th(?:\s+align=("|\')(left|right|center)\1)?\s*>#si', $matches[0], $cols);
$regEx = '';
$i = 1;
$aligns = array();
foreach ($cols[2] as $align) {
$align = strtolower($align);
array_push($aligns, $align);
if (empty($align)) {
$align = 'left'; // default value
}
$td = '\s+align=("|\')' . $align . '\\' . $i;
$i++;
if ($align == 'left') {
// look for empty align or left
$td = '(?:' . $td . ')?';
}
$td = '<td' . $td . '\s*>';
$regEx .= $td . $this->tdSubstitute;
}
$regEx = sprintf($this->tableLookaheadBody, $regEx);
if (preg_match($regEx, $this->parser->html, $matches, null, strlen($matches[0]))) {
// this is a markdownable table tag!
$this->table = array(
'rows' => array(),
'col_widths' => array(),
'aligns' => $aligns,
);
$this->row = 0;
} else {
// non markdownable table
$this->handleTagToText();
}
} else {
// non markdownable table
$this->handleTagToText();
}
} else {
$this->table = array(
'rows' => array(),
'col_widths' => array(),
'aligns' => array(),
);
$this->row = 0;
}
} else {
// finally build the table in Markdown Extra syntax
$separator = array();
if (!isset($this->table['aligns'])) {
$this->table['aligns'] = array();
}
// seperator with correct align identifiers
foreach ($this->table['aligns'] as $col => $align) {
if (!$this->keepHTML && !isset($this->table['col_widths'][$col])) {
break;
}
$left = ' ';
$right = ' ';
switch ($align) {
case 'left':
$left = ':';
break;
case 'center':
$right = ':';
$left = ':';
case 'right':
$right = ':';
break;
}
array_push($separator, $left . str_repeat('-', $this->table['col_widths'][$col]) . $right);
}
$separator = '|' . implode('|', $separator) . '|';
$rows = array();
// add padding
array_walk_recursive($this->table['rows'], array(&$this, 'alignTdContent'));
$header = array_shift($this->table['rows']);
array_push($rows, '| ' . implode(' | ', $header) . ' |');
array_push($rows, $separator);
foreach ($this->table['rows'] as $row) {
array_push($rows, '| ' . implode(' | ', $row) . ' |');
}
$this->out(implode("\n" . $this->indent, $rows));
$this->table = array();
$this->setLineBreaks(2);
}
}
/**
* properly pad content so it is aligned as whished
* should be used with array_walk_recursive on $this->table['rows']
*
* @param string &$content
* @param int $col
* @return void
*/
protected function alignTdContent(&$content, $col)
{
if (!isset($this->table['aligns'][$col])) {
$this->table['aligns'][$col] = 'left';
}
switch ($this->table['aligns'][$col]) {
default:
case 'left':
$content .= str_repeat(' ', $this->table['col_widths'][$col] - $this->strlen($content));
break;
case 'right':
$content = str_repeat(' ', $this->table['col_widths'][$col] - $this->strlen($content)) . $content;
break;
case 'center':
$paddingNeeded = $this->table['col_widths'][$col] - $this->strlen($content);
$left = floor($paddingNeeded / 2);
$right = $paddingNeeded - $left;
$content = str_repeat(' ', $left) . $content . str_repeat(' ', $right);
break;
}
}
/**
* handle <tr> tags
*
* @param void
* @return void
*/
protected function handleTag_tr()
{
if ($this->parser->isStartTag) {
$this->col = -1;
} else {
$this->row++;
}
}
/**
* handle <td> tags
*
* @param void
* @return void
*/
protected function handleTag_td()
{
if ($this->parser->isStartTag) {
$this->col++;
if (!isset($this->table['col_widths'][$this->col])) {
$this->table['col_widths'][$this->col] = 0;
}
$this->buffer();
} else {
$buffer = trim($this->unbuffer());
if (!isset($this->table['col_widths'][$this->col])) {
$this->table['col_widths'][$this->col] = 0;
}
$this->table['col_widths'][$this->col] = max($this->table['col_widths'][$this->col], $this->strlen($buffer));
$this->table['rows'][$this->row][$this->col] = $buffer;
}
}
/**
* handle <th> tags
*
* @param void
* @return void
*/
protected function handleTag_th()
{
if (!$this->keepHTML && !isset($this->table['rows'][1]) && !isset($this->table['aligns'][$this->col + 1])) {
if (isset($this->parser->tagAttributes['align'])) {
$this->table['aligns'][$this->col + 1] = $this->parser->tagAttributes['align'];
} else {
$this->table['aligns'][$this->col + 1] = '';
}
}
$this->handleTag_td();
}
/**
* handle <dl> tags
*
* @param void
* @return void
*/
protected function handleTag_dl()
{
if (!$this->parser->isStartTag) {
$this->setLineBreaks(2);
}
}
/**
* handle <dt> tags
*
* @param void
* @return void
**/
protected function handleTag_dt()
{
if (!$this->parser->isStartTag) {
$this->setLineBreaks(1);
}
}
/**
* handle <dd> tags
*
* @param void
* @return void
*/
protected function handleTag_dd()
{
if ($this->parser->isStartTag) {
if (substr(ltrim($this->parser->html), 0, 3) == '<p>') {
// next comes a paragraph, so we'll need an extra line
$this->out("\n" . $this->indent);
} elseif (substr($this->output, -2) == "\n\n") {
$this->output = substr($this->output, 0, -1);
}
$this->out(': ');
$this->indent(' ', false);
} else {
// lookahead for next dt
if (substr(ltrim($this->parser->html), 0, 4) == '<dt>') {
$this->setLineBreaks(2);
} else {
$this->setLineBreaks(1);
}
$this->indent(' ');
}
}
/**
* handle <fnref /> tags (custom footnote references, see markdownify_extra::parseString())
*
* @param void
* @return void
*/
protected function handleTag_fnref()
{
$this->out('[^' . $this->parser->tagAttributes['target'] . ']');
}
/**
* handle <fn> tags (custom footnotes, see markdownify_extra::parseString()
* and markdownify_extra::_makeFootnotes())
*
* @param void
* @return void
*/
protected function handleTag_fn()
{
if ($this->parser->isStartTag) {
$this->out('[^' . $this->parser->tagAttributes['name'] . ']:');
$this->setLineBreaks(1);
} else {
$this->setLineBreaks(2);
}
$this->indent(' ');
}
/**
* handle <footnotes> tag (custom footnotes, see markdownify_extra::parseString()
* and markdownify_extra::_makeFootnotes())
*
* @param void
* @return void
*/
protected function handleTag_footnotes()
{
if (!$this->parser->isStartTag) {
$this->setLineBreaks(2);
}
}
/**
* parse a HTML string, clean up footnotes prior
*
* @param string $HTML input
* @return string Markdown formatted output
*/
public function parseString($html)
{
/** TODO: custom markdown-extra options, e.g. titles & classes **/
// <sup id="fnref:..."><a href"#fn..." rel="footnote">...</a></sup>
// => <fnref target="..." />
$html = preg_replace('@<sup id="fnref:([^"]+)">\s*<a href="#fn:\1" rel="footnote">\s*\d+\s*</a>\s*</sup>@Us', '<fnref target="$1" />', $html);
// <div class="footnotes">
// <hr />
// <ol>
//
// <li id="fn:...">...</li>
// ...
//
// </ol>
// </div>
// =>
// <footnotes>
// <fn name="...">...</fn>
// ...
// </footnotes>
$html = preg_replace_callback('#<div class="footnotes">\s*<hr />\s*<ol>\s*(.+)\s*</ol>\s*</div>#Us', array(&$this, '_makeFootnotes'), $html);
return parent::parseString($html);
}
/**
* replace HTML representation of footnotes with something more easily parsable
*
* @note this is a callback to be used in parseString()
*
* @param array $matches
* @return string
*/
protected function _makeFootnotes($matches)
{
// <li id="fn:1">
// ...
// <a href="#fnref:block" rev="footnote">&#8617;</a></p>
// </li>
// => <fn name="1">...</fn>
// remove footnote link
$fns = preg_replace('@\s*(&#160;\s*)?<a href="#fnref:[^"]+" rev="footnote"[^>]*>&#8617;</a>\s*@s', '', $matches[1]);
// remove empty paragraph
$fns = preg_replace('@<p>\s*</p>@s', '', $fns);
// <li id="fn:1">...</li> -> <footnote nr="1">...</footnote>
$fns = str_replace('<li id="fn:', '<fn name="', $fns);
$fns = '<footnotes>' . $fns . '</footnotes>';
return preg_replace('#</li>\s*(?=(?:<fn|</footnotes>))#s', '</fn>$1', $fns);
}
/**
* handle <a> tags parsing
*
* @param void
* @return void
*/
protected function getCurrentCssSelector()
{
$cssSelector = '';
if (isset($this->parser->tagAttributes['id'])) {
$cssSelector .= '#' . $this->decode($this->parser->tagAttributes['id']);
}
if (isset($this->parser->tagAttributes['class'])) {
$classes = explode(' ', $this->decode($this->parser->tagAttributes['class']));
$classes = array_filter($classes);
$cssSelector .= '.' . join('.', $classes);
}
return $cssSelector;
}
}

View File

@ -0,0 +1,564 @@
<?php
/* This file is part of the Markdownify project, which is under LGPL license */
namespace Markdownify;
class Parser
{
public static $skipWhitespace = true;
public static $a_ord;
public static $z_ord;
public static $special_ords;
/**
* tags which are always empty (<br /> etc.)
*
* @var array<string>
*/
public $emptyTags = array(
'br',
'hr',
'input',
'img',
'area',
'link',
'meta',
'param',
);
/**
* tags with preformatted text
* whitespaces wont be touched in them
*
* @var array<string>
*/
public $preformattedTags = array(
'script',
'style',
'pre',
'code',
);
/**
* supress HTML tags inside preformatted tags (see above)
*
* @var bool
*/
public $noTagsInCode = false;
/**
* html to be parsed
*
* @var string
*/
public $html = '';
/**
* node type:
*
* - tag (see isStartTag)
* - text (includes cdata)
* - comment
* - doctype
* - pi (processing instruction)
*
* @var string
*/
public $nodeType = '';
/**
* current node content, i.e. either a
* simple string (text node), or something like
* <tag attrib="value"...>
*
* @var string
*/
public $node = '';
/**
* wether current node is an opening tag (<a>) or not (</a>)
* set to NULL if current node is not a tag
* NOTE: empty tags (<br />) set this to true as well!
*
* @var bool | null
*/
public $isStartTag = null;
/**
* wether current node is an empty tag (<br />) or not (<a></a>)
*
* @var bool | null
*/
public $isEmptyTag = null;
/**
* tag name
*
* @var string | null
*/
public $tagName = '';
/**
* attributes of current tag
*
* @var array (attribName=>value) | null
*/
public $tagAttributes = null;
/**
* whether or not the actual context is a inline context
*
* @var bool | null
*/
public $isInlineContext = null;
/**
* whether the current tag is a block element
*
* @var bool | null
*/
public $isBlockElement = null;
/**
* whether the previous tag (browser) is a block element
*
* @var bool | null
*/
public $isNextToInlineContext = null;
/**
* keep whitespace
*
* @var int
*/
public $keepWhitespace = 0;
/**
* list of open tags
* count this to get current depth
*
* @var array
*/
public $openTags = array();
/**
* list of block elements
*
* @var array
* TODO: what shall we do with <del> and <ins> ?!
*/
public $blockElements = array(
// tag name => <bool> is block
// block elements
'address' => true,
'blockquote' => true,
'center' => true,
'del' => true,
'dir' => true,
'div' => true,
'dl' => true,
'fieldset' => true,
'form' => true,
'h1' => true,
'h2' => true,
'h3' => true,
'h4' => true,
'h5' => true,
'h6' => true,
'hr' => true,
'ins' => true,
'isindex' => true,
'menu' => true,
'noframes' => true,
'noscript' => true,
'ol' => true,
'p' => true,
'pre' => true,
'table' => true,
'ul' => true,
// set table elements and list items to block as well
'thead' => true,
'tbody' => true,
'tfoot' => true,
'td' => true,
'tr' => true,
'th' => true,
'li' => true,
'dd' => true,
'dt' => true,
// header items and html / body as well
'html' => true,
'body' => true,
'head' => true,
'meta' => true,
'link' => true,
'style' => true,
'title' => true,
// unfancy media tags, when indented should be rendered as block
'map' => true,
'object' => true,
'param' => true,
'embed' => true,
'area' => true,
// inline elements
'a' => false,
'abbr' => false,
'acronym' => false,
'applet' => false,
'b' => false,
'basefont' => false,
'bdo' => false,
'big' => false,
'br' => false,
'button' => false,
'cite' => false,
'code' => false,
'del' => false,
'dfn' => false,
'em' => false,
'font' => false,
'i' => false,
'img' => false,
'ins' => false,
'input' => false,
'iframe' => false,
'kbd' => false,
'label' => false,
'q' => false,
'samp' => false,
'script' => false,
'select' => false,
'small' => false,
'span' => false,
'strong' => false,
'sub' => false,
'sup' => false,
'textarea' => false,
'tt' => false,
'var' => false,
);
/**
* get next node, set $this->html prior!
*
* @param void
* @return bool
*/
public function nextNode()
{
if (empty($this->html)) {
// we are done with parsing the html string
return false;
}
if ($this->isStartTag && !$this->isEmptyTag) {
array_push($this->openTags, $this->tagName);
if (in_array($this->tagName, $this->preformattedTags)) {
// dont truncate whitespaces for <code> or <pre> contents
$this->keepWhitespace++;
}
}
if ($this->html[0] == '<') {
$token = substr($this->html, 0, 9);
if (substr($token, 0, 2) == '<?') {
// xml prolog or other pi's
/** TODO **/
// trigger_error('this might need some work', E_USER_NOTICE);
$pos = strpos($this->html, '>');
$this->setNode('pi', $pos + 1);
return true;
}
if (substr($token, 0, 4) == '<!--') {
// comment
$pos = strpos($this->html, '-->');
if ($pos === false) {
// could not find a closing -->, use next gt instead
// this is firefox' behaviour
$pos = strpos($this->html, '>') + 1;
} else {
$pos += 3;
}
$this->setNode('comment', $pos);
static::$skipWhitespace = true;
return true;
}
if ($token == '<!DOCTYPE') {
// doctype
$this->setNode('doctype', strpos($this->html, '>') + 1);
static::$skipWhitespace = true;
return true;
}
if ($token == '<![CDATA[') {
// cdata, use text node
// remove leading <![CDATA[
$this->html = substr($this->html, 9);
$this->setNode('text', strpos($this->html, ']]>') + 3);
// remove trailing ]]> and trim
$this->node = substr($this->node, 0, -3);
$this->handleWhitespaces();
static::$skipWhitespace = true;
return true;
}
if ($this->parseTag()) {
// seems to be a tag
// handle whitespaces
if ($this->isBlockElement) {
static::$skipWhitespace = true;
} else {
static::$skipWhitespace = false;
}
return true;
}
}
if ($this->keepWhitespace) {
static::$skipWhitespace = false;
}
// when we get here it seems to be a text node
$pos = strpos($this->html, '<');
if ($pos === false) {
$pos = strlen($this->html);
}
$this->setNode('text', $pos);
$this->handleWhitespaces();
if (static::$skipWhitespace && $this->node == ' ') {
return $this->nextNode();
}
$this->isInlineContext = true;
static::$skipWhitespace = false;
return true;
}
/**
* parse tag, set tag name and attributes, see if it's a closing tag and so forth...
*
* @param void
* @return bool
*/
protected function parseTag()
{
if (!isset(static::$a_ord)) {
static::$a_ord = ord('a');
static::$z_ord = ord('z');
static::$special_ords = array(
ord(':'), // for xml:lang
ord('-'), // for http-equiv
);
}
$tagName = '';
$pos = 1;
$isStartTag = $this->html[$pos] != '/';
if (!$isStartTag) {
$pos++;
}
// get tagName
while (isset($this->html[$pos])) {
$pos_ord = ord(strtolower($this->html[$pos]));
if (($pos_ord >= static::$a_ord && $pos_ord <= static::$z_ord) || (!empty($tagName) && is_numeric($this->html[$pos]))) {
$tagName .= $this->html[$pos];
$pos++;
} else {
$pos--;
break;
}
}
$tagName = strtolower($tagName);
if (empty($tagName) || !isset($this->blockElements[$tagName])) {
// something went wrong => invalid tag
$this->invalidTag();
return false;
}
if ($this->noTagsInCode && end($this->openTags) == 'code' && !($tagName == 'code' && !$isStartTag)) {
// we supress all HTML tags inside code tags
$this->invalidTag();
return false;
}
// get tag attributes
/** TODO: in html 4 attributes do not need to be quoted **/
$isEmptyTag = false;
$attributes = array();
$currAttrib = '';
while (isset($this->html[$pos + 1])) {
$pos++;
// close tag
if ($this->html[$pos] == '>' || $this->html[$pos] . $this->html[$pos + 1] == '/>') {
if ($this->html[$pos] == '/') {
$isEmptyTag = true;
$pos++;
}
break;
}
$pos_ord = ord(strtolower($this->html[$pos]));
if (($pos_ord >= static::$a_ord && $pos_ord <= static::$z_ord) || in_array($pos_ord, static::$special_ords)) {
// attribute name
$currAttrib .= $this->html[$pos];
} elseif (in_array($this->html[$pos], array(' ', "\t", "\n"))) {
// drop whitespace
} elseif (in_array($this->html[$pos] . $this->html[$pos + 1], array('="', "='"))) {
// get attribute value
$pos++;
$await = $this->html[$pos]; // single or double quote
$pos++;
$value = '';
while (isset($this->html[$pos]) && $this->html[$pos] != $await) {
$value .= $this->html[$pos];
$pos++;
}
$attributes[$currAttrib] = $value;
$currAttrib = '';
} else {
$this->invalidTag();
return false;
}
}
if ($this->html[$pos] != '>') {
$this->invalidTag();
return false;
}
if (!empty($currAttrib)) {
// html 4 allows something like <option selected> instead of <option selected="selected">
$attributes[$currAttrib] = $currAttrib;
}
if (!$isStartTag) {
if (!empty($attributes) || $tagName != end($this->openTags)) {
// end tags must not contain any attributes
// or maybe we did not expect a different tag to be closed
$this->invalidTag();
return false;
}
array_pop($this->openTags);
if (in_array($tagName, $this->preformattedTags)) {
$this->keepWhitespace--;
}
}
$pos++;
$this->node = substr($this->html, 0, $pos);
$this->html = substr($this->html, $pos);
$this->tagName = $tagName;
$this->tagAttributes = $attributes;
$this->isStartTag = $isStartTag;
$this->isEmptyTag = $isEmptyTag || in_array($tagName, $this->emptyTags);
if ($this->isEmptyTag) {
// might be not well formed
$this->node = preg_replace('# */? *>$#', ' />', $this->node);
}
$this->nodeType = 'tag';
$this->isBlockElement = $this->blockElements[$tagName];
$this->isNextToInlineContext = $isStartTag && $this->isInlineContext;
$this->isInlineContext = !$this->isBlockElement;
return true;
}
/**
* handle invalid tags
*
* @param void
* @return void
*/
protected function invalidTag()
{
$this->html = substr_replace($this->html, '&lt;', 0, 1);
}
/**
* update all vars and make $this->html shorter
*
* @param string $type see description for $this->nodeType
* @param int $pos to which position shall we cut?
* @return void
*/
protected function setNode($type, $pos)
{
if ($this->nodeType == 'tag') {
// set tag specific vars to null
// $type == tag should not be called here
// see this::parseTag() for more
$this->tagName = null;
$this->tagAttributes = null;
$this->isStartTag = null;
$this->isEmptyTag = null;
$this->isBlockElement = null;
}
$this->nodeType = $type;
$this->node = substr($this->html, 0, $pos);
$this->html = substr($this->html, $pos);
}
/**
* check if $this->html begins with $str
*
* @param string $str
* @return bool
*/
protected function match($str)
{
return substr($this->html, 0, strlen($str)) == $str;
}
/**
* truncate whitespaces
*
* @param void
* @return void
*/
protected function handleWhitespaces()
{
if ($this->keepWhitespace) {
// <pre> or <code> before...
return;
}
// truncate multiple whitespaces to a single one
$this->node = preg_replace('#\s+#s', ' ', $this->node);
}
/**
* normalize self::node
*
* @param void
* @return void
*/
protected function normalizeNode()
{
$this->node = '<';
if (!$this->isStartTag) {
$this->node .= '/' . $this->tagName . '>';
return;
}
$this->node .= $this->tagName;
foreach ($this->tagAttributes as $name => $value) {
$this->node .= ' ' . $name . '="' . str_replace('"', '&quot;', $value) . '"';
}
if ($this->isEmptyTag) {
$this->node .= ' /';
}
$this->node .= '>';
}
}

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@ App::$strings["Delete"] = "Eliminar";
App::$strings["You are using %1\$s of your available file storage."] = "Está usando %1\$s de su espacio disponible para ficheros.";
App::$strings["You are using %1\$s of %2\$s available file storage. (%3\$s&#37;)"] = "Está usando %1\$s de %2\$s que tiene a su disposición para ficheros. (%3\$s&#37;)";
App::$strings["WARNING:"] = "ATENCIÓN: ";
App::$strings["Please use DAV to upload large (video, audio) files.<br>See <a class=\"zrl\" href=\"help/member/member_guide#Cloud_Desktop_Clients\">Cloud Desktop Clients</a>"] = "Por favor, use DAV para subir ficheros de gran tamaño (vídeo, audio).<br>Mire en <a class=\"zrl\" href=\"help/member/member_guide#Cloud_Desktop_Clients\">Cloud Desktop Clients</a>";
App::$strings["Create new folder"] = "Crear nueva carpeta";
App::$strings["Upload file"] = "Subir fichero";
App::$strings["Drop files here to immediately upload"] = "Arrastre los ficheros aquí para subirlos de forma inmediata";
@ -305,18 +306,6 @@ App::$strings["Only allow embeds from secure (SSL) websites and links."] = "Sól
App::$strings["Allow unfiltered embedded HTML content only from these domains"] = "Permitir contenido HTML sin filtrar sólo desde estos dominios ";
App::$strings["One site per line. By default embedded content is filtered."] = "Un sitio por línea. El contenido incorporado se filtra de forma predeterminada.";
App::$strings["Block embedded HTML from these domains"] = "Bloquear contenido con HTML incorporado desde estos dominios";
App::$strings["Theme settings updated."] = "Ajustes del tema actualizados.";
App::$strings["No themes found."] = "No se han encontrado temas.";
App::$strings["Disable"] = "Desactivar";
App::$strings["Enable"] = "Activar";
App::$strings["Screenshot"] = "Instantánea de pantalla";
App::$strings["Themes"] = "Temas";
App::$strings["Toggle"] = "Cambiar";
App::$strings["Settings"] = "Ajustes";
App::$strings["Author: "] = "Autor:";
App::$strings["Maintainer: "] = "Mantenedor:";
App::$strings["[Experimental]"] = "[Experimental]";
App::$strings["[Unsupported]"] = "[No soportado]";
App::$strings["Password changed for account %d."] = "Ha cambiado la contraseña para la cuenta %d.";
App::$strings["Account settings updated."] = "Se han actualizado los ajustes de la cuenta.";
App::$strings["Account not found."] = "No se ha encontrado la cuenta.";
@ -392,8 +381,16 @@ App::$strings["No failed updates."] = "No ha fallado ninguna actualización.";
App::$strings["Failed Updates"] = "Han fallado las actualizaciones";
App::$strings["Mark success (if update was manually applied)"] = "Marcar como exitosa (si la actualización se ha hecho manualmente)";
App::$strings["Attempt to execute this update step automatically"] = "Intentar ejecutar este paso de actualización automáticamente";
App::$strings["Queue Statistics"] = "Estadísticas de la cola";
App::$strings["Total Entries"] = "Total de entradas";
App::$strings["Priority"] = "Prioridad";
App::$strings["Destination URL"] = "Dirección de destino";
App::$strings["Mark hub permanently offline"] = "Marcar el servidor como permanentemente fuera de línea";
App::$strings["Empty queue for this hub"] = "Vaciar la cola para este servidor";
App::$strings["Last known contact"] = "Último contacto conocido";
App::$strings["Site settings updated."] = "Ajustes del sitio actualizados.";
App::$strings["Default"] = "Predeterminado";
App::$strings["%s - (Incompatible)"] = "%s - (Incompatible)";
App::$strings["mobile"] = "móvil";
App::$strings["experimental"] = "experimental";
App::$strings["unsupported"] = "no soportado";
@ -479,7 +476,13 @@ App::$strings["Expiration period in days for imported (grid/network) content"] =
App::$strings["0 for no expiration of imported content"] = "0 para que no caduque el contenido importado";
App::$strings["Plugin %s disabled."] = "Extensión %s desactivada.";
App::$strings["Plugin %s enabled."] = "Extensión %s activada.";
App::$strings["Disable"] = "Desactivar";
App::$strings["Enable"] = "Activar";
App::$strings["Plugins"] = "Extensiones (plugins)";
App::$strings["Toggle"] = "Cambiar";
App::$strings["Settings"] = "Ajustes";
App::$strings["Author: "] = "Autor:";
App::$strings["Maintainer: "] = "Mantenedor:";
App::$strings["Minimum project version: "] = "Versión mínima del proyecto:";
App::$strings["Maximum project version: "] = "Versión máxima del proyecto:";
App::$strings["Minimum PHP version: "] = "Versión mínima de PHP:";
@ -500,13 +503,12 @@ App::$strings["Install a New Plugin Repository"] = "Instalar un nuevo repositori
App::$strings["Update"] = "Actualizar";
App::$strings["Switch branch"] = "Cambiar la rama";
App::$strings["Remove"] = "Eliminar";
App::$strings["Queue Statistics"] = "Estadísticas de la cola";
App::$strings["Total Entries"] = "Total de entradas";
App::$strings["Priority"] = "Prioridad";
App::$strings["Destination URL"] = "Dirección de destino";
App::$strings["Mark hub permanently offline"] = "Marcar el servidor como permanentemente fuera de línea";
App::$strings["Empty queue for this hub"] = "Vaciar la cola para este servidor";
App::$strings["Last known contact"] = "Último contacto conocido";
App::$strings["Theme settings updated."] = "Ajustes del tema actualizados.";
App::$strings["No themes found."] = "No se han encontrado temas.";
App::$strings["Screenshot"] = "Instantánea de pantalla";
App::$strings["Themes"] = "Temas";
App::$strings["[Experimental]"] = "[Experimental]";
App::$strings["[Unsupported]"] = "[No soportado]";
App::$strings["Export Channel"] = "Exportar el canal";
App::$strings["Export your basic channel information to a file. This acts as a backup of your connections, permissions, profile and basic data, which can be used to import your data to a new server hub, but does not contain your content."] = "Exportar la información básica del canal a un fichero. Este equivale a una copia de seguridad de sus conexiones, el perfil y datos fundamentales, que puede usarse para importar sus datos a un nuevo servidor, pero no incluye su contenido.";
App::$strings["Export Content"] = "Exportar contenidos";
@ -533,6 +535,7 @@ App::$strings["Search Results For:"] = "Buscar resultados para:";
App::$strings["Privacy group is empty"] = "El grupo de canales está vacío";
App::$strings["Privacy group: "] = "Grupo de canales: ";
App::$strings["Invalid connection."] = "Conexión no válida.";
App::$strings["Invalid channel."] = "El canal no es válido.";
App::$strings["Unable to update menu."] = "No se puede actualizar el menú.";
App::$strings["Unable to create menu."] = "No se puede crear el menú.";
App::$strings["Menu Name"] = "Nombre del menú";
@ -596,6 +599,8 @@ App::$strings["View Profile"] = "Ver el perfil";
App::$strings["View %s's profile"] = "Ver el perfil de %s";
App::$strings["Refresh Permissions"] = "Recargar los permisos";
App::$strings["Fetch updated permissions"] = "Obtener los permisos actualizados";
App::$strings["Refresh Photo"] = "Actualizar la foto";
App::$strings["Fetch updated photo"] = "Obtener una foto actualizada";
App::$strings["Recent Activity"] = "Actividad reciente";
App::$strings["View recent posts and comments"] = "Ver publicaciones y comentarios recientes";
App::$strings["Block (or Unblock) all communications with this connection"] = "Bloquear (o desbloquear) todas las comunicaciones con esta conexión";
@ -612,6 +617,8 @@ App::$strings["Hide"] = "Ocultar";
App::$strings["Hide or Unhide this connection from your other connections"] = "Ocultar o mostrar esta conexión a sus otras conexiones";
App::$strings["This connection is hidden!"] = "¡Esta conexión está oculta!";
App::$strings["Delete this connection"] = "Eliminar esta conexión";
App::$strings["Fetch Vcard"] = "Obtener una vcard";
App::$strings["Fetch electronic calling card for this connection"] = "Obtener una tarjeta de llamada electrónica para esta conexión";
App::$strings["Permissions"] = "Permisos";
App::$strings["Open Individual Permissions section by default"] = "Abrir la sección de permisos individuales por defecto";
App::$strings["Affinity"] = "Afinidad";
@ -730,7 +737,76 @@ App::$strings["Share this file"] = "Compartir este fichero";
App::$strings["Show URL to this file"] = "Mostrar la dirección de este fichero";
App::$strings["Notify your contacts about this file"] = "Avisar a sus contactos sobre este fichero";
App::$strings["Photos"] = "Fotos";
App::$strings["Page owner information could not be retrieved."] = "La información del propietario de la página no pudo ser recuperada.";
App::$strings["Profile Photos"] = "Fotos del perfil";
App::$strings["Album not found."] = "Álbum no encontrado.";
App::$strings["Delete Album"] = "Borrar álbum";
App::$strings["Multiple storage folders exist with this album name, but within different directories. Please remove the desired folder or folders using the Files manager"] = "Hay varias carpetas con este nombre de álbum, pero dentro de diferentes directorios. Por favor, elimine la carpeta o carpetas que desee utilizando el administrador de ficheros";
App::$strings["Delete Photo"] = "Borrar foto";
App::$strings["Public access denied."] = "Acceso público denegado.";
App::$strings["No photos selected"] = "No hay fotos seleccionadas";
App::$strings["Access to this item is restricted."] = "El acceso a este elemento está restringido.";
App::$strings["%1$.2f MB of %2$.2f MB photo storage used."] = "%1$.2f MB de %2$.2f MB de almacenamiento de fotos utilizado.";
App::$strings["%1$.2f MB photo storage used."] = "%1$.2f MB de almacenamiento de fotos utilizado.";
App::$strings["Upload Photos"] = "Subir fotos";
App::$strings["Enter an album name"] = "Introducir un nombre de álbum";
App::$strings["or select an existing album (doubleclick)"] = "o seleccionar uno existente (doble click)";
App::$strings["Create a status post for this upload"] = "Crear un mensaje de estado para esta subida";
App::$strings["Caption (optional):"] = "Título (opcional):";
App::$strings["Description (optional):"] = "Descripción (opcional):";
App::$strings["Album name could not be decoded"] = "El nombre del álbum no ha podido ser descifrado";
App::$strings["Contact Photos"] = "Fotos de contacto";
App::$strings["Show Newest First"] = "Mostrar lo más reciente primero";
App::$strings["Show Oldest First"] = "Mostrar lo más antiguo primero";
App::$strings["View Photo"] = "Ver foto";
App::$strings["Edit Album"] = "Editar álbum";
App::$strings["Permission denied. Access to this item may be restricted."] = "Permiso denegado. El acceso a este elemento puede estar restringido.";
App::$strings["Photo not available"] = "Foto no disponible";
App::$strings["Use as profile photo"] = "Usar como foto del perfil";
App::$strings["Use as cover photo"] = "Usar como imagen de portada del perfil";
App::$strings["Private Photo"] = "Foto privada";
App::$strings["View Full Size"] = "Ver tamaño completo";
App::$strings["Edit photo"] = "Editar foto";
App::$strings["Rotate CW (right)"] = "Girar CW (a la derecha)";
App::$strings["Rotate CCW (left)"] = "Girar CCW (a la izquierda)";
App::$strings["Move photo to album"] = "Mover la foto a un álbum";
App::$strings["Enter a new album name"] = "Introducir un nuevo nombre de álbum";
App::$strings["or select an existing one (doubleclick)"] = "o seleccionar uno (doble click) existente";
App::$strings["Caption"] = "Título";
App::$strings["Add a Tag"] = "Añadir una etiqueta";
App::$strings["Example: @bob, @Barbara_Jensen, @jim@example.com"] = "Ejemplos: @eva, @Carmen_Osuna, @jaime@ejemplo.com";
App::$strings["Flag as adult in album view"] = "Marcar como \"solo para adultos\" en el álbum";
App::$strings["I like this (toggle)"] = "Me gusta (cambiar)";
App::$strings["I don't like this (toggle)"] = "No me gusta esto (cambiar)";
App::$strings["Share"] = "Compartir";
App::$strings["Please wait"] = "Espere por favor";
App::$strings["This is you"] = "Este es usted";
App::$strings["Comment"] = "Comentar";
App::$strings["__ctx:title__ Likes"] = "Me gusta";
App::$strings["__ctx:title__ Dislikes"] = "No me gusta";
App::$strings["__ctx:title__ Agree"] = "De acuerdo";
App::$strings["__ctx:title__ Disagree"] = "En desacuerdo";
App::$strings["__ctx:title__ Abstain"] = "Abstención";
App::$strings["__ctx:title__ Attending"] = "Participaré";
App::$strings["__ctx:title__ Not attending"] = "No participaré";
App::$strings["__ctx:title__ Might attend"] = "Quizá participe";
App::$strings["View all"] = "Ver todo";
App::$strings["__ctx:noun__ Like"] = array(
0 => "Me gusta",
1 => "Me gusta",
);
App::$strings["__ctx:noun__ Dislike"] = array(
0 => "No me gusta",
1 => "No me gusta",
);
App::$strings["Photo Tools"] = "Gestión de las fotos";
App::$strings["In This Photo:"] = "En esta foto:";
App::$strings["Map"] = "Mapa";
App::$strings["__ctx:noun__ Likes"] = "Me gusta";
App::$strings["__ctx:noun__ Dislikes"] = "No me gusta";
App::$strings["Close"] = "Cerrar";
App::$strings["View Album"] = "Ver álbum";
App::$strings["Recent Photos"] = "Fotos recientes";
App::$strings["Privacy group created."] = "El grupo de canales ha sido creado.";
App::$strings["Could not create privacy group."] = "No se puede crear el grupo de canales";
App::$strings["Privacy group not found."] = "Grupo de canales no encontrado.";
@ -884,7 +960,6 @@ App::$strings["Import selected"] = "Importar elementos seleccionados";
App::$strings["Export Webpage Elements"] = "Exportar elementos de una página web";
App::$strings["Export selected"] = "Exportar los elementos seleccionados";
App::$strings["Webpages"] = "Páginas web";
App::$strings["Share"] = "Compartir";
App::$strings["Actions"] = "Acciones";
App::$strings["Page Link"] = "Vínculo de la página";
App::$strings["Page Title"] = "Título de página";
@ -935,7 +1010,6 @@ App::$strings["Website:"] = "Sitio web:";
App::$strings["Remote Channel [%s] (not yet known on this site)"] = "Canal remoto [%s] (aún no es conocido en este sitio)";
App::$strings["Rating (this information is public)"] = "Valoración (esta información es pública)";
App::$strings["Optionally explain your rating (this information is public)"] = "Opcionalmente puede explicar su valoración (esta información es pública)";
App::$strings["Profile Photos"] = "Fotos del perfil";
App::$strings["Shift-reload the page or clear browser cache if the new photo does not display immediately."] = "Recargue la página o limpie el caché del navegador si la nueva foto no se muestra inmediatamente.";
App::$strings["Use Photo for Profile"] = "Usar la fotografía para el perfil";
App::$strings["Upload Profile Photo"] = "Subir foto de perfil";
@ -1040,73 +1114,43 @@ App::$strings["No entries (some entries may be hidden)."] = "Sin entradas (algun
App::$strings["vcard"] = "vcard";
App::$strings["Unable to find your hub."] = "No se puede encontrar su servidor.";
App::$strings["Post successful."] = "Enviado con éxito.";
App::$strings["Page owner information could not be retrieved."] = "La información del propietario de la página no pudo ser recuperada.";
App::$strings["Album not found."] = "Álbum no encontrado.";
App::$strings["Delete Album"] = "Borrar álbum";
App::$strings["Multiple storage folders exist with this album name, but within different directories. Please remove the desired folder or folders using the Files manager"] = "Hay varias carpetas con este nombre de álbum, pero dentro de diferentes directorios. Por favor, elimine la carpeta o carpetas que desee utilizando el administrador de ficheros";
App::$strings["Delete Photo"] = "Borrar foto";
App::$strings["No photos selected"] = "No hay fotos seleccionadas";
App::$strings["Access to this item is restricted."] = "El acceso a este elemento está restringido.";
App::$strings["%1$.2f MB of %2$.2f MB photo storage used."] = "%1$.2f MB de %2$.2f MB de almacenamiento de fotos utilizado.";
App::$strings["%1$.2f MB photo storage used."] = "%1$.2f MB de almacenamiento de fotos utilizado.";
App::$strings["Upload Photos"] = "Subir fotos";
App::$strings["Enter an album name"] = "Introducir un nombre de álbum";
App::$strings["or select an existing album (doubleclick)"] = "o seleccionar uno existente (doble click)";
App::$strings["Create a status post for this upload"] = "Crear un mensaje de estado para esta subida";
App::$strings["Caption (optional):"] = "Título (opcional):";
App::$strings["Description (optional):"] = "Descripción (opcional):";
App::$strings["Album name could not be decoded"] = "El nombre del álbum no ha podido ser descifrado";
App::$strings["Contact Photos"] = "Fotos de contacto";
App::$strings["Show Newest First"] = "Mostrar lo más reciente primero";
App::$strings["Show Oldest First"] = "Mostrar lo más antiguo primero";
App::$strings["View Photo"] = "Ver foto";
App::$strings["Edit Album"] = "Editar álbum";
App::$strings["Permission denied. Access to this item may be restricted."] = "Permiso denegado. El acceso a este elemento puede estar restringido.";
App::$strings["Photo not available"] = "Foto no disponible";
App::$strings["Use as profile photo"] = "Usar como foto del perfil";
App::$strings["Use as cover photo"] = "Usar como imagen de portada del perfil";
App::$strings["Private Photo"] = "Foto privada";
App::$strings["View Full Size"] = "Ver tamaño completo";
App::$strings["Edit photo"] = "Editar foto";
App::$strings["Rotate CW (right)"] = "Girar CW (a la derecha)";
App::$strings["Rotate CCW (left)"] = "Girar CCW (a la izquierda)";
App::$strings["Move photo to album"] = "Mover la foto a un álbum";
App::$strings["Enter a new album name"] = "Introducir un nuevo nombre de álbum";
App::$strings["or select an existing one (doubleclick)"] = "o seleccionar uno (doble click) existente";
App::$strings["Caption"] = "Título";
App::$strings["Add a Tag"] = "Añadir una etiqueta";
App::$strings["Example: @bob, @Barbara_Jensen, @jim@example.com"] = "Ejemplos: @eva, @Carmen_Osuna, @jaime@ejemplo.com";
App::$strings["Flag as adult in album view"] = "Marcar como \"solo para adultos\" en el álbum";
App::$strings["I like this (toggle)"] = "Me gusta (cambiar)";
App::$strings["I don't like this (toggle)"] = "No me gusta esto (cambiar)";
App::$strings["Please wait"] = "Espere por favor";
App::$strings["This is you"] = "Este es usted";
App::$strings["Comment"] = "Comentar";
App::$strings["__ctx:title__ Likes"] = "Me gusta";
App::$strings["__ctx:title__ Dislikes"] = "No me gusta";
App::$strings["__ctx:title__ Agree"] = "De acuerdo";
App::$strings["__ctx:title__ Disagree"] = "En desacuerdo";
App::$strings["__ctx:title__ Abstain"] = "Abstención";
App::$strings["__ctx:title__ Attending"] = "Participaré";
App::$strings["__ctx:title__ Not attending"] = "No participaré";
App::$strings["__ctx:title__ Might attend"] = "Quizá participe";
App::$strings["View all"] = "Ver todo";
App::$strings["__ctx:noun__ Like"] = array(
0 => "Me gusta",
1 => "Me gusta",
);
App::$strings["__ctx:noun__ Dislike"] = array(
0 => "No me gusta",
1 => "No me gusta",
);
App::$strings["Photo Tools"] = "Gestión de las fotos";
App::$strings["In This Photo:"] = "En esta foto:";
App::$strings["Map"] = "Mapa";
App::$strings["__ctx:noun__ Likes"] = "Me gusta";
App::$strings["__ctx:noun__ Dislikes"] = "No me gusta";
App::$strings["Close"] = "Cerrar";
App::$strings["View Album"] = "Ver álbum";
App::$strings["Recent Photos"] = "Fotos recientes";
App::$strings["Source of Item"] = "Origen del elemento";
App::$strings["No service class restrictions found."] = "No se han encontrado restricciones sobre esta clase de servicio.";
App::$strings["network"] = "red";
App::$strings["RSS"] = "RSS";
App::$strings["Channel removals are not allowed within 48 hours of changing the account password."] = "La eliminación de canales no está permitida hasta pasadas 48 horas desde el último cambio de contraseña.";
App::$strings["Remove This Channel"] = "Eliminar este canal";
App::$strings["This channel will be completely removed from the network. "] = "Este canal va a ser completamente eliminado de la red. ";
App::$strings["Remove this channel and all its clones from the network"] = "Eliminar este canal y todos sus clones de la red";
App::$strings["By default only the instance of the channel located on this hub will be removed from the network"] = "Por defecto, solo la instancia del canal alojado en este servidor será eliminado de la red";
App::$strings["Remove Channel"] = "Eliminar el canal";
App::$strings["Files: shared with me"] = "Ficheros: compartidos conmigo";
App::$strings["NEW"] = "NUEVO";
App::$strings["Remove all files"] = "Eliminar todos los ficheros";
App::$strings["Remove this file"] = "Eliminar este fichero";
App::$strings["post"] = "la entrada";
App::$strings["comment"] = "el comentario";
App::$strings["%1\$s tagged %2\$s's %3\$s with %4\$s"] = "%1\$s ha etiquetado %3\$s de %2\$s con %4\$s";
App::$strings["Failed to create source. No channel selected."] = "No se ha podido crear el origen de los contenidos. No ha sido seleccionado ningún canal.";
App::$strings["Source created."] = "Fuente creada.";
App::$strings["Source updated."] = "Fuente actualizada.";
App::$strings["*"] = "*";
App::$strings["Channel Sources"] = "Orígenes de los contenidos del canal";
App::$strings["Manage remote sources of content for your channel."] = "Gestionar contenido de origen remoto para su canal.";
App::$strings["New Source"] = "Nueva fuente";
App::$strings["Import all or selected content from the following channel into this channel and distribute it according to your channel settings."] = "Importar todo el contenido o una selección de los siguientes canales en este canal y distribuirlo de acuerdo con sus ajustes.";
App::$strings["Only import content with these words (one per line)"] = "Importar solo contenido que contenga estas palabras (una por línea)";
App::$strings["Leave blank to import all public content"] = "Dejar en blanco para importar todo el contenido público";
App::$strings["Channel Name"] = "Nombre del canal";
App::$strings["Add the following categories to posts imported from this source (comma separated)"] = "Añadir los temas siguientes a las entradas importadas de esta fuente (separadas por comas)";
App::$strings["Optional"] = "Opcional";
App::$strings["Source not found."] = "Fuente no encontrada";
App::$strings["Edit Source"] = "Editar fuente";
App::$strings["Delete Source"] = "Eliminar fuente";
App::$strings["Source removed"] = "Fuente eliminada";
App::$strings["Unable to remove source."] = "No se puede eliminar la fuente.";
App::$strings["No suggestions available. If this is a new site, please try again in 24 hours."] = "No hay sugerencias disponibles. Si es un sitio nuevo, espere 24 horas y pruebe de nuevo.";
App::$strings["Ignore/Hide"] = "Ignorar/Ocultar";
App::$strings["Profile not found."] = "Perfil no encontrado.";
App::$strings["Profile deleted."] = "Perfil eliminado.";
App::$strings["Profile-"] = "Perfil-";
@ -1172,79 +1216,9 @@ App::$strings["Love/Romance"] = "Vida sentimental o amorosa";
App::$strings["School/Education"] = "Estudios";
App::$strings["Contact information and social networks"] = "Información de contacto y redes sociales";
App::$strings["My other channels"] = "Mis otros canales";
App::$strings["Communications"] = "Comunicaciones";
App::$strings["Profile Image"] = "Imagen del perfil";
App::$strings["Edit Profiles"] = "Editar perfiles";
App::$strings["No service class restrictions found."] = "No se han encontrado restricciones sobre esta clase de servicio.";
App::$strings["network"] = "red";
App::$strings["RSS"] = "RSS";
App::$strings["Channel removals are not allowed within 48 hours of changing the account password."] = "La eliminación de canales no está permitida hasta pasadas 48 horas desde el último cambio de contraseña.";
App::$strings["Remove This Channel"] = "Eliminar este canal";
App::$strings["This channel will be completely removed from the network. "] = "Este canal va a ser completamente eliminado de la red. ";
App::$strings["Remove this channel and all its clones from the network"] = "Eliminar este canal y todos sus clones de la red";
App::$strings["By default only the instance of the channel located on this hub will be removed from the network"] = "Por defecto, solo la instancia del canal alojado en este servidor será eliminado de la red";
App::$strings["Remove Channel"] = "Eliminar el canal";
App::$strings["Files: shared with me"] = "Ficheros: compartidos conmigo";
App::$strings["NEW"] = "NUEVO";
App::$strings["Remove all files"] = "Eliminar todos los ficheros";
App::$strings["Remove this file"] = "Eliminar este fichero";
App::$strings["post"] = "la entrada";
App::$strings["comment"] = "el comentario";
App::$strings["%1\$s tagged %2\$s's %3\$s with %4\$s"] = "%1\$s ha etiquetado %3\$s de %2\$s con %4\$s";
App::$strings["Failed to create source. No channel selected."] = "No se ha podido crear el origen de los contenidos. No ha sido seleccionado ningún canal.";
App::$strings["Source created."] = "Fuente creada.";
App::$strings["Source updated."] = "Fuente actualizada.";
App::$strings["*"] = "*";
App::$strings["Channel Sources"] = "Orígenes de los contenidos del canal";
App::$strings["Manage remote sources of content for your channel."] = "Gestionar contenido de origen remoto para su canal.";
App::$strings["New Source"] = "Nueva fuente";
App::$strings["Import all or selected content from the following channel into this channel and distribute it according to your channel settings."] = "Importar todo el contenido o una selección de los siguientes canales en este canal y distribuirlo de acuerdo con sus ajustes.";
App::$strings["Only import content with these words (one per line)"] = "Importar solo contenido que contenga estas palabras (una por línea)";
App::$strings["Leave blank to import all public content"] = "Dejar en blanco para importar todo el contenido público";
App::$strings["Channel Name"] = "Nombre del canal";
App::$strings["Add the following categories to posts imported from this source (comma separated)"] = "Añadir los temas siguientes a las entradas importadas de esta fuente (separadas por comas)";
App::$strings["Optional"] = "Opcional";
App::$strings["Source not found."] = "Fuente no encontrada";
App::$strings["Edit Source"] = "Editar fuente";
App::$strings["Delete Source"] = "Eliminar fuente";
App::$strings["Source removed"] = "Fuente eliminada";
App::$strings["Unable to remove source."] = "No se puede eliminar la fuente.";
App::$strings["No suggestions available. If this is a new site, please try again in 24 hours."] = "No hay sugerencias disponibles. Si es un sitio nuevo, espere 24 horas y pruebe de nuevo.";
App::$strings["Ignore/Hide"] = "Ignorar/Ocultar";
App::$strings["Profile Unavailable."] = "Perfil no disponible";
App::$strings["Not found"] = "No encontrado";
App::$strings["Invalid channel"] = "Canal no válido";
App::$strings["Wikis"] = "Wikis";
App::$strings["Download"] = "Descargar";
App::$strings["Wiki name"] = "Nombre del wiki";
App::$strings["Content type"] = "Tipo de contenido";
App::$strings["Create a status post for this wiki"] = "Crear un mensaje de estado para este wiki";
App::$strings["Wiki not found"] = "Wiki no encontrado";
App::$strings["Rename page"] = "Renombrar la página";
App::$strings["Error retrieving page content"] = "Error al recuperar el contenido de la página";
App::$strings["Revision Comparison"] = "Comparación de revisiones";
App::$strings["Revert"] = "Revertir";
App::$strings["Short description of your changes (optional)"] = "Breve descripción de sus cambios (opcional)";
App::$strings["Source"] = "Fuente";
App::$strings["New page name"] = "Nombre de la nueva página";
App::$strings["Embed image from photo albums"] = "Incluir una imagen de los álbumes de fotos";
App::$strings["Embed an image from your albums"] = "Incluir una imagen de sus álbumes";
App::$strings["OK"] = "OK";
App::$strings["Choose images to embed"] = "Elegir imágenes para incluir";
App::$strings["Choose an album"] = "Elegir un álbum";
App::$strings["Choose a different album"] = "Elegir un álbum diferente...";
App::$strings["Error getting album list"] = "Error al obtener la lista de álbumes";
App::$strings["Error getting photo link"] = "Error al obtener el enlace de la foto";
App::$strings["Error getting album"] = "Error al obtener el álbum";
App::$strings["Error creating wiki. Invalid name."] = "Error al crear el wiki: el nombre no es válido.";
App::$strings["Wiki created, but error creating Home page."] = "Se ha creado el wiki, pero se ha producido un error al crear la página de inicio.";
App::$strings["Error creating wiki"] = "Error al crear el wiki";
App::$strings["Wiki delete permission denied."] = "Se ha denegado el permiso para eliminar el wiki.";
App::$strings["Error deleting wiki"] = "Se ha producido un error al eliminar el wiki";
App::$strings["New page created"] = "Se ha creado la nueva página";
App::$strings["Cannot delete Home"] = "No se puede eliminar la página principal";
App::$strings["Current Revision"] = "Revisión actual";
App::$strings["Selected Revision"] = "Revisión seleccionada";
App::$strings["You must be authenticated."] = "Debe estar autenticado.";
App::$strings["Additional Features"] = "Funcionalidades";
App::$strings["Name is required"] = "El nombre es obligatorio";
App::$strings["Key and Secret are required"] = "\"Key\" y \"Secret\" son obligatorios";
@ -1368,6 +1342,25 @@ App::$strings["Personal menu to display in your channel pages"] = "Menú persona
App::$strings["Remove this channel."] = "Eliminar este canal.";
App::$strings["Firefox Share \$Projectname provider"] = "Servicio de compartición de Firefox: proveedor \$Projectname";
App::$strings["Start calendar week on monday"] = "Comenzar el calendario semanal por el lunes";
App::$strings["Affinity Slider settings updated."] = "Se han actualizado los ajustes del controlador de afinidad.";
App::$strings["No feature settings configured"] = "No se ha establecido la configuración de los complementos";
App::$strings["Default maximum affinity level"] = "Nivel máximo de afinidad por defecto";
App::$strings["Default minimum affinity level"] = "Nivel mínimo de afinidad por defecto";
App::$strings["Affinity Slider Settings"] = "Ajustes del controlador de afinidad";
App::$strings["Feature/Addon Settings"] = "Ajustes de los complementos";
App::$strings["Permission category saved."] = "Se ha guardado la categoría del permiso.";
App::$strings["Use this form to create permission rules for various classes of people or connections."] = "Utilice este formulario para crear reglas de permiso para varias clases de personas o conexiones.";
App::$strings["Permission Categories"] = "Categorías de autorización";
App::$strings["Permission Name"] = "Nombre de la autorización";
App::$strings["This channel is limited to %d tokens"] = "Este canal tiene un límite de %d tokens";
App::$strings["Name and Password are required."] = "Se requiere el nombre y la contraseña.";
App::$strings["Token saved."] = "Token salvado.";
App::$strings["Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content."] = "Utilice este formulario para crear identificadores de acceso temporal para compartir cosas con los no miembros de Hubzilla. Estas identidades se pueden usar en las Listas de control de acceso (ACL) y así los visitantes pueden iniciar sesión, utilizando estas credenciales, para acceder a su contenido privado.";
App::$strings["You may also provide <em>dropbox</em> style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:"] = "También puede proporcionar, con el estilo <em>dropbox</em>, enlaces de acceso a sus amigos y asociados añadiendo la contraseña de inicio de sesión a cualquier dirección URL, como se muestra. Ejemplos: ";
App::$strings["Guest Access Tokens"] = "Tokens de acceso para invitados";
App::$strings["Login Name"] = "Nombre de inicio de sesión";
App::$strings["Login Password"] = "Contraseña de inicio de sesión";
App::$strings["Expires (yyyy-mm-dd)"] = "Expira (aaaa-mm-dd)";
App::$strings["No special theme for mobile devices"] = "Sin tema especial para dispositivos móviles";
App::$strings["%s - (Experimental)"] = "%s - (Experimental)";
App::$strings["Display Settings"] = "Ajustes de visualización";
@ -1395,25 +1388,6 @@ App::$strings["Use blog/list mode on grid page"] = "Mostrar mi red en modo blog"
App::$strings["Channel page max height of content (in pixels)"] = "Altura máxima del contenido de la página del canal (en píxeles)";
App::$strings["click to expand content exceeding this height"] = "Pulsar para expandir el contenido que exceda de esta altura";
App::$strings["Grid page max height of content (in pixels)"] = "Altura máxima del contenido de mi red (en píxeles)";
App::$strings["Affinity Slider settings updated."] = "Se han actualizado los ajustes del controlador de afinidad.";
App::$strings["No feature settings configured"] = "No se ha establecido la configuración de los complementos";
App::$strings["Default maximum affinity level"] = "Nivel máximo de afinidad por defecto";
App::$strings["Default minimum affinity level"] = "Nivel mínimo de afinidad por defecto";
App::$strings["Affinity Slider Settings"] = "Ajustes del controlador de afinidad";
App::$strings["Feature/Addon Settings"] = "Ajustes de los complementos";
App::$strings["Permission category saved."] = "Se ha guardado la categoría del permiso.";
App::$strings["Use this form to create permission rules for various classes of people or connections."] = "Utilice este formulario para crear reglas de permiso para varias clases de personas o conexiones.";
App::$strings["Permission Categories"] = "Categorías de autorización";
App::$strings["Permission Name"] = "Nombre de la autorización";
App::$strings["This channel is limited to %d tokens"] = "Este canal tiene un límite de %d tokens";
App::$strings["Name and Password are required."] = "Se requiere el nombre y la contraseña.";
App::$strings["Token saved."] = "Token salvado.";
App::$strings["Use this form to create temporary access identifiers to share things with non-members. These identities may be used in Access Control Lists and visitors may login using these credentials to access private content."] = "Utilice este formulario para crear identificadores de acceso temporal para compartir cosas con los no miembros de Hubzilla. Estas identidades se pueden usar en las Listas de control de acceso (ACL) y así los visitantes pueden iniciar sesión, utilizando estas credenciales, para acceder a su contenido privado.";
App::$strings["You may also provide <em>dropbox</em> style access links to friends and associates by adding the Login Password to any specific site URL as shown. Examples:"] = "También puede proporcionar, con el estilo <em>dropbox</em>, enlaces de acceso a sus amigos y asociados añadiendo la contraseña de inicio de sesión a cualquier dirección URL, como se muestra. Ejemplos: ";
App::$strings["Guest Access Tokens"] = "Tokens de acceso para invitados";
App::$strings["Login Name"] = "Nombre de inicio de sesión";
App::$strings["Login Password"] = "Contraseña de inicio de sesión";
App::$strings["Expires (yyyy-mm-dd)"] = "Expira (aaaa-mm-dd)";
App::$strings["Tag removed"] = "Etiqueta eliminada.";
App::$strings["Remove Item Tag"] = "Eliminar etiqueta del elemento.";
App::$strings["Select a tag to remove: "] = "Seleccionar una etiqueta para eliminar:";
@ -1522,7 +1496,41 @@ App::$strings["IMPORTANT: You will need to [manually] setup a scheduled task for
App::$strings["No connections."] = "Sin conexiones.";
App::$strings["Visit %s's profile [%s]"] = "Visitar el perfil de %s [%s]";
App::$strings["View Connections"] = "Ver conexiones";
App::$strings["Source of Item"] = "Origen del elemento";
App::$strings["Profile Unavailable."] = "Perfil no disponible";
App::$strings["Not found"] = "No encontrado";
App::$strings["Invalid channel"] = "Canal no válido";
App::$strings["Wikis"] = "Wikis";
App::$strings["Download"] = "Descargar";
App::$strings["Wiki name"] = "Nombre del wiki";
App::$strings["Content type"] = "Tipo de contenido";
App::$strings["Create a status post for this wiki"] = "Crear un mensaje de estado para este wiki";
App::$strings["Wiki not found"] = "Wiki no encontrado";
App::$strings["Rename page"] = "Renombrar la página";
App::$strings["Error retrieving page content"] = "Error al recuperar el contenido de la página";
App::$strings["Revision Comparison"] = "Comparación de revisiones";
App::$strings["Revert"] = "Revertir";
App::$strings["Short description of your changes (optional)"] = "Breve descripción de sus cambios (opcional)";
App::$strings["Source"] = "Fuente";
App::$strings["New page name"] = "Nombre de la nueva página";
App::$strings["Embed image from photo albums"] = "Incluir una imagen de los álbumes de fotos";
App::$strings["Embed an image from your albums"] = "Incluir una imagen de sus álbumes";
App::$strings["OK"] = "OK";
App::$strings["Choose images to embed"] = "Elegir imágenes para incluir";
App::$strings["Choose an album"] = "Elegir un álbum";
App::$strings["Choose a different album"] = "Elegir un álbum diferente...";
App::$strings["Error getting album list"] = "Error al obtener la lista de álbumes";
App::$strings["Error getting photo link"] = "Error al obtener el enlace de la foto";
App::$strings["Error getting album"] = "Error al obtener el álbum";
App::$strings["Error creating wiki. Invalid name."] = "Error al crear el wiki: el nombre no es válido.";
App::$strings["Wiki created, but error creating Home page."] = "Se ha creado el wiki, pero se ha producido un error al crear la página de inicio.";
App::$strings["Error creating wiki"] = "Error al crear el wiki";
App::$strings["Wiki delete permission denied."] = "Se ha denegado el permiso para eliminar el wiki.";
App::$strings["Error deleting wiki"] = "Se ha producido un error al eliminar el wiki";
App::$strings["New page created"] = "Se ha creado la nueva página";
App::$strings["Cannot delete Home"] = "No se puede eliminar la página principal";
App::$strings["Current Revision"] = "Revisión actual";
App::$strings["Selected Revision"] = "Revisión seleccionada";
App::$strings["You must be authenticated."] = "Debe estar autenticado.";
App::$strings["Room not found"] = "Sala no encontrada";
App::$strings["Leave Room"] = "Abandonar la sala";
App::$strings["Delete Room"] = "Eliminar esta sala";
@ -2074,7 +2082,6 @@ App::$strings["Maximum count to import"] = "Límite máximo de importación";
App::$strings["0 or blank to import all available"] = "0 o en blanco para importar todos los disponibles";
App::$strings["Post to Red"] = "Enviar a Red";
App::$strings["Channel is required."] = "Se requiere un canal.";
App::$strings["Invalid channel."] = "El canal no es válido.";
App::$strings["redred Settings saved."] = "Se han salvado los ajustes de redred.";
App::$strings["Allow posting to another Hubzilla Channel"] = "Permitir la publicación en otro canal de Hubzilla";
App::$strings["Send public postings to Hubzilla channel by default"] = "Enviar entradas públicas al canal Hubzilla por defecto";
@ -2380,6 +2387,71 @@ App::$strings["Registration revoked for %s"] = "Registro revocado para %s";
App::$strings["Click here to upgrade."] = "Pulse aquí para actualizar";
App::$strings["This action exceeds the limits set by your subscription plan."] = "Esta acción supera los límites establecidos por su plan de suscripción ";
App::$strings["This action is not available under your subscription plan."] = "Esta acción no está disponible en su plan de suscripción.";
App::$strings["Categories"] = "Temas";
App::$strings["Suggestions"] = "Sugerencias";
App::$strings["See more..."] = "Ver más...";
App::$strings["You have %1$.0f of %2$.0f allowed connections."] = "Tiene %1$.0f de %2$.0f conexiones permitidas.";
App::$strings["Add New Connection"] = "Añadir nueva conexión";
App::$strings["Enter channel address"] = "Dirección del canal";
App::$strings["Examples: bob@example.com, https://example.com/barbara"] = "Ejemplos: manuel@ejemplo.com, https://ejemplo.com/carmen";
App::$strings["Notes"] = "Notas";
App::$strings["Remove term"] = "Eliminar término";
App::$strings["Saved Searches"] = "Búsquedas guardadas";
App::$strings["add"] = "añadir";
App::$strings["Saved Folders"] = "Carpetas guardadas";
App::$strings["Everything"] = "Todo";
App::$strings["Archives"] = "Hemeroteca";
App::$strings["Refresh"] = "Recargar";
App::$strings["Account settings"] = "Configuración de la cuenta";
App::$strings["Channel settings"] = "Configuración del canal";
App::$strings["Additional features"] = "Funcionalidades";
App::$strings["Feature/Addon settings"] = "Complementos";
App::$strings["Display settings"] = "Ajustes de visualización";
App::$strings["Manage locations"] = "Gestión de ubicaciones (clones) del canal";
App::$strings["Export channel"] = "Exportar canal";
App::$strings["Connected apps"] = "Aplicaciones (apps) conectadas";
App::$strings["Permission Groups"] = "Grupos de permisos";
App::$strings["Premium Channel Settings"] = "Configuración del canal premium";
App::$strings["Private Mail Menu"] = "Menú de correo privado";
App::$strings["Combined View"] = "Vista combinada";
App::$strings["Inbox"] = "Bandeja de entrada";
App::$strings["Outbox"] = "Bandeja de salida";
App::$strings["New Message"] = "Nuevo mensaje";
App::$strings["Conversations"] = "Conversaciones";
App::$strings["Received Messages"] = "Mensajes recibidos";
App::$strings["Sent Messages"] = "Enviar mensajes";
App::$strings["No messages."] = "Sin mensajes.";
App::$strings["Delete conversation"] = "Eliminar conversación";
App::$strings["Events Tools"] = "Gestión de eventos";
App::$strings["Export Calendar"] = "Exportar el calendario";
App::$strings["Import Calendar"] = "Importar un calendario";
App::$strings["Chatrooms"] = "Salas de chat";
App::$strings["Overview"] = "Resumen";
App::$strings["Chat Members"] = "Miembros del chat";
App::$strings["__ctx:wiki_history__ Message"] = "Mensaje";
App::$strings["Bookmarked Chatrooms"] = "Salas de chat preferidas";
App::$strings["Suggested Chatrooms"] = "Salas de chat sugeridas";
App::$strings["photo/image"] = "foto/imagen";
App::$strings["Click to show more"] = "Hacer clic para ver más";
App::$strings["Rating Tools"] = "Valoraciones";
App::$strings["Rate Me"] = "Valorar este canal";
App::$strings["View Ratings"] = "Mostrar las valoraciones";
App::$strings["Forums"] = "Foros";
App::$strings["__ctx:widget__ Activity"] = "Actividad";
App::$strings["Tasks"] = "Tareas";
App::$strings["Member registrations waiting for confirmation"] = "Inscripciones de nuevos miembros pendientes de aprobación";
App::$strings["Inspect queue"] = "Examinar la cola";
App::$strings["DB updates"] = "Actualizaciones de la base de datos";
App::$strings["Admin"] = "Administrador";
App::$strings["Plugin Features"] = "Extensiones";
App::$strings["Tags"] = "Etiquetas";
App::$strings["Keywords"] = "Palabras clave";
App::$strings["have"] = "tener";
App::$strings["has"] = "tiene";
App::$strings["want"] = "quiero";
App::$strings["wants"] = "quiere";
App::$strings["likes"] = "gusta de";
App::$strings["dislikes"] = "no gusta de";
App::$strings["l F d, Y \\@ g:i A"] = "l d de F, Y \\@ G:i";
App::$strings["Starts:"] = "Comienza:";
App::$strings["Finishes:"] = "Finaliza:";
@ -2389,15 +2461,6 @@ App::$strings["Needs Action"] = "Necesita de una intervención";
App::$strings["Completed"] = "Completado/a";
App::$strings["In Process"] = "En proceso";
App::$strings["Cancelled"] = "Cancelado/a";
App::$strings["Categories"] = "Temas";
App::$strings["Tags"] = "Etiquetas";
App::$strings["Keywords"] = "Palabras clave";
App::$strings["have"] = "tener";
App::$strings["has"] = "tiene";
App::$strings["want"] = "quiero";
App::$strings["wants"] = "quiere";
App::$strings["likes"] = "gusta de";
App::$strings["dislikes"] = "no gusta de";
App::$strings["Birthday"] = "Cumpleaños";
App::$strings["Age: "] = "Edad:";
App::$strings["YYYY-MM-DD or MM-DD"] = "AAAA-MM-DD o MM-DD";
@ -2509,183 +2572,10 @@ App::$strings["Click to open/close"] = "Pulsar para abrir/cerrar";
App::$strings["spoiler"] = "spoiler";
App::$strings["$1 wrote:"] = "$1 escribió:";
App::$strings["%1\$s's bookmarks"] = "Marcadores de %1\$s";
App::$strings["prev"] = "anterior";
App::$strings["first"] = "primera";
App::$strings["last"] = "última";
App::$strings["next"] = "próxima";
App::$strings["older"] = "más antiguas";
App::$strings["newer"] = "más recientes";
App::$strings["No connections"] = "Sin conexiones";
App::$strings["View all %s connections"] = "Ver todas las %s conexiones";
App::$strings["poke"] = "un toque";
App::$strings["poked"] = "ha dado un toque a";
App::$strings["ping"] = "un \"ping\"";
App::$strings["pinged"] = "ha enviado un \"ping\" a";
App::$strings["prod"] = "una incitación ";
App::$strings["prodded"] = "ha incitado a ";
App::$strings["slap"] = "una bofetada ";
App::$strings["slapped"] = "ha abofeteado a ";
App::$strings["finger"] = "un \"finger\" ";
App::$strings["fingered"] = "envió un \"finger\" a";
App::$strings["rebuff"] = "un reproche";
App::$strings["rebuffed"] = "ha hecho un reproche a ";
App::$strings["happy"] = "feliz ";
App::$strings["sad"] = "triste ";
App::$strings["mellow"] = "tranquilo/a";
App::$strings["tired"] = "cansado/a ";
App::$strings["perky"] = "vivaz";
App::$strings["angry"] = "enfadado/a";
App::$strings["stupefied"] = "asombrado/a";
App::$strings["puzzled"] = "perplejo/a";
App::$strings["interested"] = "interesado/a";
App::$strings["bitter"] = "amargado/a";
App::$strings["cheerful"] = "alegre";
App::$strings["alive"] = "animado/a";
App::$strings["annoyed"] = "molesto/a";
App::$strings["anxious"] = "ansioso/a";
App::$strings["cranky"] = "de mal humor";
App::$strings["disturbed"] = "perturbado/a";
App::$strings["frustrated"] = "frustrado/a";
App::$strings["depressed"] = "deprimido/a";
App::$strings["motivated"] = "motivado/a";
App::$strings["relaxed"] = "relajado/a";
App::$strings["surprised"] = "sorprendido/a";
App::$strings["Monday"] = "lunes";
App::$strings["Tuesday"] = "martes";
App::$strings["Wednesday"] = "miércoles";
App::$strings["Thursday"] = "jueves";
App::$strings["Friday"] = "viernes";
App::$strings["Saturday"] = "sábado";
App::$strings["Sunday"] = "domingo";
App::$strings["January"] = "enero";
App::$strings["February"] = "febrero";
App::$strings["March"] = "marzo";
App::$strings["April"] = "abril";
App::$strings["May"] = "mayo";
App::$strings["June"] = "junio";
App::$strings["July"] = "julio";
App::$strings["August"] = "agosto";
App::$strings["September"] = "septiembre";
App::$strings["October"] = "octubre";
App::$strings["November"] = "noviembre";
App::$strings["December"] = "diciembre";
App::$strings["Unknown Attachment"] = "Adjunto no reconocido";
App::$strings["unknown"] = "desconocido";
App::$strings["remove category"] = "eliminar el tema";
App::$strings["remove from file"] = "eliminar del fichero";
App::$strings["Page layout"] = "Plantilla de la página";
App::$strings["You can create your own with the layouts tool"] = "Puede crear su propia disposición gráfica con la herramienta de plantillas";
App::$strings["Page content type"] = "Tipo de contenido de la página";
App::$strings["activity"] = "la actividad";
App::$strings["Design Tools"] = "Herramientas de diseño web";
App::$strings["Pages"] = "Páginas";
App::$strings["Import website..."] = "Importar un sitio web...";
App::$strings["Select folder to import"] = "Seleccionar la carpeta que se va a importar";
App::$strings["Import from a zipped folder:"] = "Importar desde una carpeta comprimida: ";
App::$strings["Import from cloud files:"] = "Importar desde los ficheros en la nube: ";
App::$strings["/cloud/channel/path/to/folder"] = "/cloud/canal/ruta/a la/carpeta";
App::$strings["Enter path to website files"] = "Ruta a los ficheros del sitio web";
App::$strings["Select folder"] = "Seleccionar la carpeta";
App::$strings["Export website..."] = "Exportar un sitio web...";
App::$strings["Export to a zip file"] = "Exportar a un fichero comprimido .zip";
App::$strings["website.zip"] = "sitio_web.zip";
App::$strings["Enter a name for the zip file."] = "Escriba un nombre para el fichero zip.";
App::$strings["Export to cloud files"] = "Exportar a la nube de ficheros";
App::$strings["/path/to/export/folder"] = "/ruta/para/exportar/carpeta";
App::$strings["Enter a path to a cloud files destination."] = "Escriba una ruta de destino a la nube de ficheros.";
App::$strings["Specify folder"] = "Especificar una carpeta";
App::$strings["Suggestions"] = "Sugerencias";
App::$strings["See more..."] = "Ver más...";
App::$strings["You have %1$.0f of %2$.0f allowed connections."] = "Tiene %1$.0f de %2$.0f conexiones permitidas.";
App::$strings["Add New Connection"] = "Añadir nueva conexión";
App::$strings["Enter channel address"] = "Dirección del canal";
App::$strings["Examples: bob@example.com, https://example.com/barbara"] = "Ejemplos: manuel@ejemplo.com, https://ejemplo.com/carmen";
App::$strings["Notes"] = "Notas";
App::$strings["Remove term"] = "Eliminar término";
App::$strings["Saved Searches"] = "Búsquedas guardadas";
App::$strings["add"] = "añadir";
App::$strings["Saved Folders"] = "Carpetas guardadas";
App::$strings["Everything"] = "Todo";
App::$strings["Archives"] = "Hemeroteca";
App::$strings["Refresh"] = "Recargar";
App::$strings["Account settings"] = "Configuración de la cuenta";
App::$strings["Channel settings"] = "Configuración del canal";
App::$strings["Additional features"] = "Funcionalidades";
App::$strings["Feature/Addon settings"] = "Complementos";
App::$strings["Display settings"] = "Ajustes de visualización";
App::$strings["Manage locations"] = "Gestión de ubicaciones (clones) del canal";
App::$strings["Export channel"] = "Exportar canal";
App::$strings["Connected apps"] = "Aplicaciones (apps) conectadas";
App::$strings["Permission Groups"] = "Grupos de permisos";
App::$strings["Premium Channel Settings"] = "Configuración del canal premium";
App::$strings["Private Mail Menu"] = "Menú de correo privado";
App::$strings["Combined View"] = "Vista combinada";
App::$strings["Inbox"] = "Bandeja de entrada";
App::$strings["Outbox"] = "Bandeja de salida";
App::$strings["New Message"] = "Nuevo mensaje";
App::$strings["Conversations"] = "Conversaciones";
App::$strings["Received Messages"] = "Mensajes recibidos";
App::$strings["Sent Messages"] = "Enviar mensajes";
App::$strings["No messages."] = "Sin mensajes.";
App::$strings["Delete conversation"] = "Eliminar conversación";
App::$strings["Events Tools"] = "Gestión de eventos";
App::$strings["Export Calendar"] = "Exportar el calendario";
App::$strings["Import Calendar"] = "Importar un calendario";
App::$strings["Chatrooms"] = "Salas de chat";
App::$strings["Overview"] = "Resumen";
App::$strings["Chat Members"] = "Miembros del chat";
App::$strings["__ctx:wiki_history__ Message"] = "Mensaje";
App::$strings["Bookmarked Chatrooms"] = "Salas de chat preferidas";
App::$strings["Suggested Chatrooms"] = "Salas de chat sugeridas";
App::$strings["photo/image"] = "foto/imagen";
App::$strings["Click to show more"] = "Hacer clic para ver más";
App::$strings["Rating Tools"] = "Valoraciones";
App::$strings["Rate Me"] = "Valorar este canal";
App::$strings["View Ratings"] = "Mostrar las valoraciones";
App::$strings["Forums"] = "Foros";
App::$strings["Tasks"] = "Tareas";
App::$strings["Member registrations waiting for confirmation"] = "Inscripciones de nuevos miembros pendientes de aprobación";
App::$strings["Inspect queue"] = "Examinar la cola";
App::$strings["DB updates"] = "Actualizaciones de la base de datos";
App::$strings["Admin"] = "Administrador";
App::$strings["Plugin Features"] = "Extensiones";
App::$strings["Unable to obtain identity information from database"] = "No ha sido posible obtener información sobre la identidad desde la base de datos";
App::$strings["Empty name"] = "Nombre vacío";
App::$strings["Name too long"] = "Nombre demasiado largo";
App::$strings["No account identifier"] = "Ningún identificador de la cuenta";
App::$strings["Nickname is required."] = "Se requiere un sobrenombre (alias).";
App::$strings["Reserved nickname. Please choose another."] = "Sobrenombre en uso. Por favor, elija otro.";
App::$strings["Nickname has unsupported characters or is already being used on this site."] = "El alias contiene caracteres no admitidos o está ya en uso por otros miembros de este sitio.";
App::$strings["Unable to retrieve created identity"] = "No ha sido posible recuperar la identidad creada";
App::$strings["Default Profile"] = "Perfil principal";
App::$strings["Create New Profile"] = "Crear un nuevo perfil";
App::$strings["Visible to everybody"] = "Visible para todos";
App::$strings["Gender:"] = "Género:";
App::$strings["Homepage:"] = "Página personal:";
App::$strings["Online Now"] = "Ahora en línea";
App::$strings["Like this channel"] = "Me gusta este canal";
App::$strings["j F, Y"] = "j F Y";
App::$strings["j F"] = "j F";
App::$strings["Birthday:"] = "Cumpleaños:";
App::$strings["for %1\$d %2\$s"] = "por %1\$d %2\$s";
App::$strings["Sexual Preference:"] = "Orientación sexual:";
App::$strings["Tags:"] = "Etiquetas:";
App::$strings["Political Views:"] = "Posición política:";
App::$strings["Religion:"] = "Religión:";
App::$strings["Hobbies/Interests:"] = "Aficciones o intereses:";
App::$strings["Likes:"] = "Me gusta:";
App::$strings["Dislikes:"] = "No me gusta:";
App::$strings["Contact information and Social Networks:"] = "Información de contacto y redes sociales:";
App::$strings["My other channels:"] = "Mis otros canales:";
App::$strings["Musical interests:"] = "Preferencias musicales:";
App::$strings["Books, literature:"] = "Libros, literatura:";
App::$strings["Television:"] = "Televisión:";
App::$strings["Film/dance/culture/entertainment:"] = "Cine, danza, cultura, entretenimiento:";
App::$strings["Love/Romance:"] = "Vida sentimental o amorosa:";
App::$strings["Work/employment:"] = "Trabajo:";
App::$strings["School/education:"] = "Estudios:";
App::$strings["Like this thing"] = "Me gusta esto";
App::$strings["User '%s' deleted"] = "El usuario '%s' ha sido eliminado";
App::$strings["New window"] = "Nueva ventana";
App::$strings["Open the selected location in a different window or browser tab"] = "Abrir la dirección seleccionada en una ventana o pestaña aparte";
App::$strings["Help:"] = "Ayuda:";
App::$strings["Not Found"] = "No encontrado";
App::$strings["New Page"] = "Nueva página";
App::$strings["%d invitation available"] = array(
0 => "%d invitación pendiente",
@ -2736,7 +2626,18 @@ App::$strings["about a year"] = "alrededor de un año";
App::$strings["%d years"] = "%d años";
App::$strings[" "] = " ";
App::$strings["timeago.numbers"] = "timeago.numbers";
App::$strings["January"] = "enero";
App::$strings["February"] = "febrero";
App::$strings["March"] = "marzo";
App::$strings["April"] = "abril";
App::$strings["__ctx:long__ May"] = "mayo";
App::$strings["June"] = "junio";
App::$strings["July"] = "julio";
App::$strings["August"] = "agosto";
App::$strings["September"] = "septiembre";
App::$strings["October"] = "octubre";
App::$strings["November"] = "noviembre";
App::$strings["December"] = "diciembre";
App::$strings["Jan"] = "ene";
App::$strings["Feb"] = "feb";
App::$strings["Mar"] = "mar";
@ -2749,6 +2650,13 @@ App::$strings["Sep"] = "sep";
App::$strings["Oct"] = "oct";
App::$strings["Nov"] = "nov";
App::$strings["Dec"] = "dic";
App::$strings["Sunday"] = "domingo";
App::$strings["Monday"] = "lunes";
App::$strings["Tuesday"] = "martes";
App::$strings["Wednesday"] = "miércoles";
App::$strings["Thursday"] = "jueves";
App::$strings["Friday"] = "viernes";
App::$strings["Saturday"] = "sábado";
App::$strings["Sun"] = "dom";
App::$strings["Mon"] = "lun";
App::$strings["Tue"] = "mar";
@ -2765,8 +2673,6 @@ App::$strings["Directory Options"] = "Opciones del directorio";
App::$strings["Safe Mode"] = "Modo seguro";
App::$strings["Public Forums Only"] = "Solo foros públicos";
App::$strings["This Website Only"] = "Solo este sitio web";
App::$strings["Attachments:"] = "Ficheros adjuntos:";
App::$strings["\$Projectname event notification:"] = "Notificación de eventos de \$Projectname:";
App::$strings["view full size"] = "Ver en el tamaño original";
App::$strings["No Subject"] = "Sin asunto";
App::$strings["OStatus"] = "OStatus";
@ -2779,6 +2685,7 @@ App::$strings["XMPP/IM"] = "XMPP/IM";
App::$strings["MySpace"] = "MySpace";
App::$strings["%1\$s is now connected with %2\$s"] = "%1\$s ahora está conectado/a con %2\$s";
App::$strings["%1\$s poked %2\$s"] = "%1\$s ha dado un toque a %2\$s";
App::$strings["poked"] = "ha dado un toque a";
App::$strings["View %s's profile @ %s"] = "Ver el perfil @ %s de %s";
App::$strings["Categories:"] = "Temas:";
App::$strings["Filed under:"] = "Archivado bajo:";
@ -2874,8 +2781,6 @@ App::$strings["Privacy Groups"] = "Grupos de canales";
App::$strings["Edit group"] = "Editar grupo";
App::$strings["Add privacy group"] = "Añadir un grupo de canales";
App::$strings["Channels not in any privacy group"] = "Sin canales en ningún grupo";
App::$strings["Help:"] = "Ayuda:";
App::$strings["Not Found"] = "No encontrado";
App::$strings["(Unknown)"] = "(Desconocido)";
App::$strings["Visible to anybody on the internet."] = "Visible para cualquiera en internet.";
App::$strings["Visible to you only."] = "Visible sólo para usted.";
@ -2892,12 +2797,10 @@ App::$strings["profile photo"] = "foto del perfil";
App::$strings["[Edited %s]"] = "[se ha editado %s]";
App::$strings["__ctx:edit_activity__ Post"] = "Publicar";
App::$strings["__ctx:edit_activity__ Comment"] = "Comentar";
App::$strings["Attachments:"] = "Ficheros adjuntos:";
App::$strings["\$Projectname event notification:"] = "Notificación de eventos de \$Projectname:";
App::$strings["guest:"] = "invitado: ";
App::$strings["The form security token was not correct. This probably happened because the form has been opened for too long (>3 hours) before submitting it."] = "El \"token\" de seguridad del formulario no es correcto. Esto ha ocurrido probablemente porque el formulario ha estado abierto demasiado tiempo (>3 horas) antes de ser enviado";
App::$strings["Invalid data packet"] = "Paquete de datos no válido";
App::$strings["Unable to verify channel signature"] = "No ha sido posible de verificar la firma del canal";
App::$strings["Unable to verify site signature for %s"] = "No ha sido posible de verificar la firma del sitio para %s";
App::$strings["invalid target signature"] = "La firma recibida no es válida";
App::$strings["Remote authentication"] = "Acceder desde su servidor";
App::$strings["Click to authenticate to your home hub"] = "Pulsar para identificarse en su servidor de inicio";
App::$strings["Logout"] = "Finalizar sesión";
@ -2949,6 +2852,72 @@ App::$strings["Path not found."] = "Ruta no encontrada";
App::$strings["mkdir failed."] = "mkdir ha fallado.";
App::$strings["database storage failed."] = "el almacenamiento en la base de datos ha fallado.";
App::$strings["Empty path"] = "Ruta vacía";
App::$strings["prev"] = "anterior";
App::$strings["first"] = "primera";
App::$strings["last"] = "última";
App::$strings["next"] = "próxima";
App::$strings["older"] = "más antiguas";
App::$strings["newer"] = "más recientes";
App::$strings["No connections"] = "Sin conexiones";
App::$strings["View all %s connections"] = "Ver todas las %s conexiones";
App::$strings["poke"] = "un toque";
App::$strings["ping"] = "un \"ping\"";
App::$strings["pinged"] = "ha enviado un \"ping\" a";
App::$strings["prod"] = "una incitación ";
App::$strings["prodded"] = "ha incitado a ";
App::$strings["slap"] = "una bofetada ";
App::$strings["slapped"] = "ha abofeteado a ";
App::$strings["finger"] = "un \"finger\" ";
App::$strings["fingered"] = "envió un \"finger\" a";
App::$strings["rebuff"] = "un reproche";
App::$strings["rebuffed"] = "ha hecho un reproche a ";
App::$strings["happy"] = "feliz ";
App::$strings["sad"] = "triste ";
App::$strings["mellow"] = "tranquilo/a";
App::$strings["tired"] = "cansado/a ";
App::$strings["perky"] = "vivaz";
App::$strings["angry"] = "enfadado/a";
App::$strings["stupefied"] = "asombrado/a";
App::$strings["puzzled"] = "perplejo/a";
App::$strings["interested"] = "interesado/a";
App::$strings["bitter"] = "amargado/a";
App::$strings["cheerful"] = "alegre";
App::$strings["alive"] = "animado/a";
App::$strings["annoyed"] = "molesto/a";
App::$strings["anxious"] = "ansioso/a";
App::$strings["cranky"] = "de mal humor";
App::$strings["disturbed"] = "perturbado/a";
App::$strings["frustrated"] = "frustrado/a";
App::$strings["depressed"] = "deprimido/a";
App::$strings["motivated"] = "motivado/a";
App::$strings["relaxed"] = "relajado/a";
App::$strings["surprised"] = "sorprendido/a";
App::$strings["May"] = "mayo";
App::$strings["Unknown Attachment"] = "Adjunto no reconocido";
App::$strings["unknown"] = "desconocido";
App::$strings["remove category"] = "eliminar el tema";
App::$strings["remove from file"] = "eliminar del fichero";
App::$strings["Page layout"] = "Plantilla de la página";
App::$strings["You can create your own with the layouts tool"] = "Puede crear su propia disposición gráfica con la herramienta de plantillas";
App::$strings["Page content type"] = "Tipo de contenido de la página";
App::$strings["activity"] = "la actividad";
App::$strings["Design Tools"] = "Herramientas de diseño web";
App::$strings["Pages"] = "Páginas";
App::$strings["Import website..."] = "Importar un sitio web...";
App::$strings["Select folder to import"] = "Seleccionar la carpeta que se va a importar";
App::$strings["Import from a zipped folder:"] = "Importar desde una carpeta comprimida: ";
App::$strings["Import from cloud files:"] = "Importar desde los ficheros en la nube: ";
App::$strings["/cloud/channel/path/to/folder"] = "/cloud/canal/ruta/a la/carpeta";
App::$strings["Enter path to website files"] = "Ruta a los ficheros del sitio web";
App::$strings["Select folder"] = "Seleccionar la carpeta";
App::$strings["Export website..."] = "Exportar un sitio web...";
App::$strings["Export to a zip file"] = "Exportar a un fichero comprimido .zip";
App::$strings["website.zip"] = "sitio_web.zip";
App::$strings["Enter a name for the zip file."] = "Escriba un nombre para el fichero zip.";
App::$strings["Export to cloud files"] = "Exportar a la nube de ficheros";
App::$strings["/path/to/export/folder"] = "/ruta/para/exportar/carpeta";
App::$strings["Enter a path to a cloud files destination."] = "Escriba una ruta de destino a la nube de ficheros.";
App::$strings["Specify folder"] = "Especificar una carpeta";
App::$strings["Logged out."] = "Desconectado/a.";
App::$strings["Failed authentication"] = "Autenticación fallida.";
App::$strings["Channel is blocked on this site."] = "El canal está bloqueado en este sitio.";
@ -2970,6 +2939,10 @@ App::$strings[" by "] = "por";
App::$strings[" on "] = "en";
App::$strings["Embedded content"] = "Contenido incorporado";
App::$strings["Embedding disabled"] = "Incrustación deshabilitada";
App::$strings["Invalid data packet"] = "Paquete de datos no válido";
App::$strings["Unable to verify channel signature"] = "No ha sido posible de verificar la firma del canal";
App::$strings["Unable to verify site signature for %s"] = "No ha sido posible de verificar la firma del sitio para %s";
App::$strings["invalid target signature"] = "La firma recibida no es válida";
App::$strings["Can view my normal stream and posts"] = "Pueden verse mi actividad y publicaciones normales";
App::$strings["Can view my webpages"] = "Pueden verse mis páginas web";
App::$strings["Can post on my channel page (\"wall\")"] = "Pueden crearse entradas en mi página de inicio del canal (“muro”)";
@ -2988,8 +2961,6 @@ App::$strings["public profile"] = "el perfil público";
App::$strings["%1\$s changed %2\$s to &ldquo;%3\$s&rdquo;"] = "%1\$s ha cambiado %2\$s a &ldquo;%3\$s&rdquo;";
App::$strings["Visit %1\$s's %2\$s"] = "Visitar %2\$s de %1\$s";
App::$strings["%1\$s has an updated %2\$s, changing %3\$s."] = "%1\$s ha actualizado %2\$s, cambiando %3\$s.";
App::$strings["New window"] = "Nueva ventana";
App::$strings["Open the selected location in a different window or browser tab"] = "Abrir la dirección seleccionada en una ventana o pestaña aparte";
App::$strings["General Features"] = "Funcionalidades básicas";
App::$strings["Multiple Profiles"] = "Múltiples perfiles";
App::$strings["Ability to create multiple profiles"] = "Capacidad de crear múltiples perfiles";
@ -3069,6 +3040,43 @@ App::$strings["Photo storage failed."] = "La foto no ha podido ser guardada.";
App::$strings["a new photo"] = "una nueva foto";
App::$strings["__ctx:photo_upload__ %1\$s posted %2\$s to %3\$s"] = "%1\$s ha publicado %2\$s en %3\$s";
App::$strings["Upload New Photos"] = "Subir nuevas fotos";
App::$strings["Unable to obtain identity information from database"] = "No ha sido posible obtener información sobre la identidad desde la base de datos";
App::$strings["Empty name"] = "Nombre vacío";
App::$strings["Name too long"] = "Nombre demasiado largo";
App::$strings["No account identifier"] = "Ningún identificador de la cuenta";
App::$strings["Nickname is required."] = "Se requiere un sobrenombre (alias).";
App::$strings["Reserved nickname. Please choose another."] = "Sobrenombre en uso. Por favor, elija otro.";
App::$strings["Nickname has unsupported characters or is already being used on this site."] = "El alias contiene caracteres no admitidos o está ya en uso por otros miembros de este sitio.";
App::$strings["Unable to retrieve created identity"] = "No ha sido posible recuperar la identidad creada";
App::$strings["Default Profile"] = "Perfil principal";
App::$strings["Create New Profile"] = "Crear un nuevo perfil";
App::$strings["Visible to everybody"] = "Visible para todos";
App::$strings["Gender:"] = "Género:";
App::$strings["Homepage:"] = "Página personal:";
App::$strings["Online Now"] = "Ahora en línea";
App::$strings["Like this channel"] = "Me gusta este canal";
App::$strings["j F, Y"] = "j F Y";
App::$strings["j F"] = "j F";
App::$strings["Birthday:"] = "Cumpleaños:";
App::$strings["for %1\$d %2\$s"] = "por %1\$d %2\$s";
App::$strings["Sexual Preference:"] = "Orientación sexual:";
App::$strings["Tags:"] = "Etiquetas:";
App::$strings["Political Views:"] = "Posición política:";
App::$strings["Religion:"] = "Religión:";
App::$strings["Hobbies/Interests:"] = "Aficciones o intereses:";
App::$strings["Likes:"] = "Me gusta:";
App::$strings["Dislikes:"] = "No me gusta:";
App::$strings["Contact information and Social Networks:"] = "Información de contacto y redes sociales:";
App::$strings["My other channels:"] = "Mis otros canales:";
App::$strings["Musical interests:"] = "Preferencias musicales:";
App::$strings["Books, literature:"] = "Libros, literatura:";
App::$strings["Television:"] = "Televisión:";
App::$strings["Film/dance/culture/entertainment:"] = "Cine, danza, cultura, entretenimiento:";
App::$strings["Love/Romance:"] = "Vida sentimental o amorosa:";
App::$strings["Work/employment:"] = "Trabajo:";
App::$strings["School/education:"] = "Estudios:";
App::$strings["Like this thing"] = "Me gusta esto";
App::$strings["User '%s' deleted"] = "El usuario '%s' ha sido eliminado";
App::$strings["Source channel not found."] = "No se ha encontrado el canal de origen.";
App::$strings["Focus (Hubzilla default)"] = "Focus (predefinido)";
App::$strings["Theme settings"] = "Ajustes del tema";