Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M3P2 HTML Generator
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
12
Issues
12
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
M3P2
M3P2 HTML Generator
Commits
4a98d5fe
Commit
4a98d5fe
authored
Apr 05, 2020
by
Administrator
💬
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Continue updating to new Parsedown engine.
parent
7e835b49
Pipeline
#1834
passed with stage
in 1 minute and 3 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
2091 additions
and
0 deletions
+2091
-0
aliases.php
system/aliases.php
+5
-0
Parsedown.php
system/src/Grav/Framework/Parsedown/Parsedown.php
+1554
-0
ParsedownExtra.php
system/src/Grav/Framework/Parsedown/ParsedownExtra.php
+532
-0
No files found.
system/aliases.php
0 → 100644
View file @
4a98d5fe
<?php
/** Moved from non-namespaced classes to Grav Framework */
class_alias
(
Grav\Framework\Parsedown\Parsedown
::
class
,
'\Parsedown'
);
class_alias
(
Grav\Framework\Parsedown\ParsedownExtra
::
class
,
'\ParsedownExtra'
);
system/src/Grav/Framework/Parsedown/Parsedown.php
0 → 100644
View file @
4a98d5fe
<?php
/**
* @package Grav\Framework\Parsedown
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace
Grav\Framework\Parsedown
;
/*
* Parsedown
* http://parsedown.org
*
* (c) Emanuil Rusev
* http://erusev.com
*
* This file ported from officiall Parsedown repo and kept for compatibility.
*/
class
Parsedown
{
# ~
const
version
=
'1.6.0'
;
# ~
function
text
(
$text
)
{
# make sure no definitions are set
$this
->
DefinitionData
=
array
();
# standardize line breaks
$text
=
str_replace
(
array
(
"
\r\n
"
,
"
\r
"
),
"
\n
"
,
$text
);
# remove surrounding line breaks
$text
=
trim
(
$text
,
"
\n
"
);
# split text into lines
$lines
=
explode
(
"
\n
"
,
$text
);
# iterate through lines to identify blocks
$markup
=
$this
->
lines
(
$lines
);
# trim line breaks
$markup
=
trim
(
$markup
,
"
\n
"
);
return
$markup
;
}
#
# Setters
#
function
setBreaksEnabled
(
$breaksEnabled
)
{
$this
->
breaksEnabled
=
$breaksEnabled
;
return
$this
;
}
protected
$breaksEnabled
;
function
setMarkupEscaped
(
$markupEscaped
)
{
$this
->
markupEscaped
=
$markupEscaped
;
return
$this
;
}
protected
$markupEscaped
;
function
setUrlsLinked
(
$urlsLinked
)
{
$this
->
urlsLinked
=
$urlsLinked
;
return
$this
;
}
protected
$urlsLinked
=
true
;
#
# Lines
#
protected
$BlockTypes
=
array
(
'#'
=>
array
(
'Header'
),
'*'
=>
array
(
'Rule'
,
'List'
),
'+'
=>
array
(
'List'
),
'-'
=>
array
(
'SetextHeader'
,
'Table'
,
'Rule'
,
'List'
),
'0'
=>
array
(
'List'
),
'1'
=>
array
(
'List'
),
'2'
=>
array
(
'List'
),
'3'
=>
array
(
'List'
),
'4'
=>
array
(
'List'
),
'5'
=>
array
(
'List'
),
'6'
=>
array
(
'List'
),
'7'
=>
array
(
'List'
),
'8'
=>
array
(
'List'
),
'9'
=>
array
(
'List'
),
':'
=>
array
(
'Table'
),
'<'
=>
array
(
'Comment'
,
'Markup'
),
'='
=>
array
(
'SetextHeader'
),
'>'
=>
array
(
'Quote'
),
'['
=>
array
(
'Reference'
),
'_'
=>
array
(
'Rule'
),
'`'
=>
array
(
'FencedCode'
),
'|'
=>
array
(
'Table'
),
'~'
=>
array
(
'FencedCode'
),
);
# ~
protected
$unmarkedBlockTypes
=
array
(
'Code'
,
);
#
# Blocks
#
protected
function
lines
(
array
$lines
)
{
$CurrentBlock
=
null
;
foreach
(
$lines
as
$line
)
{
if
(
chop
(
$line
)
===
''
)
{
if
(
isset
(
$CurrentBlock
))
{
$CurrentBlock
[
'interrupted'
]
=
true
;
}
continue
;
}
if
(
strpos
(
$line
,
"
\t
"
)
!==
false
)
{
$parts
=
explode
(
"
\t
"
,
$line
);
$line
=
$parts
[
0
];
unset
(
$parts
[
0
]);
foreach
(
$parts
as
$part
)
{
$shortage
=
4
-
mb_strlen
(
$line
,
'utf-8'
)
%
4
;
$line
.=
str_repeat
(
' '
,
$shortage
);
$line
.=
$part
;
}
}
$indent
=
0
;
while
(
isset
(
$line
[
$indent
])
and
$line
[
$indent
]
===
' '
)
{
$indent
++
;
}
$text
=
$indent
>
0
?
substr
(
$line
,
$indent
)
:
$line
;
# ~
$Line
=
array
(
'body'
=>
$line
,
'indent'
=>
$indent
,
'text'
=>
$text
);
# ~
if
(
isset
(
$CurrentBlock
[
'continuable'
]))
{
$Block
=
$this
->
{
'block'
.
$CurrentBlock
[
'type'
]
.
'Continue'
}(
$Line
,
$CurrentBlock
);
if
(
isset
(
$Block
))
{
$CurrentBlock
=
$Block
;
continue
;
}
else
{
if
(
$this
->
isBlockCompletable
(
$CurrentBlock
[
'type'
]))
{
$CurrentBlock
=
$this
->
{
'block'
.
$CurrentBlock
[
'type'
]
.
'Complete'
}(
$CurrentBlock
);
}
}
}
# ~
$marker
=
$text
[
0
];
# ~
$blockTypes
=
$this
->
unmarkedBlockTypes
;
if
(
isset
(
$this
->
BlockTypes
[
$marker
]))
{
foreach
(
$this
->
BlockTypes
[
$marker
]
as
$blockType
)
{
$blockTypes
[]
=
$blockType
;
}
}
#
# ~
foreach
(
$blockTypes
as
$blockType
)
{
$Block
=
$this
->
{
'block'
.
$blockType
}(
$Line
,
$CurrentBlock
);
if
(
isset
(
$Block
))
{
$Block
[
'type'
]
=
$blockType
;
if
(
!
isset
(
$Block
[
'identified'
]))
{
$Blocks
[]
=
$CurrentBlock
;
$Block
[
'identified'
]
=
true
;
}
if
(
$this
->
isBlockContinuable
(
$blockType
))
{
$Block
[
'continuable'
]
=
true
;
}
$CurrentBlock
=
$Block
;
continue
2
;
}
}
# ~
if
(
isset
(
$CurrentBlock
)
and
!
isset
(
$CurrentBlock
[
'type'
])
and
!
isset
(
$CurrentBlock
[
'interrupted'
]))
{
$CurrentBlock
[
'element'
][
'text'
]
.=
"
\n
"
.
$text
;
}
else
{
$Blocks
[]
=
$CurrentBlock
;
$CurrentBlock
=
$this
->
paragraph
(
$Line
);
$CurrentBlock
[
'identified'
]
=
true
;
}
}
# ~
if
(
isset
(
$CurrentBlock
[
'continuable'
])
and
$this
->
isBlockCompletable
(
$CurrentBlock
[
'type'
]))
{
$CurrentBlock
=
$this
->
{
'block'
.
$CurrentBlock
[
'type'
]
.
'Complete'
}(
$CurrentBlock
);
}
# ~
$Blocks
[]
=
$CurrentBlock
;
unset
(
$Blocks
[
0
]);
# ~
$markup
=
''
;
foreach
(
$Blocks
as
$Block
)
{
if
(
isset
(
$Block
[
'hidden'
]))
{
continue
;
}
$markup
.=
"
\n
"
;
$markup
.=
isset
(
$Block
[
'markup'
])
?
$Block
[
'markup'
]
:
$this
->
element
(
$Block
[
'element'
]);
}
$markup
.=
"
\n
"
;
# ~
return
$markup
;
}
protected
function
isBlockContinuable
(
$Type
)
{
return
method_exists
(
$this
,
'block'
.
$Type
.
'Continue'
);
}
protected
function
isBlockCompletable
(
$Type
)
{
return
method_exists
(
$this
,
'block'
.
$Type
.
'Complete'
);
}
#
# Code
protected
function
blockCode
(
$Line
,
$Block
=
null
)
{
if
(
isset
(
$Block
)
and
!
isset
(
$Block
[
'type'
])
and
!
isset
(
$Block
[
'interrupted'
]))
{
return
;
}
if
(
$Line
[
'indent'
]
>=
4
)
{
$text
=
substr
(
$Line
[
'body'
],
4
);
$Block
=
array
(
'element'
=>
array
(
'name'
=>
'pre'
,
'handler'
=>
'element'
,
'text'
=>
array
(
'name'
=>
'code'
,
'text'
=>
$text
,
),
),
);
return
$Block
;
}
}
protected
function
blockCodeContinue
(
$Line
,
$Block
)
{
if
(
$Line
[
'indent'
]
>=
4
)
{
if
(
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'element'
][
'text'
][
'text'
]
.=
"
\n
"
;
unset
(
$Block
[
'interrupted'
]);
}
$Block
[
'element'
][
'text'
][
'text'
]
.=
"
\n
"
;
$text
=
substr
(
$Line
[
'body'
],
4
);
$Block
[
'element'
][
'text'
][
'text'
]
.=
$text
;
return
$Block
;
}
}
protected
function
blockCodeComplete
(
$Block
)
{
$text
=
$Block
[
'element'
][
'text'
][
'text'
];
$text
=
htmlspecialchars
(
$text
,
ENT_NOQUOTES
,
'UTF-8'
);
$Block
[
'element'
][
'text'
][
'text'
]
=
$text
;
return
$Block
;
}
#
# Comment
protected
function
blockComment
(
$Line
)
{
if
(
$this
->
markupEscaped
)
{
return
;
}
if
(
isset
(
$Line
[
'text'
][
3
])
and
$Line
[
'text'
][
3
]
===
'-'
and
$Line
[
'text'
][
2
]
===
'-'
and
$Line
[
'text'
][
1
]
===
'!'
)
{
$Block
=
array
(
'markup'
=>
$Line
[
'body'
],
);
if
(
preg_match
(
'/-->$/'
,
$Line
[
'text'
]))
{
$Block
[
'closed'
]
=
true
;
}
return
$Block
;
}
}
protected
function
blockCommentContinue
(
$Line
,
array
$Block
)
{
if
(
isset
(
$Block
[
'closed'
]))
{
return
;
}
$Block
[
'markup'
]
.=
"
\n
"
.
$Line
[
'body'
];
if
(
preg_match
(
'/-->$/'
,
$Line
[
'text'
]))
{
$Block
[
'closed'
]
=
true
;
}
return
$Block
;
}
#
# Fenced Code
protected
function
blockFencedCode
(
$Line
)
{
if
(
preg_match
(
'/^['
.
$Line
[
'text'
][
0
]
.
']{3,}[ ]*([\w-]+)?[ ]*$/'
,
$Line
[
'text'
],
$matches
))
{
$Element
=
array
(
'name'
=>
'code'
,
'text'
=>
''
,
);
if
(
isset
(
$matches
[
1
]))
{
$class
=
'language-'
.
$matches
[
1
];
$Element
[
'attributes'
]
=
array
(
'class'
=>
$class
,
);
}
$Block
=
array
(
'char'
=>
$Line
[
'text'
][
0
],
'element'
=>
array
(
'name'
=>
'pre'
,
'handler'
=>
'element'
,
'text'
=>
$Element
,
),
);
return
$Block
;
}
}
protected
function
blockFencedCodeContinue
(
$Line
,
$Block
)
{
if
(
isset
(
$Block
[
'complete'
]))
{
return
;
}
if
(
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'element'
][
'text'
][
'text'
]
.=
"
\n
"
;
unset
(
$Block
[
'interrupted'
]);
}
if
(
preg_match
(
'/^'
.
$Block
[
'char'
]
.
'{3,}[ ]*$/'
,
$Line
[
'text'
]))
{
$Block
[
'element'
][
'text'
][
'text'
]
=
substr
(
$Block
[
'element'
][
'text'
][
'text'
],
1
);
$Block
[
'complete'
]
=
true
;
return
$Block
;
}
$Block
[
'element'
][
'text'
][
'text'
]
.=
"
\n
"
.
$Line
[
'body'
];
return
$Block
;
}
protected
function
blockFencedCodeComplete
(
$Block
)
{
$text
=
$Block
[
'element'
][
'text'
][
'text'
];
$text
=
htmlspecialchars
(
$text
,
ENT_NOQUOTES
,
'UTF-8'
);
$Block
[
'element'
][
'text'
][
'text'
]
=
$text
;
return
$Block
;
}
#
# Header
protected
function
blockHeader
(
$Line
)
{
if
(
isset
(
$Line
[
'text'
][
1
]))
{
$level
=
1
;
while
(
isset
(
$Line
[
'text'
][
$level
])
and
$Line
[
'text'
][
$level
]
===
'#'
)
{
$level
++
;
}
if
(
$level
>
6
)
{
return
;
}
$text
=
trim
(
$Line
[
'text'
],
'# '
);
$Block
=
array
(
'element'
=>
array
(
'name'
=>
'h'
.
min
(
6
,
$level
),
'text'
=>
$text
,
'handler'
=>
'line'
,
),
);
return
$Block
;
}
}
#
# List
protected
function
blockList
(
$Line
)
{
list
(
$name
,
$pattern
)
=
$Line
[
'text'
][
0
]
<=
'-'
?
array
(
'ul'
,
'[*+-]'
)
:
array
(
'ol'
,
'[0-9]+[.]'
);
if
(
preg_match
(
'/^('
.
$pattern
.
'[ ]+)(.*)/'
,
$Line
[
'text'
],
$matches
))
{
$Block
=
array
(
'indent'
=>
$Line
[
'indent'
],
'pattern'
=>
$pattern
,
'element'
=>
array
(
'name'
=>
$name
,
'handler'
=>
'elements'
,
),
);
if
(
$name
===
'ol'
)
{
$listStart
=
stristr
(
$matches
[
0
],
'.'
,
true
);
if
(
$listStart
!==
'1'
)
{
$Block
[
'element'
][
'attributes'
]
=
array
(
'start'
=>
$listStart
);
}
}
$Block
[
'li'
]
=
array
(
'name'
=>
'li'
,
'handler'
=>
'li'
,
'text'
=>
array
(
$matches
[
2
],
),
);
$Block
[
'element'
][
'text'
]
[]
=
&
$Block
[
'li'
];
return
$Block
;
}
}
protected
function
blockListContinue
(
$Line
,
array
$Block
)
{
if
(
$Block
[
'indent'
]
===
$Line
[
'indent'
]
and
preg_match
(
'/^'
.
$Block
[
'pattern'
]
.
'(?:[ ]+(.*)|$)/'
,
$Line
[
'text'
],
$matches
))
{
if
(
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'li'
][
'text'
]
[]
=
''
;
unset
(
$Block
[
'interrupted'
]);
}
unset
(
$Block
[
'li'
]);
$text
=
isset
(
$matches
[
1
])
?
$matches
[
1
]
:
''
;
$Block
[
'li'
]
=
array
(
'name'
=>
'li'
,
'handler'
=>
'li'
,
'text'
=>
array
(
$text
,
),
);
$Block
[
'element'
][
'text'
]
[]
=
&
$Block
[
'li'
];
return
$Block
;
}
if
(
$Line
[
'text'
][
0
]
===
'['
and
$this
->
blockReference
(
$Line
))
{
return
$Block
;
}
if
(
!
isset
(
$Block
[
'interrupted'
]))
{
$text
=
preg_replace
(
'/^[ ]{0,4}/'
,
''
,
$Line
[
'body'
]);
$Block
[
'li'
][
'text'
]
[]
=
$text
;
return
$Block
;
}
if
(
$Line
[
'indent'
]
>
0
)
{
$Block
[
'li'
][
'text'
]
[]
=
''
;
$text
=
preg_replace
(
'/^[ ]{0,4}/'
,
''
,
$Line
[
'body'
]);
$Block
[
'li'
][
'text'
]
[]
=
$text
;
unset
(
$Block
[
'interrupted'
]);
return
$Block
;
}
}
#
# Quote
protected
function
blockQuote
(
$Line
)
{
if
(
preg_match
(
'/^>[ ]?(.*)/'
,
$Line
[
'text'
],
$matches
))
{
$Block
=
array
(
'element'
=>
array
(
'name'
=>
'blockquote'
,
'handler'
=>
'lines'
,
'text'
=>
(
array
)
$matches
[
1
],
),
);
return
$Block
;
}
}
protected
function
blockQuoteContinue
(
$Line
,
array
$Block
)
{
if
(
$Line
[
'text'
][
0
]
===
'>'
and
preg_match
(
'/^>[ ]?(.*)/'
,
$Line
[
'text'
],
$matches
))
{
if
(
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'element'
][
'text'
]
[]
=
''
;
unset
(
$Block
[
'interrupted'
]);
}
$Block
[
'element'
][
'text'
]
[]
=
$matches
[
1
];
return
$Block
;
}
if
(
!
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'element'
][
'text'
]
[]
=
$Line
[
'text'
];
return
$Block
;
}
}
#
# Rule
protected
function
blockRule
(
$Line
)
{
if
(
preg_match
(
'/^(['
.
$Line
[
'text'
][
0
]
.
'])([ ]*\1){2,}[ ]*$/'
,
$Line
[
'text'
]))
{
$Block
=
array
(
'element'
=>
array
(
'name'
=>
'hr'
),
);
return
$Block
;
}
}
#
# Setext
protected
function
blockSetextHeader
(
$Line
,
array
$Block
=
null
)
{
if
(
!
isset
(
$Block
)
or
isset
(
$Block
[
'type'
])
or
isset
(
$Block
[
'interrupted'
]))
{
return
;
}
if
(
chop
(
$Line
[
'text'
],
$Line
[
'text'
][
0
])
===
''
)
{
$Block
[
'element'
][
'name'
]
=
$Line
[
'text'
][
0
]
===
'='
?
'h1'
:
'h2'
;
return
$Block
;
}
}
#
# Markup
protected
function
blockMarkup
(
$Line
)
{
if
(
$this
->
markupEscaped
)
{
return
;
}
if
(
preg_match
(
'/^<(\w*)(?:[ ]*'
.
$this
->
regexHtmlAttribute
.
')*[ ]*(\/)?>/'
,
$Line
[
'text'
],
$matches
))
{
$element
=
strtolower
(
$matches
[
1
]);
if
(
in_array
(
$element
,
$this
->
textLevelElements
))
{
return
;
}
$Block
=
array
(
'name'
=>
$matches
[
1
],
'depth'
=>
0
,
'markup'
=>
$Line
[
'text'
],
);
$length
=
strlen
(
$matches
[
0
]);
$remainder
=
substr
(
$Line
[
'text'
],
$length
);
if
(
trim
(
$remainder
)
===
''
)
{
if
(
isset
(
$matches
[
2
])
or
in_array
(
$matches
[
1
],
$this
->
voidElements
))
{
$Block
[
'closed'
]
=
true
;
$Block
[
'void'
]
=
true
;
}
}
else
{
if
(
isset
(
$matches
[
2
])
or
in_array
(
$matches
[
1
],
$this
->
voidElements
))
{
return
;
}
if
(
preg_match
(
'/<\/'
.
$matches
[
1
]
.
'>[ ]*$/i'
,
$remainder
))
{
$Block
[
'closed'
]
=
true
;
}
}
return
$Block
;
}
}
protected
function
blockMarkupContinue
(
$Line
,
array
$Block
)
{
if
(
isset
(
$Block
[
'closed'
]))
{
return
;
}
if
(
preg_match
(
'/^<'
.
$Block
[
'name'
]
.
'(?:[ ]*'
.
$this
->
regexHtmlAttribute
.
')*[ ]*>/i'
,
$Line
[
'text'
]))
# open
{
$Block
[
'depth'
]
++
;
}
if
(
preg_match
(
'/(.*?)<\/'
.
$Block
[
'name'
]
.
'>[ ]*$/i'
,
$Line
[
'text'
],
$matches
))
# close
{
if
(
$Block
[
'depth'
]
>
0
)
{
$Block
[
'depth'
]
--
;
}
else
{
$Block
[
'closed'
]
=
true
;
}
}
if
(
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'markup'
]
.=
"
\n
"
;
unset
(
$Block
[
'interrupted'
]);
}
$Block
[
'markup'
]
.=
"
\n
"
.
$Line
[
'body'
];
return
$Block
;
}
#
# Reference
protected
function
blockReference
(
$Line
)
{
if
(
preg_match
(
'/^\[(.+?)\]:[ ]*<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/'
,
$Line
[
'text'
],
$matches
))
{
$id
=
strtolower
(
$matches
[
1
]);
$Data
=
array
(
'url'
=>
$matches
[
2
],
'title'
=>
null
,
);
if
(
isset
(
$matches
[
3
]))
{
$Data
[
'title'
]
=
$matches
[
3
];
}
$this
->
DefinitionData
[
'Reference'
][
$id
]
=
$Data
;
$Block
=
array
(
'hidden'
=>
true
,
);
return
$Block
;
}
}
#
# Table
protected
function
blockTable
(
$Line
,
array
$Block
=
null
)
{
if
(
!
isset
(
$Block
)
or
isset
(
$Block
[
'type'
])
or
isset
(
$Block
[
'interrupted'
]))
{
return
;
}
if
(
strpos
(
$Block
[
'element'
][
'text'
],
'|'
)
!==
false
and
chop
(
$Line
[
'text'
],
' -:|'
)
===
''
)
{
$alignments
=
array
();
$divider
=
$Line
[
'text'
];
$divider
=
trim
(
$divider
);
$divider
=
trim
(
$divider
,
'|'
);
$dividerCells
=
explode
(
'|'
,
$divider
);
foreach
(
$dividerCells
as
$dividerCell
)
{
$dividerCell
=
trim
(
$dividerCell
);
if
(
$dividerCell
===
''
)
{
continue
;
}
$alignment
=
null
;
if
(
$dividerCell
[
0
]
===
':'
)
{
$alignment
=
'left'
;
}
if
(
substr
(
$dividerCell
,
-
1
)
===
':'
)
{
$alignment
=
$alignment
===
'left'
?
'center'
:
'right'
;
}
$alignments
[]
=
$alignment
;
}
# ~
$HeaderElements
=
array
();
$header
=
$Block
[
'element'
][
'text'
];
$header
=
trim
(
$header
);
$header
=
trim
(
$header
,
'|'
);
$headerCells
=
explode
(
'|'
,
$header
);
foreach
(
$headerCells
as
$index
=>
$headerCell
)
{
$headerCell
=
trim
(
$headerCell
);
$HeaderElement
=
array
(
'name'
=>
'th'
,
'text'
=>
$headerCell
,
'handler'
=>
'line'
,
);
if
(
isset
(
$alignments
[
$index
]))
{
$alignment
=
$alignments
[
$index
];
$HeaderElement
[
'attributes'
]
=
array
(
'style'
=>
'text-align: '
.
$alignment
.
';'
,
);
}
$HeaderElements
[]
=
$HeaderElement
;
}
# ~
$Block
=
array
(
'alignments'
=>
$alignments
,
'identified'
=>
true
,
'element'
=>
array
(
'name'
=>
'table'
,
'handler'
=>
'elements'
,
),
);
$Block
[
'element'
][
'text'
]
[]
=
array
(
'name'
=>
'thead'
,
'handler'
=>
'elements'
,
);
$Block
[
'element'
][
'text'
]
[]
=
array
(
'name'
=>
'tbody'
,
'handler'
=>
'elements'
,
'text'
=>
array
(),
);
$Block
[
'element'
][
'text'
][
0
][
'text'
]
[]
=
array
(
'name'
=>
'tr'
,
'handler'
=>
'elements'
,
'text'
=>
$HeaderElements
,
);
return
$Block
;
}
}
protected
function
blockTableContinue
(
$Line
,
array
$Block
)
{
if
(
isset
(
$Block
[
'interrupted'
]))
{
return
;
}
if
(
$Line
[
'text'
][
0
]
===
'|'
or
strpos
(
$Line
[
'text'
],
'|'
))
{
$Elements
=
array
();
$row
=
$Line
[
'text'
];
$row
=
trim
(
$row
);
$row
=
trim
(
$row
,
'|'
);
preg_match_all
(
'/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/'
,
$row
,
$matches
);
foreach
(
$matches
[
0
]
as
$index
=>
$cell
)
{
$cell
=
trim
(
$cell
);
$Element
=
array
(
'name'
=>
'td'
,
'handler'
=>
'line'
,
'text'
=>
$cell
,
);
if
(
isset
(
$Block
[
'alignments'
][
$index
]))
{
$Element
[
'attributes'
]
=
array
(
'style'
=>
'text-align: '
.
$Block
[
'alignments'
][
$index
]
.
';'
,
);
}
$Elements
[]
=
$Element
;
}
$Element
=
array
(
'name'
=>
'tr'
,
'handler'
=>
'elements'
,
'text'
=>
$Elements
,
);
$Block
[
'element'
][
'text'
][
1
][
'text'
]
[]
=
$Element
;
return
$Block
;
}
}
#
# ~
#
protected
function
paragraph
(
$Line
)
{
$Block
=
array
(
'element'
=>
array
(
'name'
=>
'p'
,
'text'
=>
$Line
[
'text'
],
'handler'
=>
'line'
,
),
);
return
$Block
;
}
#
# Inline Elements
#
protected
$InlineTypes
=
array
(
'"'
=>
array
(
'SpecialCharacter'
),
'!'
=>
array
(
'Image'
),
'&'
=>
array
(
'SpecialCharacter'
),
'*'
=>
array
(
'Emphasis'
),
':'
=>
array
(
'Url'
),
'<'
=>
array
(
'UrlTag'
,
'EmailTag'
,
'Markup'
,
'SpecialCharacter'
),
'>'
=>
array
(
'SpecialCharacter'
),
'['
=>
array
(
'Link'
),
'_'
=>
array
(
'Emphasis'
),
'`'
=>
array
(
'Code'
),
'~'
=>
array
(
'Strikethrough'
),
'\\'
=>
array
(
'EscapeSequence'
),
);
# ~
protected
$inlineMarkerList
=
'!"*_&[:<>`~\\'
;
#
# ~
#
public
function
line
(
$text
)
{
$markup
=
''
;
# $excerpt is based on the first occurrence of a marker
while
(
$excerpt
=
strpbrk
(
$text
,
$this
->
inlineMarkerList
))
{
$marker
=
$excerpt
[
0
];
$markerPosition
=
strpos
(
$text
,
$marker
);
$Excerpt
=
array
(
'text'
=>
$excerpt
,
'context'
=>
$text
);
foreach
(
$this
->
InlineTypes
[
$marker
]
as
$inlineType
)
{
$Inline
=
$this
->
{
'inline'
.
$inlineType
}(
$Excerpt
);
if
(
!
isset
(
$Inline
))
{
continue
;
}
# makes sure that the inline belongs to "our" marker
if
(
isset
(
$Inline
[
'position'
])
and
$Inline
[
'position'
]
>
$markerPosition
)
{
continue
;
}
# sets a default inline position
if
(
!
isset
(
$Inline
[
'position'
]))
{
$Inline
[
'position'
]
=
$markerPosition
;
}
# the text that comes before the inline
$unmarkedText
=
substr
(
$text
,
0
,
$Inline
[
'position'
]);
# compile the unmarked text
$markup
.=
$this
->
unmarkedText
(
$unmarkedText
);
# compile the inline
$markup
.=
isset
(
$Inline
[
'markup'
])
?
$Inline
[
'markup'
]
:
$this
->
element
(
$Inline
[
'element'
]);
# remove the examined text
$text
=
substr
(
$text
,
$Inline
[
'position'
]
+
$Inline
[
'extent'
]);
continue
2
;
}
# the marker does not belong to an inline
$unmarkedText
=
substr
(
$text
,
0
,
$markerPosition
+
1
);
$markup
.=
$this
->
unmarkedText
(
$unmarkedText
);
$text
=
substr
(
$text
,
$markerPosition
+
1
);
}
$markup
.=
$this
->
unmarkedText
(
$text
);
return
$markup
;
}
#
# ~
#
protected
function
inlineCode
(
$Excerpt
)
{
$marker
=
$Excerpt
[
'text'
][
0
];
if
(
preg_match
(
'/^('
.
$marker
.
'+)[ ]*(.+?)[ ]*(?<!'
.
$marker
.
')\1(?!'
.
$marker
.
')/s'
,
$Excerpt
[
'text'
],
$matches
))
{
$text
=
$matches
[
2
];
$text
=
htmlspecialchars
(
$text
,
ENT_NOQUOTES
,
'UTF-8'
);
$text
=
preg_replace
(
"/[ ]*
\n
/"
,
' '
,
$text
);
return
array
(
'extent'
=>
strlen
(
$matches
[
0
]),
'element'
=>
array
(
'name'
=>
'code'
,
'text'
=>
$text
,
),
);
}
}
protected
function
inlineEmailTag
(
$Excerpt
)
{
if
(
strpos
(
$Excerpt
[
'text'
],
'>'
)
!==
false
and
preg_match
(
'/^<((mailto:)?\S+?@\S+?)>/i'
,
$Excerpt
[
'text'
],
$matches
))
{
$url
=
$matches
[
1
];
if
(
!
isset
(
$matches
[
2
]))
{
$url
=
'mailto:'
.
$url
;
}
return
array
(
'extent'
=>
strlen
(
$matches
[
0
]),
'element'
=>
array
(
'name'
=>
'a'
,
'text'
=>
$matches
[
1
],
'attributes'
=>
array
(
'href'
=>
$url
,
),
),
);
}
}
protected
function
inlineEmphasis
(
$Excerpt
)
{
if
(
!
isset
(
$Excerpt
[
'text'
][
1
]))
{
return
;
}
$marker
=
$Excerpt
[
'text'
][
0
];
if
(
$Excerpt
[
'text'
][
1
]
===
$marker
and
preg_match
(
$this
->
StrongRegex
[
$marker
],
$Excerpt
[
'text'
],
$matches
))
{
$emphasis
=
'strong'
;
}
elseif
(
preg_match
(
$this
->
EmRegex
[
$marker
],
$Excerpt
[
'text'
],
$matches
))
{
$emphasis
=
'em'
;
}
else
{
return
;
}
return
array
(
'extent'
=>
strlen
(
$matches
[
0
]),
'element'
=>
array
(
'name'
=>
$emphasis
,
'handler'
=>
'line'
,
'text'
=>
$matches
[
1
],
),
);
}
protected
function
inlineEscapeSequence
(
$Excerpt
)
{
if
(
isset
(
$Excerpt
[
'text'
][
1
])
and
in_array
(
$Excerpt
[
'text'
][
1
],
$this
->
specialCharacters
))
{
return
array
(
'markup'
=>
$Excerpt
[
'text'
][
1
],
'extent'
=>
2
,
);
}
}
protected
function
inlineImage
(
$Excerpt
)
{
if
(
!
isset
(
$Excerpt
[
'text'
][
1
])
or
$Excerpt
[
'text'
][
1
]
!==
'['
)
{
return
;
}
$Excerpt
[
'text'
]
=
substr
(
$Excerpt
[
'text'
],
1
);
$Link
=
$this
->
inlineLink
(
$Excerpt
);
if
(
$Link
===
null
)
{
return
;
}
$Inline
=
array
(
'extent'
=>
$Link
[
'extent'
]
+
1
,
'element'
=>
array
(
'name'
=>
'img'
,
'attributes'
=>
array
(
'src'
=>
$Link
[
'element'
][
'attributes'
][
'href'
],
'alt'
=>
$Link
[
'element'
][
'text'
],
),
),
);
$Inline
[
'element'
][
'attributes'
]
+=
$Link
[
'element'
][
'attributes'
];
unset
(
$Inline
[
'element'
][
'attributes'
][
'href'
]);
return
$Inline
;
}
protected
function
inlineLink
(
$Excerpt
)
{
$Element
=
array
(
'name'
=>
'a'
,
'handler'
=>
'line'
,
'text'
=>
null
,
'attributes'
=>
array
(
'href'
=>
null
,
'title'
=>
null
,
),
);
$extent
=
0
;
$remainder
=
$Excerpt
[
'text'
];
if
(
preg_match
(
'/\[((?:[^][]++|(?R))*+)\]/'
,
$remainder
,
$matches
))
{
$Element
[
'text'
]
=
$matches
[
1
];
$extent
+=
strlen
(
$matches
[
0
]);
$remainder
=
substr
(
$remainder
,
$extent
);
}
else
{
return
;
}
if
(
preg_match
(
'/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/'
,
$remainder
,
$matches
))
{
$Element
[
'attributes'
][
'href'
]
=
$matches
[
1
];
if
(
isset
(
$matches
[
2
]))
{
$Element
[
'attributes'
][
'title'
]
=
substr
(
$matches
[
2
],
1
,
-
1
);
}
$extent
+=
strlen
(
$matches
[
0
]);
}
else
{
if
(
preg_match
(
'/^\s*\[(.*?)\]/'
,
$remainder
,
$matches
))
{
$definition
=
strlen
(
$matches
[
1
])
?
$matches
[
1
]
:
$Element
[
'text'
];
$definition
=
strtolower
(
$definition
);
$extent
+=
strlen
(
$matches
[
0
]);
}
else
{
$definition
=
strtolower
(
$Element
[
'text'
]);
}
if
(
!
isset
(
$this
->
DefinitionData
[
'Reference'
][
$definition
]))
{
return
;
}
$Definition
=
$this
->
DefinitionData
[
'Reference'
][
$definition
];
$Element
[
'attributes'
][
'href'
]
=
$Definition
[
'url'
];
$Element
[
'attributes'
][
'title'
]
=
$Definition
[
'title'
];
}
$Element
[
'attributes'
][
'href'
]
=
str_replace
(
array
(
'&'
,
'<'
),
array
(
'&'
,
'<'
),
$Element
[
'attributes'
][
'href'
]);
return
array
(
'extent'
=>
$extent
,
'element'
=>
$Element
,
);
}
protected
function
inlineMarkup
(
$Excerpt
)
{
if
(
$this
->
markupEscaped
or
strpos
(
$Excerpt
[
'text'
],
'>'
)
===
false
)
{
return
;
}
if
(
$Excerpt
[
'text'
][
1
]
===
'/'
and
preg_match
(
'/^<\/\w*[ ]*>/s'
,
$Excerpt
[
'text'
],
$matches
))
{
return
array
(
'markup'
=>
$matches
[
0
],
'extent'
=>
strlen
(
$matches
[
0
]),
);
}
if
(
$Excerpt
[
'text'
][
1
]
===
'!'
and
preg_match
(
'/^<!---?[^>-](?:-?[^-])*-->/s'
,
$Excerpt
[
'text'
],
$matches
))
{
return
array
(
'markup'
=>
$matches
[
0
],
'extent'
=>
strlen
(
$matches
[
0
]),
);
}
if
(
$Excerpt
[
'text'
][
1
]
!==
' '
and
preg_match
(
'/^<\w*(?:[ ]*'
.
$this
->
regexHtmlAttribute
.
')*[ ]*\/?>/s'
,
$Excerpt
[
'text'
],
$matches
))
{
return
array
(
'markup'
=>
$matches
[
0
],
'extent'
=>
strlen
(
$matches
[
0
]),
);
}
}
protected
function
inlineSpecialCharacter
(
$Excerpt
)
{
if
(
$Excerpt
[
'text'
][
0
]
===
'&'
and
!
preg_match
(
'/^&#?\w+;/'
,
$Excerpt
[
'text'
]))
{
return
array
(
'markup'
=>
'&'
,
'extent'
=>
1
,
);
}
$SpecialCharacter
=
array
(
'>'
=>
'gt'
,
'<'
=>
'lt'
,
'"'
=>
'quot'
);
if
(
isset
(
$SpecialCharacter
[
$Excerpt
[
'text'
][
0
]]))
{
return
array
(
'markup'
=>
'&'
.
$SpecialCharacter
[
$Excerpt
[
'text'
][
0
]]
.
';'
,
'extent'
=>
1
,
);
}
}
protected
function
inlineStrikethrough
(
$Excerpt
)
{
if
(
!
isset
(
$Excerpt
[
'text'
][
1
]))
{
return
;
}
if
(
$Excerpt
[
'text'
][
1
]
===
'~'
and
preg_match
(
'/^~~(?=\S)(.+?)(?<=\S)~~/'
,
$Excerpt
[
'text'
],
$matches
))
{
return
array
(
'extent'
=>
strlen
(
$matches
[
0
]),
'element'
=>
array
(
'name'
=>
'del'
,
'text'
=>
$matches
[
1
],
'handler'
=>
'line'
,
),
);
}
}
protected
function
inlineUrl
(
$Excerpt
)
{
if
(
$this
->
urlsLinked
!==
true
or
!
isset
(
$Excerpt
[
'text'
][
2
])
or
$Excerpt
[
'text'
][
2
]
!==
'/'
)
{
return
;
}
if
(
preg_match
(
'/\bhttps?:[\/]{2}[^\s<]+\b\/*/ui'
,
$Excerpt
[
'context'
],
$matches
,
PREG_OFFSET_CAPTURE
))
{
$Inline
=
array
(
'extent'
=>
strlen
(
$matches
[
0
][
0
]),
'position'
=>
$matches
[
0
][
1
],
'element'
=>
array
(
'name'
=>
'a'
,
'text'
=>
$matches
[
0
][
0
],
'attributes'
=>
array
(
'href'
=>
$matches
[
0
][
0
],
),
),
);
return
$Inline
;
}
}
protected
function
inlineUrlTag
(
$Excerpt
)
{
if
(
strpos
(
$Excerpt
[
'text'
],
'>'
)
!==
false
and
preg_match
(
'/^<(\w+:\/{2}[^ >]+)>/i'
,
$Excerpt
[
'text'
],
$matches
))
{
$url
=
str_replace
(
array
(
'&'
,
'<'
),
array
(
'&'
,
'<'
),
$matches
[
1
]);
return
array
(
'extent'
=>
strlen
(
$matches
[
0
]),
'element'
=>
array
(
'name'
=>
'a'
,
'text'
=>
$url
,
'attributes'
=>
array
(
'href'
=>
$url
,
),
),
);
}
}
# ~
protected
function
unmarkedText
(
$text
)
{
if
(
$this
->
breaksEnabled
)
{
$text
=
preg_replace
(
'/[ ]*\n/'
,
"<br />
\n
"
,
$text
);
}
else
{
$text
=
preg_replace
(
'/(?:[ ][ ]+|[ ]*\\\\)\n/'
,
"<br />
\n
"
,
$text
);
$text
=
str_replace
(
"
\n
"
,
"
\n
"
,
$text
);
}
return
$text
;
}
#
# Handlers
#
protected
function
element
(
array
$Element
)
{
$markup
=
'<'
.
$Element
[
'name'
];
if
(
isset
(
$Element
[
'attributes'
]))
{
foreach
(
$Element
[
'attributes'
]
as
$name
=>
$value
)
{
if
(
$value
===
null
)
{
continue
;
}
$markup
.=
' '
.
$name
.
'="'
.
$value
.
'"'
;
}
}
if
(
isset
(
$Element
[
'text'
]))
{
$markup
.=
'>'
;
if
(
isset
(
$Element
[
'handler'
]))
{
$markup
.=
$this
->
{
$Element
[
'handler'
]}(
$Element
[
'text'
]);
}
else
{
$markup
.=
$Element
[
'text'
];
}
$markup
.=
'</'
.
$Element
[
'name'
]
.
'>'
;
}
else
{
$markup
.=
' />'
;
}
return
$markup
;
}
protected
function
elements
(
array
$Elements
)
{
$markup
=
''
;
foreach
(
$Elements
as
$Element
)
{
$markup
.=
"
\n
"
.
$this
->
element
(
$Element
);
}
$markup
.=
"
\n
"
;
return
$markup
;
}
# ~
protected
function
li
(
$lines
)
{
$markup
=
$this
->
lines
(
$lines
);
$trimmedMarkup
=
trim
(
$markup
);
if
(
!
in_array
(
''
,
$lines
)
and
substr
(
$trimmedMarkup
,
0
,
3
)
===
'<p>'
)
{
$markup
=
$trimmedMarkup
;
$markup
=
substr
(
$markup
,
3
);
$position
=
strpos
(
$markup
,
"</p>"
);
$markup
=
substr_replace
(
$markup
,
''
,
$position
,
4
);
}
return
$markup
;
}
#
# Deprecated Methods
#
function
parse
(
$text
)
{
$markup
=
$this
->
text
(
$text
);
return
$markup
;
}
#
# Static Methods
#
static
function
instance
(
$name
=
'default'
)
{
if
(
isset
(
self
::
$instances
[
$name
]))
{
return
self
::
$instances
[
$name
];
}
$instance
=
new
static
();
self
::
$instances
[
$name
]
=
$instance
;
return
$instance
;
}
private
static
$instances
=
array
();
#
# Fields
#
protected
$DefinitionData
;
#
# Read-Only
protected
$specialCharacters
=
array
(
'\\'
,
'`'
,
'*'
,
'_'
,
'{'
,
'}'
,
'['
,
']'
,
'('
,
')'
,
'>'
,
'#'
,
'+'
,
'-'
,
'.'
,
'!'
,
'|'
,
);
protected
$StrongRegex
=
array
(
'*'
=>
'/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s'
,
'_'
=>
'/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us'
,
);
protected
$EmRegex
=
array
(
'*'
=>
'/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s'
,
'_'
=>
'/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us'
,
);
protected
$regexHtmlAttribute
=
'[a-zA-Z_:][\w:.-]*(?:\s*=\s*(?:[^"\'=<>`\s]+|"[^"]*"|\'[^\']*\'))?'
;
protected
$voidElements
=
array
(
'area'
,
'base'
,
'br'
,
'col'
,
'command'
,
'embed'
,
'hr'
,
'img'
,
'input'
,
'link'
,
'meta'
,
'param'
,
'source'
,
);
protected
$textLevelElements
=
array
(
'a'
,
'br'
,
'bdo'
,
'abbr'
,
'blink'
,
'nextid'
,
'acronym'
,
'basefont'
,
'b'
,
'em'
,
'big'
,
'cite'
,
'small'
,
'spacer'
,
'listing'
,
'i'
,
'rp'
,
'del'
,
'code'
,
'strike'
,
'marquee'
,
'q'
,
'rt'
,
'ins'
,
'font'
,
'strong'
,
's'
,
'tt'
,
'kbd'
,
'mark'
,
'u'
,
'xm'
,
'sub'
,
'nobr'
,
'sup'
,
'ruby'
,
'var'
,
'span'
,
'wbr'
,
'time'
,
);
}
system/src/Grav/Framework/Parsedown/ParsedownExtra.php
0 → 100644
View file @
4a98d5fe
<?php
/**
* @package Grav\Framework\Parsedown
*
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/
namespace
Grav\Framework\Parsedown
;
/*
* Parsedown Extra
* http://parsedown.org
*
* (c) Emanuil Rusev
* http://erusev.com
*
* This file ported from officiall ParsedownExtra repo and kept for compatibility.
*/
class
ParsedownExtra
extends
Parsedown
{
# ~
const
version
=
'0.7.0'
;
# ~
function
__construct
()
{
if
(
parent
::
version
<
'1.5.0'
)
{
throw
new
Exception
(
'ParsedownExtra requires a later version of Parsedown'
);
}
$this
->
BlockTypes
[
':'
]
[]
=
'DefinitionList'
;
$this
->
BlockTypes
[
'*'
]
[]
=
'Abbreviation'
;
# identify footnote definitions before reference definitions
array_unshift
(
$this
->
BlockTypes
[
'['
],
'Footnote'
);
# identify footnote markers before before links
array_unshift
(
$this
->
InlineTypes
[
'['
],
'FootnoteMarker'
);
}
#
# ~
function
text
(
$text
)
{
$markup
=
parent
::
text
(
$text
);
# merge consecutive dl elements
$markup
=
preg_replace
(
'/<\/dl>\s+<dl>\s+/'
,
''
,
$markup
);
# add footnotes
if
(
isset
(
$this
->
DefinitionData
[
'Footnote'
]))
{
$Element
=
$this
->
buildFootnoteElement
();
$markup
.=
"
\n
"
.
$this
->
element
(
$Element
);
}
return
$markup
;
}
#
# Blocks
#
#
# Abbreviation
protected
function
blockAbbreviation
(
$Line
)
{
if
(
preg_match
(
'/^\*\[(.+?)\]:[ ]*(.+?)[ ]*$/'
,
$Line
[
'text'
],
$matches
))
{
$this
->
DefinitionData
[
'Abbreviation'
][
$matches
[
1
]]
=
$matches
[
2
];
$Block
=
array
(
'hidden'
=>
true
,
);
return
$Block
;
}
}
#
# Footnote
protected
function
blockFootnote
(
$Line
)
{
if
(
preg_match
(
'/^\[\^(.+?)\]:[ ]?(.*)$/'
,
$Line
[
'text'
],
$matches
))
{
$Block
=
array
(
'label'
=>
$matches
[
1
],
'text'
=>
$matches
[
2
],
'hidden'
=>
true
,
);
return
$Block
;
}
}
protected
function
blockFootnoteContinue
(
$Line
,
$Block
)
{
if
(
$Line
[
'text'
][
0
]
===
'['
and
preg_match
(
'/^\[\^(.+?)\]:/'
,
$Line
[
'text'
]))
{
return
;
}
if
(
isset
(
$Block
[
'interrupted'
]))
{
if
(
$Line
[
'indent'
]
>=
4
)
{
$Block
[
'text'
]
.=
"
\n\n
"
.
$Line
[
'text'
];
return
$Block
;
}
}
else
{
$Block
[
'text'
]
.=
"
\n
"
.
$Line
[
'text'
];
return
$Block
;
}
}
protected
function
blockFootnoteComplete
(
$Block
)
{
$this
->
DefinitionData
[
'Footnote'
][
$Block
[
'label'
]]
=
array
(
'text'
=>
$Block
[
'text'
],
'count'
=>
null
,
'number'
=>
null
,
);
return
$Block
;
}
#
# Definition List
protected
function
blockDefinitionList
(
$Line
,
$Block
)
{
if
(
!
isset
(
$Block
)
or
isset
(
$Block
[
'type'
]))
{
return
;
}
$Element
=
array
(
'name'
=>
'dl'
,
'handler'
=>
'elements'
,
'text'
=>
array
(),
);
$terms
=
explode
(
"
\n
"
,
$Block
[
'element'
][
'text'
]);
foreach
(
$terms
as
$term
)
{
$Element
[
'text'
]
[]
=
array
(
'name'
=>
'dt'
,
'handler'
=>
'line'
,
'text'
=>
$term
,
);
}
$Block
[
'element'
]
=
$Element
;
$Block
=
$this
->
addDdElement
(
$Line
,
$Block
);
return
$Block
;
}
protected
function
blockDefinitionListContinue
(
$Line
,
array
$Block
)
{
if
(
$Line
[
'text'
][
0
]
===
':'
)
{
$Block
=
$this
->
addDdElement
(
$Line
,
$Block
);
return
$Block
;
}
else
{
if
(
isset
(
$Block
[
'interrupted'
])
and
$Line
[
'indent'
]
===
0
)
{
return
;
}
if
(
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'dd'
][
'handler'
]
=
'text'
;
$Block
[
'dd'
][
'text'
]
.=
"
\n\n
"
;
unset
(
$Block
[
'interrupted'
]);
}
$text
=
substr
(
$Line
[
'body'
],
min
(
$Line
[
'indent'
],
4
));
$Block
[
'dd'
][
'text'
]
.=
"
\n
"
.
$text
;
return
$Block
;
}
}
#
# Header
protected
function
blockHeader
(
$Line
)
{
$Block
=
parent
::
blockHeader
(
$Line
);
if
(
$Block
!==
null
&&
preg_match
(
'/[ #]*{('
.
$this
->
regexAttribute
.
'+)}[ ]*$/'
,
$Block
[
'element'
][
'text'
],
$matches
,
PREG_OFFSET_CAPTURE
))
{
$attributeString
=
$matches
[
1
][
0
];
$Block
[
'element'
][
'attributes'
]
=
$this
->
parseAttributeData
(
$attributeString
);
$Block
[
'element'
][
'text'
]
=
substr
(
$Block
[
'element'
][
'text'
],
0
,
$matches
[
0
][
1
]);
}
return
$Block
;
}
#
# Markup
protected
function
blockMarkupComplete
(
$Block
)
{
if
(
!
isset
(
$Block
[
'void'
]))
{
$Block
[
'markup'
]
=
$this
->
processTag
(
$Block
[
'markup'
]);
}
return
$Block
;
}
#
# Setext
protected
function
blockSetextHeader
(
$Line
,
array
$Block
=
null
)
{
$Block
=
parent
::
blockSetextHeader
(
$Line
,
$Block
);
if
(
$Block
!==
null
&&
preg_match
(
'/[ ]*{('
.
$this
->
regexAttribute
.
'+)}[ ]*$/'
,
$Block
[
'element'
][
'text'
],
$matches
,
PREG_OFFSET_CAPTURE
))
{
$attributeString
=
$matches
[
1
][
0
];
$Block
[
'element'
][
'attributes'
]
=
$this
->
parseAttributeData
(
$attributeString
);
$Block
[
'element'
][
'text'
]
=
substr
(
$Block
[
'element'
][
'text'
],
0
,
$matches
[
0
][
1
]);
}
return
$Block
;
}
#
# Inline Elements
#
#
# Footnote Marker
protected
function
inlineFootnoteMarker
(
$Excerpt
)
{
if
(
preg_match
(
'/^\[\^(.+?)\]/'
,
$Excerpt
[
'text'
],
$matches
))
{
$name
=
$matches
[
1
];
if
(
!
isset
(
$this
->
DefinitionData
[
'Footnote'
][
$name
]))
{
return
;
}
$this
->
DefinitionData
[
'Footnote'
][
$name
][
'count'
]
++
;
if
(
!
isset
(
$this
->
DefinitionData
[
'Footnote'
][
$name
][
'number'
]))
{
$this
->
DefinitionData
[
'Footnote'
][
$name
][
'number'
]
=
++
$this
->
footnoteCount
;
# » &
}
$Element
=
array
(
'name'
=>
'sup'
,
'attributes'
=>
array
(
'id'
=>
'fnref'
.
$this
->
DefinitionData
[
'Footnote'
][
$name
][
'count'
]
.
':'
.
$name
),
'handler'
=>
'element'
,
'text'
=>
array
(
'name'
=>
'a'
,
'attributes'
=>
array
(
'href'
=>
'#fn:'
.
$name
,
'class'
=>
'footnote-ref'
),
'text'
=>
$this
->
DefinitionData
[
'Footnote'
][
$name
][
'number'
],
),
);
return
array
(
'extent'
=>
strlen
(
$matches
[
0
]),
'element'
=>
$Element
,
);
}
}
private
$footnoteCount
=
0
;
#
# Link
protected
function
inlineLink
(
$Excerpt
)
{
$Link
=
parent
::
inlineLink
(
$Excerpt
);
$remainder
=
$Link
!==
null
?
substr
(
$Excerpt
[
'text'
],
$Link
[
'extent'
])
:
''
;
if
(
preg_match
(
'/^[ ]*{('
.
$this
->
regexAttribute
.
'+)}/'
,
$remainder
,
$matches
))
{
$Link
[
'element'
][
'attributes'
]
+=
$this
->
parseAttributeData
(
$matches
[
1
]);
$Link
[
'extent'
]
+=
strlen
(
$matches
[
0
]);
}
return
$Link
;
}
#
# ~
#
protected
function
unmarkedText
(
$text
)
{
$text
=
parent
::
unmarkedText
(
$text
);
if
(
isset
(
$this
->
DefinitionData
[
'Abbreviation'
]))
{
foreach
(
$this
->
DefinitionData
[
'Abbreviation'
]
as
$abbreviation
=>
$meaning
)
{
$pattern
=
'/\b'
.
preg_quote
(
$abbreviation
,
'/'
)
.
'\b/'
;
$text
=
preg_replace
(
$pattern
,
'<abbr title="'
.
$meaning
.
'">'
.
$abbreviation
.
'</abbr>'
,
$text
);
}
}
return
$text
;
}
#
# Util Methods
#
protected
function
addDdElement
(
array
$Line
,
array
$Block
)
{
$text
=
substr
(
$Line
[
'text'
],
1
);
$text
=
trim
(
$text
);
unset
(
$Block
[
'dd'
]);
$Block
[
'dd'
]
=
array
(
'name'
=>
'dd'
,
'handler'
=>
'line'
,
'text'
=>
$text
,
);
if
(
isset
(
$Block
[
'interrupted'
]))
{
$Block
[
'dd'
][
'handler'
]
=
'text'
;
unset
(
$Block
[
'interrupted'
]);
}
$Block
[
'element'
][
'text'
]
[]
=
&
$Block
[
'dd'
];
return
$Block
;
}
protected
function
buildFootnoteElement
()
{
$Element
=
array
(
'name'
=>
'div'
,
'attributes'
=>
array
(
'class'
=>
'footnotes'
),
'handler'
=>
'elements'
,
'text'
=>
array
(
array
(
'name'
=>
'hr'
,
),
array
(
'name'
=>
'ol'
,
'handler'
=>
'elements'
,
'text'
=>
array
(),
),
),
);
uasort
(
$this
->
DefinitionData
[
'Footnote'
],
'self::sortFootnotes'
);
foreach
(
$this
->
DefinitionData
[
'Footnote'
]
as
$definitionId
=>
$DefinitionData
)
{
if
(
!
isset
(
$DefinitionData
[
'number'
]))
{
continue
;
}
$text
=
$DefinitionData
[
'text'
];
$text
=
parent
::
text
(
$text
);
$numbers
=
range
(
1
,
$DefinitionData
[
'count'
]);
$backLinksMarkup
=
''
;
foreach
(
$numbers
as
$number
)
{
$backLinksMarkup
.=
' <a href="#fnref'
.
$number
.
':'
.
$definitionId
.
'" rev="footnote" class="footnote-backref">↩</a>'
;
}
$backLinksMarkup
=
substr
(
$backLinksMarkup
,
1
);
if
(
substr
(
$text
,
-
4
)
===
'</p>'
)
{
$backLinksMarkup
=
' '
.
$backLinksMarkup
;
$text
=
substr_replace
(
$text
,
$backLinksMarkup
.
'</p>'
,
-
4
);
}
else
{
$text
.=
"
\n
"
.
'<p>'
.
$backLinksMarkup
.
'</p>'
;
}
$Element
[
'text'
][
1
][
'text'
]
[]
=
array
(
'name'
=>
'li'
,
'attributes'
=>
array
(
'id'
=>
'fn:'
.
$definitionId
),
'text'
=>
"
\n
"
.
$text
.
"
\n
"
,
);
}
return
$Element
;
}
# ~
protected
function
parseAttributeData
(
$attributeString
)
{
$Data
=
array
();
$attributes
=
preg_split
(
'/[ ]+/'
,
$attributeString
,
-
1
,
PREG_SPLIT_NO_EMPTY
);
foreach
(
$attributes
as
$attribute
)
{
if
(
$attribute
[
0
]
===
'#'
)
{
$Data
[
'id'
]
=
substr
(
$attribute
,
1
);
}
else
# "."
{
$classes
[]
=
substr
(
$attribute
,
1
);
}
}
if
(
isset
(
$classes
))
{
$Data
[
'class'
]
=
implode
(
' '
,
$classes
);
}
return
$Data
;
}
# ~
protected
function
processTag
(
$elementMarkup
)
# recursive
{
# http://stackoverflow.com/q/1148928/200145
libxml_use_internal_errors
(
true
);
$DOMDocument
=
new
\DOMDocument
;
# http://stackoverflow.com/q/11309194/200145
$elementMarkup
=
mb_convert_encoding
(
$elementMarkup
,
'HTML-ENTITIES'
,
'UTF-8'
);
# http://stackoverflow.com/q/4879946/200145
$DOMDocument
->
loadHTML
(
$elementMarkup
);
$DOMDocument
->
removeChild
(
$DOMDocument
->
doctype
);
$DOMDocument
->
replaceChild
(
$DOMDocument
->
firstChild
->
firstChild
->
firstChild
,
$DOMDocument
->
firstChild
);
$elementText
=
''
;
if
(
$DOMDocument
->
documentElement
->
getAttribute
(
'markdown'
)
===
'1'
)
{
foreach
(
$DOMDocument
->
documentElement
->
childNodes
as
$Node
)
{
$elementText
.=
$DOMDocument
->
saveHTML
(
$Node
);
}
$DOMDocument
->
documentElement
->
removeAttribute
(
'markdown'
);
$elementText
=
"
\n
"
.
$this
->
text
(
$elementText
)
.
"
\n
"
;
}
else
{
foreach
(
$DOMDocument
->
documentElement
->
childNodes
as
$Node
)
{
$nodeMarkup
=
$DOMDocument
->
saveHTML
(
$Node
);
if
(
$Node
instanceof
\DOMElement
and
!
in_array
(
$Node
->
nodeName
,
$this
->
textLevelElements
))
{
$elementText
.=
$this
->
processTag
(
$nodeMarkup
);
}
else
{
$elementText
.=
$nodeMarkup
;
}
}
}
# because we don't want for markup to get encoded
$DOMDocument
->
documentElement
->
nodeValue
=
'placeholder\x1A'
;
$markup
=
$DOMDocument
->
saveHTML
(
$DOMDocument
->
documentElement
);
$markup
=
str_replace
(
'placeholder\x1A'
,
$elementText
,
$markup
);
return
$markup
;
}
# ~
protected
function
sortFootnotes
(
$A
,
$B
)
# callback
{
return
$A
[
'number'
]
-
$B
[
'number'
];
}
#
# Fields
#
protected
$regexAttribute
=
'(?:[#.][-\w]+[ ]*)'
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment