finished inline text semantics tags through <time>
This commit is contained in:
parent
885975e3b4
commit
1a12390c71
44 changed files with 1739 additions and 0 deletions
20
src/Helpers/StringableValue.php
Normal file
20
src/Helpers/StringableValue.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Helpers;
|
||||
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Class for automatically serializing and unserializing text values (such as in
|
||||
* attributes) between a text representation that can be rendered and an object
|
||||
* representation that is easy to work with.
|
||||
*
|
||||
* Objects that implement this can be passed into an Attributes object and will
|
||||
* be stored as their object form and automatically converted into strings at
|
||||
* render time. Some tags will have specific requirements for particular
|
||||
* implementations of this interface for particular attribute getters/setters.
|
||||
*/
|
||||
interface StringableValue extends Stringable
|
||||
{
|
||||
public static function fromString(string|Stringable|null $string): self|null;
|
||||
}
|
34
src/Html5/InlineTextSemantics/BTag.php
Normal file
34
src/Html5/InlineTextSemantics/BTag.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <b> HTML element is used to draw the reader's attention to the element's
|
||||
* contents, which are not otherwise granted special importance. This was
|
||||
* formerly known as the Boldface element, and most browsers still draw the text
|
||||
* in boldface. However, you should not use <b> for styling text or granting
|
||||
* importance. If you wish to create boldface text, you should use the CSS
|
||||
* font-weight property. If you wish to indicate an element is of special
|
||||
* importance, you should use the <strong> element.
|
||||
*
|
||||
* Do not confuse the <b> element with the <strong>, <em>, or <mark> elements.
|
||||
* The <strong> element represents text of certain importance, <em> puts some
|
||||
* emphasis on the text and the <mark> element represents text of certain
|
||||
* relevance. The <b> element doesn't convey such special semantic information;
|
||||
* use it only when no others fit.
|
||||
*
|
||||
* It is a good practice to use the class attribute on the <b> element in order
|
||||
* to convey additional semantic information as needed (for example <b
|
||||
* class="lead"> for the first sentence in a paragraph). This makes it easier to
|
||||
* manage multiple use cases of <b> if your stylistic needs change, without the
|
||||
* need to change all of its uses in the HTML.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/b
|
||||
*/
|
||||
class BTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'b';
|
||||
}
|
29
src/Html5/InlineTextSemantics/BdiTag.php
Normal file
29
src/Html5/InlineTextSemantics/BdiTag.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <bdi> HTML element tells the browser's bidirectional algorithm to treat
|
||||
* the text it contains in isolation from its surrounding text. It's
|
||||
* particularly useful when a website dynamically inserts some text and doesn't
|
||||
* know the directionality of the text being inserted.
|
||||
*
|
||||
* Bidirectional text is text that may contain both sequences of characters that
|
||||
* are arranged left-to-right (LTR) and sequences of characters that are
|
||||
* arranged right-to-left (RTL), such as an Arabic quotation embedded in an
|
||||
* English string. Browsers implement the Unicode Bidirectional Algorithm to
|
||||
* handle this. In this algorithm, characters are given an implicit
|
||||
* directionality: for example, Latin characters are treated as LTR while Arabic
|
||||
* characters are treated as RTL. Some other characters (such as spaces and some
|
||||
* punctuation) are treated as neutral and are assigned directionality based on
|
||||
* that of their surrounding characters.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi
|
||||
*/
|
||||
class BdiTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'bdi';
|
||||
}
|
17
src/Html5/InlineTextSemantics/BdoTag.php
Normal file
17
src/Html5/InlineTextSemantics/BdoTag.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <bdo> HTML element overrides the current directionality of text, so that
|
||||
* the text within is rendered in a different direction.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo
|
||||
*/
|
||||
class BdoTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'bdo';
|
||||
}
|
16
src/Html5/InlineTextSemantics/BrTag.php
Normal file
16
src/Html5/InlineTextSemantics/BrTag.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractTag;
|
||||
|
||||
/**
|
||||
* The <br> HTML element produces a line break in text (carriage-return). It is useful for writing a poem or an address, where the division of lines is significant.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/br
|
||||
*/
|
||||
class BrTag extends AbstractTag
|
||||
{
|
||||
const TAG = 'br';
|
||||
}
|
18
src/Html5/InlineTextSemantics/CiteTag.php
Normal file
18
src/Html5/InlineTextSemantics/CiteTag.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <cite> HTML element is used to mark up the title of a cited creative
|
||||
* work. The reference may be in an abbreviated form according to
|
||||
* context-appropriate conventions related to citation metadata.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/cite
|
||||
*/
|
||||
class CiteTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'cite';
|
||||
}
|
18
src/Html5/InlineTextSemantics/CodeTag.php
Normal file
18
src/Html5/InlineTextSemantics/CodeTag.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <code> HTML element displays its contents styled in a fashion intended to
|
||||
* indicate that the text is a short fragment of computer code. By default, the
|
||||
* content text is displayed using the user agent's default monospace font.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code
|
||||
*/
|
||||
class CodeTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'code';
|
||||
}
|
56
src/Html5/InlineTextSemantics/DataTag.php
Normal file
56
src/Html5/InlineTextSemantics/DataTag.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* The <data> HTML element links a given piece of content with a
|
||||
* machine-readable translation. If the content is time- or date-related, the
|
||||
* <time> element must be used.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/data
|
||||
*/
|
||||
class DataTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'data';
|
||||
|
||||
/**
|
||||
* This attribute specifies the machine-readable translation of the content
|
||||
* of the element.
|
||||
*
|
||||
* @return null|string|Stringable
|
||||
*/
|
||||
public function value(): null|string|Stringable
|
||||
{
|
||||
return $this->attributes()->asString('value');
|
||||
}
|
||||
|
||||
/**
|
||||
* This attribute specifies the machine-readable translation of the content
|
||||
* of the element.
|
||||
*
|
||||
* @param null|string|Stringable $value
|
||||
* @return static
|
||||
*/
|
||||
public function setValue(null|string|Stringable $value): static
|
||||
{
|
||||
if ($value) $this->attributes()['value'] = $value;
|
||||
else $this->unsetValue();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This attribute specifies the machine-readable translation of the content
|
||||
* of the element.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function unsetValue(): static
|
||||
{
|
||||
unset($this->attributes()['value']);
|
||||
return $this;
|
||||
}
|
||||
}
|
76
src/Html5/InlineTextSemantics/DfnTag.php
Normal file
76
src/Html5/InlineTextSemantics/DfnTag.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* The <dfn> HTML element is used to indicate the term being defined within the
|
||||
* context of a definition phrase or sentence. The ancestor <p> element, the
|
||||
* <dt>/<dd> pairing, or the nearest <section> ancestor of the <dfn> element, is
|
||||
* considered to be the definition of the term.
|
||||
*
|
||||
* The term being defined is identified following these rules:
|
||||
*
|
||||
* * If the <dfn> element has a title attribute, the value of the title
|
||||
* attribute is considered to be the term being defined. The element must
|
||||
* still have text within it, but that text may be an abbreviation (perhaps
|
||||
* using <abbr>) or another form of the term.
|
||||
* * If the <dfn> contains a single child element and does not have any text
|
||||
* content of its own, and the child element is an <abbr> element with a
|
||||
* title attribute itself, then the exact value of the <abbr> element's title
|
||||
* is the term being defined.
|
||||
* * Otherwise, the text content of the <dfn> element is the term being
|
||||
* defined. This is shown in the first example below.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dfn
|
||||
*/
|
||||
class DataTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'dfn';
|
||||
|
||||
/**
|
||||
* If the <dfn> element has a title attribute, the value of the title
|
||||
* attribute is considered to be the term being defined. The element must
|
||||
* still have text within it, but that text may be an abbreviation (perhaps
|
||||
* using <abbr>) or another form of the term.
|
||||
*
|
||||
* @return null|string|Stringable
|
||||
*/
|
||||
public function title(): null|string|Stringable
|
||||
{
|
||||
return $this->attributes()->asString('title');
|
||||
}
|
||||
|
||||
/**
|
||||
* If the <dfn> element has a title attribute, the value of the title
|
||||
* attribute is considered to be the term being defined. The element must
|
||||
* still have text within it, but that text may be an abbreviation (perhaps
|
||||
* using <abbr>) or another form of the term.
|
||||
*
|
||||
* @param null|string|Stringable $title
|
||||
* @return static
|
||||
*/
|
||||
public function setTitle(null|string|Stringable $title): static
|
||||
{
|
||||
if ($title) $this->attributes()['title'] = $title;
|
||||
else $this->unsetTitle();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the <dfn> element has a title attribute, the value of the title
|
||||
* attribute is considered to be the term being defined. The element must
|
||||
* still have text within it, but that text may be an abbreviation (perhaps
|
||||
* using <abbr>) or another form of the term.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function unsetTitle(): static
|
||||
{
|
||||
unset($this->attributes()['title']);
|
||||
return $this;
|
||||
}
|
||||
}
|
30
src/Html5/InlineTextSemantics/EmTag.php
Normal file
30
src/Html5/InlineTextSemantics/EmTag.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <em> HTML element marks text that has stress emphasis. The <em> element
|
||||
* can be nested, with each level of nesting indicating a greater degree of
|
||||
* emphasis.
|
||||
*
|
||||
* The <em> element is for words that have a stressed emphasis compared to
|
||||
* surrounding text, which is often limited to a word or words of a sentence and
|
||||
* affects the meaning of the sentence itself.
|
||||
*
|
||||
* Typically this element is displayed in italic type. However, it should not be
|
||||
* used to apply italic styling; use the CSS font-style property for that
|
||||
* purpose. Use the <cite> element to mark the title of a work (book, play,
|
||||
* song, etc.). Use the <i> element to mark text that is in an alternate tone or
|
||||
* mood, which covers many common situations for italics such as scientific
|
||||
* names or words in other languages. Use the <strong> element to mark text that
|
||||
* has greater importance than surrounding text.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/em
|
||||
*/
|
||||
class EmTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'em';
|
||||
}
|
20
src/Html5/InlineTextSemantics/ITag.php
Normal file
20
src/Html5/InlineTextSemantics/ITag.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <i> HTML element represents a range of text that is set off from the
|
||||
* normal text for some reason, such as idiomatic text, technical terms,
|
||||
* taxonomical designations, among others. Historically, these have been
|
||||
* presented using italicized type, which is the original source of the <i>
|
||||
* naming of this element.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/i
|
||||
*/
|
||||
class ITag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'i';
|
||||
}
|
27
src/Html5/InlineTextSemantics/KbdTag.php
Normal file
27
src/Html5/InlineTextSemantics/KbdTag.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <kbd> HTML element represents a span of inline text denoting textual user
|
||||
* input from a keyboard, voice input, or any other text entry device. By
|
||||
* convention, the user agent defaults to rendering the contents of a <kbd>
|
||||
* element using its default monospace font, although this is not mandated by
|
||||
* the HTML standard.
|
||||
*
|
||||
* To describe an input comprised of multiple keystrokes, you can nest multiple
|
||||
* <kbd> elements, with an outer <kbd> element representing the overall input
|
||||
* and each individual keystroke or component of the input enclosed within its
|
||||
* own <kbd>, such as:
|
||||
*
|
||||
* <kbd><kbd>Ctrl</kbd>+<kbd>N</kbd></kbd>
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/kbd
|
||||
*/
|
||||
class KbdTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'kbd';
|
||||
}
|
18
src/Html5/InlineTextSemantics/MarkTag.php
Normal file
18
src/Html5/InlineTextSemantics/MarkTag.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <mark> HTML element represents text which is marked or highlighted for
|
||||
* reference or notation purposes due to the marked passage's relevance in the
|
||||
* enclosing context.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark
|
||||
*/
|
||||
class MarkTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'mark';
|
||||
}
|
60
src/Html5/InlineTextSemantics/QTag.php
Normal file
60
src/Html5/InlineTextSemantics/QTag.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* The <q> HTML element indicates that the enclosed text is a short inline
|
||||
* quotation. Most modern browsers implement this by surrounding the text in
|
||||
* quotation marks. This element is intended for short quotations that don't
|
||||
* require paragraph breaks; for long quotations use the <blockquote> element.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q
|
||||
*/
|
||||
class QTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'q';
|
||||
|
||||
/**
|
||||
* The value of this attribute is a URL that designates a source document or
|
||||
* message for the information quoted. This attribute is intended to point
|
||||
* to information explaining the context or the reference for the quote.
|
||||
*
|
||||
* @return null|string|Stringable
|
||||
*/
|
||||
public function cite(): null|string|Stringable
|
||||
{
|
||||
return $this->attributes()->asString('cite');
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this attribute is a URL that designates a source document or
|
||||
* message for the information quoted. This attribute is intended to point
|
||||
* to information explaining the context or the reference for the quote.
|
||||
*
|
||||
* @param null|string|Stringable $cite
|
||||
* @return static
|
||||
*/
|
||||
public function setCite(null|string|Stringable $cite): static
|
||||
{
|
||||
if ($cite) $this->attributes()['cite'] = $cite;
|
||||
else $this->unsetCite();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The value of this attribute is a URL that designates a source document or
|
||||
* message for the information quoted. This attribute is intended to point
|
||||
* to information explaining the context or the reference for the quote.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function unsetCite(): static
|
||||
{
|
||||
unset($this->attributes()['cite']);
|
||||
return $this;
|
||||
}
|
||||
}
|
25
src/Html5/InlineTextSemantics/RpTag.php
Normal file
25
src/Html5/InlineTextSemantics/RpTag.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <rp> HTML element is used to provide fall-back parentheses for browsers
|
||||
* that do not support display of ruby annotations using the <ruby> element. One
|
||||
* <rp> element should enclose each of the opening and closing parentheses that
|
||||
* wrap the <rt> element that contains the annotation's text.
|
||||
*
|
||||
* Ruby annotations are for showing pronunciation of East Asian characters, like
|
||||
* using Japanese furigana or Taiwanese bopomofo characters. The <rp> element is
|
||||
* used in the case of lack of <ruby> element support; the <rp> content provides
|
||||
* what should be displayed in order to indicate the presence of a ruby
|
||||
* annotation, usually parentheses.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rp
|
||||
*/
|
||||
class RpTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'rp';
|
||||
}
|
24
src/Html5/InlineTextSemantics/RtTag.php
Normal file
24
src/Html5/InlineTextSemantics/RtTag.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <rt> HTML element specifies the ruby text component of a ruby annotation,
|
||||
* which is used to provide pronunciation, translation, or transliteration
|
||||
* information for East Asian typography. The <rt> element must always be
|
||||
* contained within a <ruby> element.
|
||||
*
|
||||
* This simple example provides Romaji transliteration for the kanji characters
|
||||
* within the <ruby> element:
|
||||
*
|
||||
* <ruby> 漢 <rt>Kan</rt> 字 <rt>ji</rt> </ruby>
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/rt
|
||||
*/
|
||||
class RtTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'rt';
|
||||
}
|
32
src/Html5/InlineTextSemantics/RubyTag.php
Normal file
32
src/Html5/InlineTextSemantics/RubyTag.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <ruby> HTML element represents small annotations that are rendered above,
|
||||
* below, or next to base text, usually used for showing the pronunciation of
|
||||
* East Asian characters. It can also be used for annotating other kinds of
|
||||
* text, but this usage is less common.
|
||||
*
|
||||
* Example 1: Character:
|
||||
* ```
|
||||
* <ruby>
|
||||
* 漢 <rp>(</rp><rt>Kan</rt><rp>)</rp>
|
||||
* 字 <rp>(</rp><rt>ji</rt><rp>)</rp>
|
||||
* </ruby>
|
||||
* ```
|
||||
*
|
||||
* Example 2: Word
|
||||
* ```
|
||||
* <ruby> 明日 <rp>(</rp><rt>Ashita</rt><rp>)</rp> </ruby>
|
||||
* ```
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ruby
|
||||
*/
|
||||
class RubyTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'ruby';
|
||||
}
|
24
src/Html5/InlineTextSemantics/STag.php
Normal file
24
src/Html5/InlineTextSemantics/STag.php
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <s> HTML element renders text with a strikethrough, or a line through it.
|
||||
* Use the <s> element to represent things that are no longer relevant or no
|
||||
* longer accurate. However, <s> is not appropriate when indicating document
|
||||
* edits; for that, use the <del> and <ins> elements, as appropriate.
|
||||
*
|
||||
* Accessibility concerns: The presence of the s element is not announced by
|
||||
* most screen reading technology in its default configuration. It can be made
|
||||
* to be announced by using the CSS content property, along with the ::before
|
||||
* and ::after pseudo-elements.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/s
|
||||
*/
|
||||
class STag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 's';
|
||||
}
|
19
src/Html5/InlineTextSemantics/SampTag.php
Normal file
19
src/Html5/InlineTextSemantics/SampTag.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <samp> HTML element is used to enclose inline text which represents
|
||||
* sample (or quoted) output from a computer program. Its contents are typically
|
||||
* rendered using the browser's default monospaced font (such as Courier or
|
||||
* Lucida Console).
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/samp
|
||||
*/
|
||||
class SampTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'samp';
|
||||
}
|
19
src/Html5/InlineTextSemantics/SmallTag.php
Normal file
19
src/Html5/InlineTextSemantics/SmallTag.php
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <small> HTML element represents side-comments and small print, like
|
||||
* copyright and legal text, independent of its styled presentation. By default,
|
||||
* it renders text within it one font-size smaller, such as from small to
|
||||
* x-small.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/small
|
||||
*/
|
||||
class SmallTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'small';
|
||||
}
|
22
src/Html5/InlineTextSemantics/SpanTag.php
Normal file
22
src/Html5/InlineTextSemantics/SpanTag.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <span> HTML element is a generic inline container for phrasing content,
|
||||
* which does not inherently represent anything. It can be used to group
|
||||
* elements for styling purposes (using the class or id attributes), or because
|
||||
* they share attribute values, such as lang. It should be used only when no
|
||||
* other semantic element is appropriate. <span> is very much like a <div>
|
||||
* element, but <div> is a block-level element whereas a <span> is an
|
||||
* inline-level element.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/span
|
||||
*/
|
||||
class SpanTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'span';
|
||||
}
|
23
src/Html5/InlineTextSemantics/StrongTag.php
Normal file
23
src/Html5/InlineTextSemantics/StrongTag.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <strong> HTML element indicates that its contents have strong importance,
|
||||
* seriousness, or urgency. Browsers typically render the contents in bold type.
|
||||
*
|
||||
* The <strong> element is for content that is of "strong importance," including
|
||||
* things of great seriousness or urgency (such as warnings). This could be a
|
||||
* sentence that is of great importance to the whole page, or you could merely
|
||||
* try to point out that some words are of greater importance compared to nearby
|
||||
* content.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/strong
|
||||
*/
|
||||
class StrongTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'strong';
|
||||
}
|
18
src/Html5/InlineTextSemantics/SubTag.php
Normal file
18
src/Html5/InlineTextSemantics/SubTag.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <sub> HTML element specifies inline text which should be displayed as
|
||||
* subscript for solely typographical reasons. Subscripts are typically rendered
|
||||
* with a lowered baseline using smaller text.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub
|
||||
*/
|
||||
class SubTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'sub';
|
||||
}
|
18
src/Html5/InlineTextSemantics/SupTag.php
Normal file
18
src/Html5/InlineTextSemantics/SupTag.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
|
||||
/**
|
||||
* The <sup> HTML element specifies inline text which is to be displayed as
|
||||
* superscript for solely typographical reasons. Superscripts are usually
|
||||
* rendered with a raised baseline using smaller text.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup
|
||||
*/
|
||||
class SupTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'sup';
|
||||
}
|
49
src/Html5/InlineTextSemantics/TimeTag.php
Normal file
49
src/Html5/InlineTextSemantics/TimeTag.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics;
|
||||
|
||||
use ByJoby\HTML\Html5\InlineTextSemantics\TimeTag\DatetimeValue;
|
||||
use ByJoby\HTML\Tags\AbstractContainerTag;
|
||||
use DateInterval;
|
||||
use DateTimeInterface;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* The <time> HTML element represents a specific period in time. It may include
|
||||
* the datetime attribute to translate dates into machine-readable format,
|
||||
* allowing for better search engine results or custom features such as
|
||||
* reminders.
|
||||
*
|
||||
* It may represent one of the following:
|
||||
* * A time on a 24-hour clock.
|
||||
* * A precise date in the Gregorian calendar (with optional time and timezone
|
||||
* information).
|
||||
* * A valid time duration.
|
||||
*
|
||||
* Tag description by Mozilla Contributors licensed under CC-BY-SA 2.5
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time
|
||||
*/
|
||||
class TimeTag extends AbstractContainerTag
|
||||
{
|
||||
const TAG = 'time';
|
||||
|
||||
public function datetime(): null|DatetimeValue
|
||||
{
|
||||
return DatetimeValue::fromString(
|
||||
$this->attributes()->asString('datetime')
|
||||
);
|
||||
}
|
||||
|
||||
public function setDatetime(null|DatetimeValue $datetime): static
|
||||
{
|
||||
if ($datetime) $this->attributes()['datetime'] = $datetime;
|
||||
else $this->unsetDatetime();
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function unsetDatetime(): static
|
||||
{
|
||||
unset($this->attributes()['datetime']);
|
||||
return $this;
|
||||
}
|
||||
}
|
76
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue.php
Normal file
76
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue.php
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use ByJoby\HTML\Helpers\StringableValue;
|
||||
use Stringable;
|
||||
|
||||
abstract class DatetimeValue implements StringableValue
|
||||
{
|
||||
/** @var array<int,class-string<DatetimeValue>> */
|
||||
const SUBCLASSES = [
|
||||
DatetimeValue_datetime::class,
|
||||
DatetimeValue_datetime_local::class,
|
||||
DatetimeValue_time::class,
|
||||
DatetimeValue_year::class,
|
||||
DatetimeValue_month::class,
|
||||
DatetimeValue_date::class,
|
||||
DatetimeValue_date_yearless::class,
|
||||
DatetimeValue_week::class,
|
||||
DatetimeValue_duration::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Matches any sequence of at least four digits, optionally prefixed with a
|
||||
* dash for negative (BCE) years
|
||||
*/
|
||||
const REGEX_YEAR = '(?<year>(\-)?[0-9]{4,})';
|
||||
|
||||
/**
|
||||
* Matches any integer from 01 to 12, leading zero optional
|
||||
*/
|
||||
const REGEX_MONTH = '(?<month>0?[1-9]|1[0-2])';
|
||||
|
||||
/**
|
||||
* Matches any integer from 01 to 31, leading zero optional
|
||||
*/
|
||||
const REGEX_DAY = '(?<day>0?[1-9]|[0-2][0-9]|3[0-1])';
|
||||
|
||||
/**
|
||||
* Matches any integer from 01 to 53, leading zero optional
|
||||
*/
|
||||
const REGEX_WEEKNUM = '(?<weeknum>0?[1-9]|[1-4][0-9]|5[0-3])';
|
||||
|
||||
/**
|
||||
* Matches any integer from 00 to 59, leading zero optional
|
||||
*/
|
||||
const REGEX_HOUR = '(?<hour>0?[0-9]|1[0-9]|2[0-3])';
|
||||
|
||||
/**
|
||||
* Matches any integer from 00 to 59, leading zero optional
|
||||
*/
|
||||
const REGEX_MINUTE = '(?<minute>0?[0-9]|[1-5][0-9])';
|
||||
|
||||
/**
|
||||
* Matches any integer from 00 to 59, leading zero optional. Optionally
|
||||
* followed by a three-digit decimal portion.
|
||||
*/
|
||||
const REGEX_SECOND = '((?<second>0?[0-9]|[1-5][0-9])(\.(?<microsecond>[0-9]{3}))?)';
|
||||
|
||||
/**
|
||||
* Tries parsing with all subclasses and returns the first one that
|
||||
* succeeds, or null if nothing does.
|
||||
*
|
||||
* @param string|Stringable|null $string
|
||||
* @return null|self
|
||||
*/
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
if (is_null($string)) return null;
|
||||
foreach (static::SUBCLASSES as $class) {
|
||||
$result = $class::fromString(strval($string));
|
||||
if ($result) return $result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
57
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_date.php
Normal file
57
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_date.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use DateTime;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds a date that will be stringed to something like 2011-11-18
|
||||
*
|
||||
* Stored internally as a DateTime with the time set to noon, which is public
|
||||
* and as such can be conveniently manipulated.
|
||||
*/
|
||||
class DatetimeValue_date extends DatetimeValue
|
||||
{
|
||||
/** @var DateTime */
|
||||
public $datetime;
|
||||
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s\-%s\-%s$/',
|
||||
static::REGEX_YEAR,
|
||||
static::REGEX_MONTH,
|
||||
static::REGEX_DAY,
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
intval($matches['year']),
|
||||
intval($matches['month']),
|
||||
intval($matches['day']),
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __construct(int $year, int $month, int $day)
|
||||
{
|
||||
$this->datetime = (new DateTime())
|
||||
->setDate($year,$month,$day)
|
||||
->setTime(12,0,0,0);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->datetime->format('Y-m-d');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use DateTime;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds a date that will be stringed to something like 11-18
|
||||
*
|
||||
* Stored internally as a DateTime with the time set to noon, which is public
|
||||
* and as such can be conveniently manipulated. Internally the year will be set
|
||||
* to the current year.
|
||||
*/
|
||||
class DatetimeValue_date_yearless extends DatetimeValue
|
||||
{
|
||||
/** @var DateTime */
|
||||
public $datetime;
|
||||
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s\-%s$/',
|
||||
static::REGEX_MONTH,
|
||||
static::REGEX_DAY,
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
intval($matches['month']),
|
||||
intval($matches['day']),
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __construct(int $month, int $day)
|
||||
{
|
||||
$this->datetime = (new DateTime())
|
||||
->setDate(intval(date('Y')), $month, $day)
|
||||
->setTime(12, 0, 0, 0);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->datetime->format('m-d');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeZone;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds a date/time that will be stringed to something like
|
||||
* 2011-11-18T14:54:39.929-0600
|
||||
*
|
||||
* Stored internally as a DateTime, which is public and as such can be
|
||||
* conveniently manipulated.
|
||||
*/
|
||||
class DatetimeValue_datetime extends DatetimeValue
|
||||
{
|
||||
/**
|
||||
* Matches either "Z" or a positive or negative offset from GMT in which the
|
||||
* colon is optional, such as +04:00 or -1030
|
||||
*/
|
||||
const REGEX_TIMEZONE = '(?<timezone>Z|(\+|\-)(0[0-9]|1[0-9]|2[0-3]):?(0[0-9]|[0-5][0-9]))';
|
||||
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s\-%s\-%s(T| )%s:%s(:%s)?%s$/i',
|
||||
static::REGEX_YEAR,
|
||||
static::REGEX_MONTH,
|
||||
static::REGEX_DAY,
|
||||
static::REGEX_HOUR,
|
||||
static::REGEX_MINUTE,
|
||||
static::REGEX_SECOND,
|
||||
static::REGEX_TIMEZONE,
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
(new DateTime())
|
||||
->setTimezone(
|
||||
self::parseTimezone($matches['timezone'])
|
||||
)
|
||||
->setDate(
|
||||
intval($matches['year']),
|
||||
intval($matches['month']),
|
||||
intval($matches['day'])
|
||||
)
|
||||
->setTime(
|
||||
intval($matches['hour']),
|
||||
intval($matches['minute']),
|
||||
intval(@$matches['second']),
|
||||
intval(@$matches['millisecond']) * 1000
|
||||
)
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static function parseTimezone(string $timezone): DateTimeZone
|
||||
{
|
||||
if ($timezone == 'Z' || $timezone == 'z') {
|
||||
return new DateTimeZone('UTC');
|
||||
} else {
|
||||
return new DateTimeZone(str_replace(':', '', $timezone));
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct(public DateTime $datetime)
|
||||
{
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->datetime->format('c');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use DateTime;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds a date/time that will be stringed to something like
|
||||
* 2011-11-18T14:54:39.929 for use as a local time without an attached timezone.
|
||||
*
|
||||
* Stored internally as a DateTime, which is public and as such can be
|
||||
* conveniently manipulated.
|
||||
*/
|
||||
class DatetimeValue_datetime_local extends DatetimeValue
|
||||
{
|
||||
/** @var DateTime */
|
||||
public $datetime;
|
||||
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s\-%s\-%s(t|T| )%s:%s(:%s)?$/',
|
||||
static::REGEX_YEAR,
|
||||
static::REGEX_MONTH,
|
||||
static::REGEX_DAY,
|
||||
static::REGEX_HOUR,
|
||||
static::REGEX_MINUTE,
|
||||
static::REGEX_SECOND,
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
intval($matches['year']),
|
||||
intval($matches['month']),
|
||||
intval($matches['day']),
|
||||
intval($matches['hour']),
|
||||
intval($matches['minute']),
|
||||
intval(@$matches['second']),
|
||||
intval(@$matches['millisecond'])
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __construct(int $year, int $month, int $day, int $hour, int $minute, int $second = 0, int $millisecond = 0)
|
||||
{
|
||||
$this->datetime = (new DateTime())
|
||||
->setDate($year, $month, $day)
|
||||
->setTime($hour, $minute, $second, $millisecond * 1000);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->datetime->format('Y-m-d\TH:i:s.v');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use DateInterval;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds an interval/duration that will be stringed to something like PT4H18M3S
|
||||
*/
|
||||
class DatetimeValue_duration extends DatetimeValue
|
||||
{
|
||||
/**
|
||||
* Matches a valid duration period designation
|
||||
*/
|
||||
const REGEX_DURATION = "(<duration>P([0-9]+Y)?([0-9]+M)?([0-9]+[WD])?(T([0-9]+H)?([0-9]+M)?([0-9]+S)?)?)";
|
||||
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to construct
|
||||
try {
|
||||
return new self(
|
||||
new DateInterval(strval($string))
|
||||
);
|
||||
} catch (\Throwable $th) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function __construct(protected DateInterval $interval)
|
||||
{
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
// format with all fields
|
||||
$string = $this->interval->format('P%yY%mM%dDT%hH%iM%sS');
|
||||
// strip out fields that are zero
|
||||
/** @var string */
|
||||
$string = preg_replace('/0[YMDHMS]/', '', $string);
|
||||
// strip trailing T if necessary
|
||||
if (str_ends_with($string, 'T')) $string = substr($string, 0, strlen($string) - 1);
|
||||
// return cleaned up value
|
||||
return $string;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds a year/month pair that will be stringed to something like 2011-11
|
||||
*/
|
||||
class DatetimeValue_month extends DatetimeValue
|
||||
{
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s\-%s$/',
|
||||
static::REGEX_YEAR,
|
||||
static::REGEX_MONTH
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
intval($matches['year']),
|
||||
intval($matches['month'])
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __construct(public int $year, public int $week)
|
||||
{
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'%s%04d-%02d',
|
||||
$this->year < 0 ? '-' : '',
|
||||
abs($this->year),
|
||||
$this->week
|
||||
);
|
||||
}
|
||||
}
|
57
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_time.php
Normal file
57
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_time.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use DateTime;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds a time that will be stringed to something like 14.54:39.929
|
||||
*
|
||||
* Stored internally as a DateTime with the date set to today, which is public
|
||||
* and as such can be conveniently manipulated.
|
||||
*/
|
||||
class DatetimeValue_time extends DatetimeValue
|
||||
{
|
||||
/** @var DateTime */
|
||||
public $datetime;
|
||||
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s:%s(:%s)?$/',
|
||||
static::REGEX_HOUR,
|
||||
static::REGEX_MINUTE,
|
||||
static::REGEX_SECOND,
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
intval($matches['hour']),
|
||||
intval($matches['minute']),
|
||||
intval(@$matches['second']),
|
||||
intval(@$matches['microsecond'])
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __construct(int $hour, int $minute, int $second = 0, int $millisecond = 0)
|
||||
{
|
||||
$this->datetime = (new DateTime())
|
||||
->setTime($hour, $minute, $second, $millisecond*1000);
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->datetime->format('H:i:s.v');
|
||||
}
|
||||
}
|
50
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_week.php
Normal file
50
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_week.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Holds a year/week pair that will be stringed to something like 2011-W47
|
||||
*/
|
||||
class DatetimeValue_week extends DatetimeValue
|
||||
{
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s\-W%s$/i',
|
||||
static::REGEX_YEAR,
|
||||
static::REGEX_WEEKNUM
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
intval($matches['year']),
|
||||
intval($matches['weeknum'])
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __construct(public int $year, public int $week)
|
||||
{
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'%s%04d-%02d',
|
||||
$this->year < 0 ? '-' : '',
|
||||
abs($this->year),
|
||||
$this->week
|
||||
);
|
||||
}
|
||||
}
|
44
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_year.php
Normal file
44
src/Html5/InlineTextSemantics/TimeTag/DatetimeValue_year.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use Stringable;
|
||||
|
||||
class DatetimeValue_year extends DatetimeValue
|
||||
{
|
||||
public static function fromString(string|Stringable|null $string): null|self
|
||||
{
|
||||
// null string returns null
|
||||
if (is_null($string)) return null;
|
||||
// try to match regular expression
|
||||
elseif (
|
||||
preg_match(
|
||||
sprintf(
|
||||
'/^%s$/',
|
||||
static::REGEX_YEAR
|
||||
),
|
||||
$string,
|
||||
$matches
|
||||
)
|
||||
) {
|
||||
return new self(
|
||||
intval($matches['year'])
|
||||
);
|
||||
}
|
||||
// return null if nothing found
|
||||
return null;
|
||||
}
|
||||
|
||||
public function __construct(protected int $year)
|
||||
{
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return sprintf(
|
||||
'%s%04d',
|
||||
$this->year < 0 ? '-' : '',
|
||||
abs($this->year)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_date_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"2011-11-18",
|
||||
DatetimeValue_date::fromString("2011-11-18")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range (test zero year)
|
||||
$this->assertEquals(
|
||||
"0000-01-01",
|
||||
DatetimeValue_date::fromString("0000-1-1")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"99999-12-31",
|
||||
DatetimeValue_date::fromString("99999-12-31")
|
||||
?->__toString()
|
||||
);
|
||||
// negative years (BCE)
|
||||
$this->assertEquals(
|
||||
"-1000-12-31",
|
||||
DatetimeValue_date::fromString("-1000-12-31")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromInvalidStrings(): void
|
||||
{
|
||||
// too short year
|
||||
$this->assertNull(
|
||||
DatetimeValue_date::fromString("999-1-1")
|
||||
);
|
||||
// below range
|
||||
$this->assertNull(
|
||||
DatetimeValue_date::fromString("1999-0-1")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date::fromString("1999-1-0")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date::fromString("1999-00-00")
|
||||
);
|
||||
// above range
|
||||
$this->assertNull(
|
||||
DatetimeValue_date::fromString("1999-13-02")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date::fromString("1999-02-32")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date::fromString("1999-13-32")
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_month_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"2011-11",
|
||||
DatetimeValue_month::fromString("2011-11")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range
|
||||
$this->assertEquals(
|
||||
"0000-01",
|
||||
DatetimeValue_month::fromString("0000-01")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"99999-12",
|
||||
DatetimeValue_month::fromString("99999-12")
|
||||
?->__toString()
|
||||
);
|
||||
// negative year
|
||||
$this->assertEquals(
|
||||
"-1500-06",
|
||||
DatetimeValue_month::fromString("-1500-06")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_time_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// examples from mdn
|
||||
$this->assertEquals(
|
||||
"14:54:00.000",
|
||||
DatetimeValue_time::fromString("14:54")
|
||||
?->__toString()
|
||||
);
|
||||
$this->assertEquals(
|
||||
"14:54:39.000",
|
||||
DatetimeValue_time::fromString("14:54:39")
|
||||
?->__toString()
|
||||
);
|
||||
$this->assertEquals(
|
||||
"14:54:39.929",
|
||||
DatetimeValue_time::fromString("14:54:39.929")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range
|
||||
$this->assertEquals(
|
||||
"00:00:00.000",
|
||||
DatetimeValue_time::fromString("00:00:00.000")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"23:59:59.999",
|
||||
DatetimeValue_time::fromString("23:59:59.999")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromInvalidStrings(): void
|
||||
{
|
||||
// hour too big
|
||||
$this->assertNull(
|
||||
DatetimeValue_time::fromString("24:00:00.000")
|
||||
);
|
||||
// minute too big
|
||||
$this->assertNull(
|
||||
DatetimeValue_time::fromString("00:60:00.000")
|
||||
);
|
||||
// second too big
|
||||
$this->assertNull(
|
||||
DatetimeValue_time::fromString("00:00:60.000")
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_week_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"2011-W47",
|
||||
DatetimeValue_week::fromString("2011-W47")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range
|
||||
$this->assertEquals(
|
||||
"0000-W01",
|
||||
DatetimeValue_week::fromString("0000-W01")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"99999-W53",
|
||||
DatetimeValue_week::fromString("99999-W53")
|
||||
?->__toString()
|
||||
);
|
||||
// negative year
|
||||
$this->assertEquals(
|
||||
"-1500-06",
|
||||
DatetimeValue_week::fromString("-1500-06")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromInvalidStrings(): void
|
||||
{
|
||||
// week too small
|
||||
$this->assertNull(
|
||||
DatetimeValue_week::fromString("0000-W00")
|
||||
);
|
||||
// week too big
|
||||
$this->assertNull(
|
||||
DatetimeValue_week::fromString("0000-W54")
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_year_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"2011",
|
||||
DatetimeValue_year::fromString("2011")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range
|
||||
$this->assertEquals(
|
||||
"0000",
|
||||
DatetimeValue_year::fromString("0000")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"99999",
|
||||
DatetimeValue_year::fromString("99999")
|
||||
?->__toString()
|
||||
);
|
||||
// negative year with only three digits
|
||||
$this->assertEquals(
|
||||
"-0150",
|
||||
DatetimeValue_year::fromString("-0150")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromInvalidStrings(): void
|
||||
{
|
||||
// year is too short
|
||||
$this->assertNull(
|
||||
DatetimeValue_year::fromString("123")
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_date_yearless_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"11-18",
|
||||
DatetimeValue_date_yearless::fromString("11-18")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range
|
||||
$this->assertEquals(
|
||||
"01-01",
|
||||
DatetimeValue_date_yearless::fromString("1-1")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"12-31",
|
||||
DatetimeValue_date_yearless::fromString("12-31")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromInvalidStrings(): void
|
||||
{
|
||||
// below range
|
||||
$this->assertNull(
|
||||
DatetimeValue_date_yearless::fromString("0-1")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date_yearless::fromString("1-0")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date_yearless::fromString("00-00")
|
||||
);
|
||||
// above range
|
||||
$this->assertNull(
|
||||
DatetimeValue_date_yearless::fromString("13-02")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date_yearless::fromString("02-32")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_date_yearless::fromString("13-32")
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_datetime_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"2011-11-18T14:54:39+00:00",
|
||||
DatetimeValue_datetime::fromString("2011-11-18T14:54:39Z")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range
|
||||
$this->assertEquals(
|
||||
"0000-01-01T00:00:00-23:59",
|
||||
DatetimeValue_datetime::fromString("0000-01-01 00:00:00-23:59")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"99999-12-31T23:59:59+23:59",
|
||||
DatetimeValue_datetime::fromString("99999-12-31T23:59:59+23:59")
|
||||
?->__toString()
|
||||
);
|
||||
// negative years (BCE)
|
||||
$this->assertEquals(
|
||||
"-1000-12-31T23:59:59+00:00",
|
||||
DatetimeValue_datetime::fromString("-1000-12-31T23:59:59+0000")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DatetimeValue_datetime_local_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"2011-11-18T14:54:39.929",
|
||||
DatetimeValue_datetime_local::fromString("2011-11-18T14:54:39.929")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range (test zero year)
|
||||
$this->assertEquals(
|
||||
"0000-01-01T00:00:00.000",
|
||||
DatetimeValue_datetime_local::fromString("0000-01-01 00:00:00.000")
|
||||
?->__toString()
|
||||
);
|
||||
// top of range
|
||||
$this->assertEquals(
|
||||
"99999-12-31T23:59:59.999",
|
||||
DatetimeValue_datetime_local::fromString("99999-12-31T23:59:59.999")
|
||||
?->__toString()
|
||||
);
|
||||
// negative years (BCE)
|
||||
$this->assertEquals(
|
||||
"-1000-12-31T23:59:59.999",
|
||||
DatetimeValue_datetime_local::fromString("-1000-12-31T23:59:59.999")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromInvalidStrings(): void
|
||||
{
|
||||
// too short microseconds
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("1999-1-1T23:59:59.99")
|
||||
);
|
||||
// too short year
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("999-1-1T23:59:59.999")
|
||||
);
|
||||
// below range
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("1999-0-1T23:59:59.999")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("1999-1-0T23:59:59.999")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("1999-00-00T23:59:59.999")
|
||||
);
|
||||
// above range
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("1999-13-02T23:59:59.999")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("1999-02-32T23:59:59.999")
|
||||
);
|
||||
$this->assertNull(
|
||||
DatetimeValue_datetime_local::fromString("1999-13-32T23:59:59.999")
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace ByJoby\HTML\Html5\InlineTextSemantics\TimeTag;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Honestly this one doesn't need a lot of testing, because it just uses PHP's
|
||||
* DateInterval built-in parsing
|
||||
*/
|
||||
class DatetimeValue_duration_Test extends TestCase
|
||||
{
|
||||
public function testFromValidStrings(): void
|
||||
{
|
||||
// example from mdn
|
||||
$this->assertEquals(
|
||||
"PT4H18M3S",
|
||||
DatetimeValue_duration::fromString("PT4H18M3S")
|
||||
?->__toString()
|
||||
);
|
||||
// bottom of range
|
||||
$this->assertEquals(
|
||||
"PT1S",
|
||||
DatetimeValue_duration::fromString("PT1S")
|
||||
?->__toString()
|
||||
);
|
||||
// all values
|
||||
$this->assertEquals(
|
||||
"P99Y99M99DT99H99M99S",
|
||||
DatetimeValue_duration::fromString("P99Y99M99DT99H99M99S")
|
||||
?->__toString()
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue