-
Notifications
You must be signed in to change notification settings - Fork 25
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #210 from ampproject/add/32-auto-extensions
- Loading branch information
Showing
13 changed files
with
1,455 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
|
||
namespace AmpProject\Dom\Document\Filter; | ||
|
||
use AmpProject\Dom\Document\AfterSaveFilter; | ||
use AmpProject\Dom\Document\BeforeLoadFilter; | ||
use AmpProject\Tag; | ||
|
||
/** | ||
* Filter to secure and restore self-closing SVG related elements. | ||
* | ||
* @package ampproject/amp-toolbox | ||
*/ | ||
final class SelfClosingSVGElements implements BeforeLoadFilter, AfterSaveFilter | ||
{ | ||
|
||
/** | ||
* SVG elements that are self-closing. | ||
* | ||
* @var string[] | ||
*/ | ||
const SELF_CLOSING_TAGS = [ | ||
Tag::CIRCLE, | ||
Tag::G, | ||
Tag::PATH, | ||
]; | ||
|
||
/** | ||
* Force all self-closing tags to have closing tags. | ||
* | ||
* @param string $html HTML string to adapt. | ||
* @return string Adapted HTML string. | ||
*/ | ||
public function beforeLoad($html) | ||
{ | ||
static $regexPattern = null; | ||
|
||
if (null === $regexPattern) { | ||
$regexPattern = '#<(' . implode('|', self::SELF_CLOSING_TAGS) . ')([^>]*?)(?>\s*(?<!\\\\)/)?>(?!.*</\1>)#'; | ||
} | ||
|
||
return preg_replace($regexPattern, '<$1$2></$1>', $html); | ||
} | ||
|
||
/** | ||
* Restore all self-closing tags again. | ||
* | ||
* @param string $html HTML string to adapt. | ||
* @return string Adapted HTML string. | ||
*/ | ||
public function afterSave($html) | ||
{ | ||
static $regexPattern = null; | ||
|
||
if (null === $regexPattern) { | ||
$regexPattern = '#<(' . implode('|', self::SELF_CLOSING_TAGS) . ')([^>]*?)(?>\s*(?<!\\\\)\/)?>(<\/\1>)#i'; | ||
} | ||
|
||
return preg_replace($regexPattern, '<$1$2 />', $html); | ||
} | ||
} |
183 changes: 183 additions & 0 deletions
183
src/Optimizer/Configuration/AutoExtensionsConfiguration.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
<?php | ||
|
||
namespace AmpProject\Optimizer\Configuration; | ||
|
||
use AmpProject\Amp; | ||
use AmpProject\Exception\InvalidExtension; | ||
use AmpProject\Extension; | ||
use AmpProject\Format; | ||
use AmpProject\Optimizer\Exception\InvalidConfigurationValue; | ||
use ReflectionClass; | ||
|
||
/** | ||
* Configuration for the AutoExtensions transformer. | ||
* | ||
* @property string $format Specifies the AMP format. Defaults to `AMP`. | ||
* @property bool $autoExtensionImport Set to `false` to disable the auto extension import. Defaults to `true`. | ||
* @property bool $experimentBindAttribute Enables experimental conversion of bind attributes. Defaults to `false`. | ||
* | ||
* @package ampproject/amp-toolbox | ||
*/ | ||
final class AutoExtensionsConfiguration extends BaseTransformerConfiguration | ||
{ | ||
|
||
/** | ||
* Configuration key that specifies the AMP format. | ||
* | ||
* @var string | ||
*/ | ||
const FORMAT = 'format'; | ||
|
||
/** | ||
* Configuration key that can disable the automatic importing of extension. | ||
* | ||
* @var string | ||
*/ | ||
const AUTO_EXTENSION_IMPORT = 'autoExtensionImport'; | ||
|
||
/** | ||
* Configuration key that enables experimental conversion of bind attributes. | ||
* | ||
* @var string | ||
*/ | ||
const EXPERIMENT_BIND_ATTRIBUTE = 'experimentBindAttribute'; | ||
|
||
/** | ||
* Configuration key that allows individual configuration of extension versions. | ||
* | ||
* @var string | ||
*/ | ||
const EXTENSION_VERSIONS = 'extensionVersions'; | ||
|
||
/** | ||
* An array of extension names that will not auto import. | ||
* | ||
* @var string | ||
*/ | ||
const IGNORED_EXTENSIONS = 'ignoredExtensions'; | ||
|
||
/** | ||
* An array of extension names that will not auto import. | ||
* | ||
* @var string | ||
*/ | ||
const REMOVE_UNNEEDED_EXTENSIONS = 'removeUnneededExtensions'; | ||
|
||
/** | ||
* Get the associative array of allowed keys and their respective default values. | ||
* | ||
* The array index is the key and the array value is the key's default value. | ||
* | ||
* @return array Associative array of allowed keys and their respective default values. | ||
*/ | ||
protected function getAllowedKeys() | ||
{ | ||
return [ | ||
self::FORMAT => Format::AMP, | ||
self::AUTO_EXTENSION_IMPORT => true, | ||
self::EXPERIMENT_BIND_ATTRIBUTE => false, | ||
self::EXTENSION_VERSIONS => [], | ||
self::IGNORED_EXTENSIONS => [], | ||
self::REMOVE_UNNEEDED_EXTENSIONS => false, | ||
]; | ||
} | ||
|
||
/** | ||
* Validate an individual configuration entry. | ||
* | ||
* @param string $key Key of the configuration entry to validate. | ||
* @param mixed $value Value of the configuration entry to validate. | ||
* @return mixed Validated value. | ||
*/ | ||
protected function validate($key, $value) | ||
{ | ||
switch ($key) { | ||
case self::FORMAT: | ||
if (! is_string($value)) { | ||
throw InvalidConfigurationValue::forInvalidSubValueType( | ||
self::class, | ||
self::FORMAT, | ||
'string', | ||
gettype($value) | ||
); | ||
} | ||
|
||
if (! in_array($value, Amp::FORMATS, true)) { | ||
throw InvalidConfigurationValue::forUnknownSubValue( | ||
self::class, | ||
self::FORMAT, | ||
Amp::FORMATS, | ||
$value | ||
); | ||
} | ||
break; | ||
|
||
case self::AUTO_EXTENSION_IMPORT: | ||
if (! is_bool($value)) { | ||
throw InvalidConfigurationValue::forInvalidSubValueType( | ||
self::class, | ||
self::AUTO_EXTENSION_IMPORT, | ||
'boolean', | ||
gettype($value) | ||
); | ||
} | ||
break; | ||
|
||
case self::EXPERIMENT_BIND_ATTRIBUTE: | ||
if (! is_bool($value)) { | ||
throw InvalidConfigurationValue::forInvalidSubValueType( | ||
self::class, | ||
self::EXPERIMENT_BIND_ATTRIBUTE, | ||
'boolean', | ||
gettype($value) | ||
); | ||
} | ||
break; | ||
|
||
case self::EXTENSION_VERSIONS: | ||
if (! is_array($value)) { | ||
throw InvalidConfigurationValue::forInvalidSubValueType( | ||
self::class, | ||
self::EXTENSION_VERSIONS, | ||
'array', | ||
gettype($value) | ||
); | ||
} | ||
break; | ||
|
||
case self::IGNORED_EXTENSIONS: | ||
if (! is_array($value)) { | ||
throw InvalidConfigurationValue::forInvalidSubValueType( | ||
self::class, | ||
self::IGNORED_EXTENSIONS, | ||
'array', | ||
gettype($value) | ||
); | ||
} | ||
|
||
// Assert that the extension names in the ignore list are valid extensions. | ||
$reflection = new ReflectionClass(Extension::class); | ||
$constants = $reflection->getConstants(); | ||
|
||
foreach ($value as $extension) { | ||
if (! in_array($extension, $constants, true)) { | ||
throw InvalidExtension::forExtension($extension); | ||
} | ||
} | ||
break; | ||
|
||
case self::REMOVE_UNNEEDED_EXTENSIONS: | ||
if (! is_bool($value)) { | ||
throw InvalidConfigurationValue::forInvalidSubValueType( | ||
self::class, | ||
self::REMOVE_UNNEEDED_EXTENSIONS, | ||
'boolean', | ||
gettype($value) | ||
); | ||
} | ||
break; | ||
} | ||
|
||
return $value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
namespace AmpProject\Optimizer\Error; | ||
|
||
use AmpProject\Dom\Element; | ||
use AmpProject\Dom\ElementDump; | ||
use AmpProject\Optimizer\Error; | ||
use Exception; | ||
|
||
/** | ||
* Optimizer error object for invalid JSON data. | ||
* | ||
* @package ampproject/amp-toolbox | ||
*/ | ||
final class CannotParseJsonData implements Error | ||
{ | ||
use ErrorProperties; | ||
|
||
const SCRIPT_EXCEPTION_MESSAGE = 'Cannot parse JSON data for script element %2$s: %1$s.'; | ||
|
||
/** | ||
* Instantiate a CannotParseJsonData object for an exception that was thrown. | ||
* | ||
* @param Exception $exception Exception that was thrown. | ||
* @param Element $script DOM element of the <style amp-runtime> tag that was targeted. | ||
* @return self | ||
*/ | ||
public static function fromExceptionForScriptElement(Exception $exception, Element $script) | ||
{ | ||
return new self(sprintf(self::SCRIPT_EXCEPTION_MESSAGE, $exception, new ElementDump($script))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.