Commit d4ecca65 by lmf

增加插件定制产品和订单管理

parent deee4193
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Backend\App\Action;
class Creditmemo extends \Magento\Backend\App\Action
{
/**
* @var \Magento\Sales\Api\CreditmemoRepositoryInterface
*/
protected $creditmemoRepository;
/**
* @var \Bss\DeleteOrder\Model\Creditmemo\Delete
*/
protected $delete;
/**
* Creditmemo constructor.
* @param Action\Context $context
* @param \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository
* @param \Bss\DeleteOrder\Model\Creditmemo\Delete $delete
*/
public function __construct(
Action\Context $context,
\Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository,
\Bss\DeleteOrder\Model\Creditmemo\Delete $delete
) {
$this->creditmemoRepository = $creditmemoRepository;
$this->delete = $delete;
parent::__construct($context);
}
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
$creditmemoId = $this->getRequest()->getParam('creditmemo_id');
$creditmemo = $this->creditmemoRepository->get($creditmemoId);
try {
$this->delete->deleteCreditmemo($creditmemoId);
$this->messageManager->addSuccessMessage(__('Successfully deleted credit memo #%1.', $creditmemo->getIncrementId()));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete credit memo #%1.', $creditmemo->getIncrementId()));
}
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('sales/creditmemo/');
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Backend\App\Action;
class Invoice extends \Magento\Backend\App\Action
{
/**
* @var \Magento\Sales\Api\InvoiceRepositoryInterface
*/
protected $invoiceRepository;
/**
* @var \Bss\DeleteOrder\Model\Invoice\Delete
*/
protected $delete;
/**
* Invoice constructor.
* @param Action\Context $context
* @param \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository
* @param \Bss\DeleteOrder\Model\Invoice\Delete $delete
*/
public function __construct(
Action\Context $context,
\Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository,
\Bss\DeleteOrder\Model\Invoice\Delete $delete
) {
$this->invoiceRepository = $invoiceRepository;
$this->delete = $delete;
parent::__construct($context);
}
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
$invoiceId = $this->getRequest()->getParam('invoice_id');
$invoice = $this->invoiceRepository->get($invoiceId);
try {
$this->delete->deleteInvoice($invoiceId);
$this->messageManager->addSuccessMessage(__('Successfully deleted invoice #%1.', $invoice->getIncrementId()));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete invoice #%1.', $invoice->getIncrementId()));
}
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('sales/invoice/');
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Sales\Api\OrderManagementInterface;
class MassCreditmemo extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
{
/**
* @var OrderManagementInterface
*/
protected $orderManagement;
/**
* @var \Magento\Sales\Model\ResourceModel\Order\Creditmemo\CollectionFactory
*/
protected $memoCollectionFactory;
/**
* @var \Magento\Sales\Api\CreditmemoRepositoryInterface
*/
protected $creditmemoRepository;
/**
* @var \Bss\DeleteOrder\Model\Creditmemo\Delete
*/
protected $delete;
/**
* MassCreditmemo constructor.
* @param Context $context
* @param Filter $filter
* @param OrderManagementInterface $orderManagement
* @param \Magento\Sales\Model\ResourceModel\Order\Creditmemo\CollectionFactory $memoCollectionFactory
* @param \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository
* @param \Bss\DeleteOrder\Model\Creditmemo\Delete $delete
*/
public function __construct(
Context $context,
Filter $filter,
CollectionFactory $collectionFactory,
OrderManagementInterface $orderManagement,
\Magento\Sales\Model\ResourceModel\Order\Creditmemo\CollectionFactory $memoCollectionFactory,
\Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository,
\Bss\DeleteOrder\Model\Creditmemo\Delete $delete
) {
parent::__construct($context, $filter);
$this->collectionFactory = $collectionFactory;
$this->orderManagement = $orderManagement;
$this->memoCollectionFactory = $memoCollectionFactory;
$this->creditmemoRepository = $creditmemoRepository;
$this->delete = $delete;
}
/**
* @param AbstractCollection $collection
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
protected function massAction(AbstractCollection $collection)
{
$params = $this->getRequest()->getParams();
$selected = [];
$collectionMemo = $this->filter->getCollection($this->memoCollectionFactory->create());
foreach ($collectionMemo as $memo) {
array_push($selected, $memo->getId());
}
if ($selected) {
foreach ($selected as $creditmemoId) {
$creditmemo = $this->creditmemoRepository->get($creditmemoId);
try {
$order = $this->deleteCreditMemo($creditmemoId);
$this->messageManager->addSuccessMessage(__('Successfully deleted credit memo #%1.', $creditmemo->getIncrementId()));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete credit memo #%1.', $creditmemo->getIncrementId()));
}
}
}
$resultRedirect = $this->resultRedirectFactory->create();
if ($params['namespace'] == 'sales_order_view_creditmemo_grid') {
$resultRedirect->setPath('sales/order/view', ['order_id' => $order->getId()]);
} else {
$resultRedirect->setPath('sales/creditmemo/');
}
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
/**
* @param $creditmemoId
* @return \Magento\Sales\Model\Order
* @throws \Exception
*/
protected function deleteCreditMemo($creditmemoId)
{
return $this->delete->deleteCreditmemo($creditmemoId);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Sales\Api\OrderManagementInterface;
class MassInvoice extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
{
/**
* @var OrderManagementInterface
*/
protected $orderManagement;
/**
* @var \Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory
*/
protected $invoiceCollectionFactory;
/**
* @var \Magento\Sales\Api\InvoiceRepositoryInterface
*/
protected $invoiceRepository;
/**
* @var \Bss\DeleteOrder\Model\Invoice\Delete
*/
protected $delete;
/**
* MassInvoice constructor.
* @param Context $context
* @param Filter $filter
* @param OrderManagementInterface $orderManagement
* @param \Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory $invoiceCollectionFactory
* @param \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository
* @param \Bss\DeleteOrder\Model\Invoice\Delete $delete
*/
public function __construct(
Context $context,
Filter $filter,
CollectionFactory $collectionFactory,
OrderManagementInterface $orderManagement,
\Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory $invoiceCollectionFactory,
\Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository,
\Bss\DeleteOrder\Model\Invoice\Delete $delete
) {
parent::__construct($context, $filter);
$this->collectionFactory = $collectionFactory;
$this->orderManagement = $orderManagement;
$this->invoiceCollectionFactory = $invoiceCollectionFactory;
$this->invoiceRepository = $invoiceRepository;
$this->delete = $delete;
}
/**
* @param AbstractCollection $collection
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
protected function massAction(AbstractCollection $collection)
{
$params = $this->getRequest()->getParams();
$selected = [];
$collectionInvoice = $this->filter->getCollection($this->invoiceCollectionFactory->create());
foreach ($collectionInvoice as $invoice) {
array_push($selected, $invoice->getId());
}
if ($selected) {
foreach ($selected as $invoiceId) {
$invoice = $this->invoiceRepository->get($invoiceId);
try {
$order = $this->deleteInvoice($invoiceId);
$this->messageManager->addSuccessMessage(__('Successfully deleted invoice #%1.', $invoice->getIncrementId()));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete invoice #%1.', $invoice->getIncrementId()));
}
}
}
$resultRedirect = $this->resultRedirectFactory->create();
if ($params['namespace'] == 'sales_order_view_invoice_grid') {
$resultRedirect->setPath('sales/order/view', ['order_id' => $order->getId()]);
} else {
$resultRedirect->setPath('sales/invoice/');
}
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
/**
* @param $invoiceId
* @return \Bss\DeleteOrder\Model\Invoice\Delete
*/
protected function deleteInvoice($invoiceId)
{
return $this->delete->deleteInvoice($invoiceId);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Backend\App\Action\Context;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Sales\Api\OrderManagementInterface;
class MassOrder extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
{
/**
* @var OrderManagementInterface
*/
protected $orderManagement;
/**
* @var CollectionFactory
*/
protected $orderCollectionFactory;
/**
* @var \Bss\DeleteOrder\Model\Order\Delete
*/
protected $delete;
/**
* MassOrder constructor.
* @param Context $context
* @param Filter $filter
* @param OrderManagementInterface $orderManagement
* @param CollectionFactory $orderCollectionFactory
* @param \Bss\DeleteOrder\Model\Order\Delete $delete
*/
public function __construct(
Context $context,
Filter $filter,
CollectionFactory $collectionFactory,
OrderManagementInterface $orderManagement,
\Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
\Bss\DeleteOrder\Model\Order\Delete $delete
) {
parent::__construct($context, $filter);
$this->collectionFactory = $collectionFactory;
$this->orderManagement = $orderManagement;
$this->orderCollectionFactory = $orderCollectionFactory;
$this->delete = $delete;
}
/**
* @param AbstractCollection $collection
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
protected function massAction(AbstractCollection $collection)
{
$collectionInvoice = $this->filter->getCollection($this->orderCollectionFactory->create());
foreach ($collectionInvoice as $order) {
$orderId = $order->getId();
$incrementId = $order->getIncrementId();
try {
$this->deleteOrder($orderId);
$this->messageManager->addSuccessMessage(__('Successfully deleted order #%1.', $incrementId));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete order #%1.', $incrementId));
}
}
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('sales/order/');
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
/**
* @param $orderId
* @throws \Exception
*/
protected function deleteOrder($orderId)
{
$this->delete->deleteOrder($orderId);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection;
use Magento\Backend\App\Action\Context;
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
use Magento\Ui\Component\MassAction\Filter;
use Magento\Sales\Api\OrderManagementInterface;
class MassShipment extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction
{
/**
* @var OrderManagementInterface
*/
protected $orderManagement;
/**
* @var \Magento\Sales\Model\ResourceModel\Order\Shipment\CollectionFactory
*/
protected $shipmentCollectionFactory;
/**
* @var \Magento\Sales\Model\Order\Shipment
*/
protected $shipment;
/**
* @var \Bss\DeleteOrder\Model\Shipment\Delete
*/
protected $delete;
/**
* MassShipment constructor.
* @param Context $context
* @param Filter $filter
* @param OrderManagementInterface $orderManagement
* @param \Magento\Sales\Model\ResourceModel\Order\Shipment\CollectionFactory $shipmentCollectionFactory
* @param \Magento\Sales\Model\Order\Shipment $shipment
* @param \Bss\DeleteOrder\Model\Shipment\Delete $delete
*/
public function __construct(
Context $context,
Filter $filter,
CollectionFactory $collectionFactory,
OrderManagementInterface $orderManagement,
\Magento\Sales\Model\ResourceModel\Order\Shipment\CollectionFactory $shipmentCollectionFactory,
\Magento\Sales\Model\Order\Shipment $shipment,
\Bss\DeleteOrder\Model\Shipment\Delete $delete
) {
parent::__construct($context, $filter);
$this->collectionFactory = $collectionFactory;
$this->orderManagement = $orderManagement;
$this->shipmentCollectionFactory = $shipmentCollectionFactory;
$this->shipment = $shipment;
$this->delete = $delete;
}
/**
* @param AbstractCollection $collection
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
protected function massAction(AbstractCollection $collection)
{
$params = $this->getRequest()->getParams();
$selected = [];
$collectionShipment = $this->filter->getCollection($this->shipmentCollectionFactory->create());
foreach ($collectionShipment as $shipment) {
array_push($selected, $shipment->getId());
}
if ($selected) {
foreach ($selected as $shipmentId) {
$shipment = $this->getShipmentbyId($shipmentId);
try {
$order = $this->deleteShipment($shipmentId);
$this->messageManager->addSuccessMessage(__('Successfully deleted shipment #%1.', $shipment->getIncrementId()));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete shipment #%1.', $shipment->getIncrementId()));
}
}
}
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('sales/shipment/');
if ($params['namespace'] == 'sales_order_view_shipment_grid') {
$resultRedirect->setPath('sales/order/view', ['order_id' => $order->getId()]);
} else {
$resultRedirect->setPath('sales/shipment/');
}
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
/**
* @param $shipmentId
* @return \Magento\Sales\Model\Order
* @throws \Exception
*/
protected function deleteShipment($shipmentId)
{
return $this->delete->deleteShipment($shipmentId);
}
/**
* @param $shipmentId
* @return \Magento\Sales\Model\Order\Shipment
*/
protected function getShipmentbyId($shipmentId)
{
return $this->shipment->load($shipmentId);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Backend\App\Action;
class Order extends \Magento\Backend\App\Action
{
/**
* @var \Magento\Sales\Model\Order
*/
protected $order;
/**
* @var \Bss\DeleteOrder\Model\Order\Delete
*/
protected $delete;
/**
* Order constructor.
* @param Action\Context $context
* @param \Magento\Sales\Model\Order $order
* @param \Bss\DeleteOrder\Model\Order\Delete $delete
*/
public function __construct(
Action\Context $context,
\Magento\Sales\Model\Order $order,
\Bss\DeleteOrder\Model\Order\Delete $delete
) {
$this->order = $order;
$this->delete = $delete;
parent::__construct($context);
}
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
$orderId = $this->getRequest()->getParam('order_id');
$order = $this->order->load($orderId);
$incrementId = $order->getIncrementId();
try {
$this->delete->deleteOrder($orderId);
$this->messageManager->addSuccessMessage(__('Successfully deleted order #%1.', $incrementId));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete order #%1.', $incrementId));
}
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('sales/order/');
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Controller\Adminhtml\Delete;
use Magento\Backend\App\Action;
class Shipment extends \Magento\Backend\App\Action
{
/**
* @var \Magento\Sales\Model\Order\Shipment
*/
protected $shipment;
/**
* @var \Bss\DeleteOrder\Model\Shipment\Delete
*/
protected $delete;
/**
* Shipment constructor.
* @param Action\Context $context
* @param \Magento\Sales\Model\Order\Shipment $shipment
* @param \Bss\DeleteOrder\Model\Shipment\Delete $delete
*/
public function __construct(
Action\Context $context,
\Magento\Sales\Model\Order\Shipment $shipment,
\Bss\DeleteOrder\Model\Shipment\Delete $delete
) {
$this->shipment = $shipment;
$this->delete = $delete;
parent::__construct($context);
}
/**
* @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Redirect|\Magento\Framework\Controller\ResultInterface
*/
public function execute()
{
$shipmentId = $this->getRequest()->getParam('shipment_id');
$shipment = $this->shipment->load($shipmentId);
try {
$this->delete->deleteShipment($shipmentId);
$this->messageManager->addSuccessMessage(__('Successfully deleted shipment #%1.', $shipment->getIncrementId()));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('Error delete shipment #%1.', $shipment->getIncrementId()));
}
$resultRedirect = $this->resultRedirectFactory->create();
$resultRedirect->setPath('sales/shipment/');
return $resultRedirect;
}
/*
* Check permission via ACL resource
*/
protected function _isAllowed()
{
return $this->_authorization->isAllowed('Bss_DeleteOrder::delete_order');
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Helper;
use Magento\Framework\App\DeploymentConfig;
use Magento\Framework\Config\ConfigOptionsListConstants;
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
/**
* @var DeploymentConfig
*/
protected $deploymentConfig;
/**
* Data constructor.
* @param \Magento\Framework\App\Helper\Context $context
* @param DeploymentConfig $deploymentConfig
*/
public function __construct(
\Magento\Framework\App\Helper\Context $context,
DeploymentConfig $deploymentConfig
) {
parent::__construct($context);
$this->deploymentConfig = $deploymentConfig;
}
/**
* @param null $name
* @return bool|string|null
*/
public function getTableName($name = null)
{
if ($name == null) {
return false;
}
$tableName = $name;
$tablePrefix = (string)$this->deploymentConfig->get(
ConfigOptionsListConstants::CONFIG_PATH_DB_PREFIX
);
if ($tablePrefix) {
$tableName = $tablePrefix . $name;
}
return $tableName;
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Model\Creditmemo;
use Magento\Framework\App\ResourceConnection;
class Delete
{
/**
* @var ResourceConnection
*/
protected $resource;
/**
* @var \Bss\DeleteOrder\Helper\Data
*/
protected $data;
/**
* @var \Magento\Sales\Api\CreditmemoRepositoryInterface
*/
protected $creditmemoRepository;
/**
* @var \Magento\Sales\Model\Order
*/
protected $order;
/**
* Delete constructor.
* @param ResourceConnection $resource
* @param \Bss\DeleteOrder\Helper\Data $data
* @param \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository
* @param \Magento\Sales\Model\Order $order
*/
public function __construct(
ResourceConnection $resource,
\Bss\DeleteOrder\Helper\Data $data,
\Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository,
\Magento\Sales\Model\Order $order
) {
$this->resource = $resource;
$this->data = $data;
$this->creditmemoRepository = $creditmemoRepository;
$this->order = $order;
}
/**
* @param $creditmemoId
* @return \Magento\Sales\Model\Order
* @throws \Exception
*/
public function deleteCreditmemo($creditmemoId)
{
$connection = $this->resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
$creditmemoGridTable = $connection->getTableName($this->data->getTableName('sales_creditmemo_grid'));
$creditmemoTable = $connection->getTableName($this->data->getTableName('sales_creditmemo'));
$creditmemo = $this->creditmemoRepository->get($creditmemoId);
$orderId = $creditmemo->getOrder()->getId();
$order = $this->order->load($orderId);
$orderItems = $order->getAllItems();
$creditmemoItems = $creditmemo->getAllItems();
// revert item in order
foreach ($orderItems as $item) {
foreach ($creditmemoItems as $creditmemoItem) {
if ($creditmemoItem->getOrderItemId() == $item->getItemId()) {
$item->setQtyRefunded($item->getQtyRefunded() - $creditmemoItem->getQty());
$item->setTaxRefunded($item->getTaxRefunded() - $creditmemoItem->getTaxAmount());
$item->setBaseTaxRefunded($item->getBaseTaxRefunded() - $creditmemoItem->getBaseTaxAmount());
$discountTaxItem = $item->getDiscountTaxCompensationRefunded();
$discountTaxCredit = $creditmemoItem->getDiscountTaxCompensationAmount();
$item->setDiscountTaxCompensationRefunded(
$discountTaxItem - $discountTaxCredit
);
$baseDiscountItem = $item->getBaseDiscountTaxCompensationRefunded();
$baseDiscountCredit = $creditmemoItem->getBaseDiscountTaxCompensationAmount();
$item->setBaseDiscountTaxCompensationRefunded(
$baseDiscountItem - $baseDiscountCredit
);
$item->setAmountRefunded($item->getAmountRefunded() - $creditmemoItem->getRowTotal());
$item->setBaseAmountRefunded($item->getBaseAmountRefunded() - $creditmemoItem->getBaseRowTotal());
$item->setDiscountRefunded($item->getDiscountRefunded() - $creditmemoItem->getDiscountAmount());
$item->setBaseDiscountRefunded(
$item->getBaseDiscountRefunded() - $creditmemoItem->getBaseDiscountAmount()
);
}
}
}
// revert info in order
$order->setBaseTotalRefunded($order->getBaseTotalRefunded() - $creditmemo->getBaseGrandTotal());
$order->setTotalRefunded($order->getTotalRefunded() - $creditmemo->getGrandTotal());
$order->setBaseSubtotalRefunded($order->getBaseSubtotalRefunded() - $creditmemo->getBaseSubtotal());
$order->setSubtotalRefunded($order->getSubtotalRefunded() - $creditmemo->getSubtotal());
$order->setBaseTaxRefunded($order->getBaseTaxRefunded() - $creditmemo->getBaseTaxAmount());
$order->setTaxRefunded($order->getTaxRefunded() - $creditmemo->getTaxAmount());
$order->setBaseDiscountTaxCompensationRefunded(
$order->getBaseDiscountTaxCompensationRefunded() - $creditmemo->getBaseDiscountTaxCompensationAmount()
);
$order->setDiscountTaxCompensationRefunded(
$order->getDiscountTaxCompensationRefunded() - $creditmemo->getDiscountTaxCompensationAmount()
);
$order->setBaseShippingRefunded($order->getBaseShippingRefunded() - $creditmemo->getBaseShippingAmount());
$order->setShippingRefunded($order->getShippingRefunded() - $creditmemo->getShippingAmount());
$order->setBaseShippingTaxRefunded(
$order->getBaseShippingTaxRefunded() - $creditmemo->getBaseShippingTaxAmount()
);
$order->setShippingTaxRefunded($order->getShippingTaxRefunded() - $creditmemo->getShippingTaxAmount());
$order->setAdjustmentPositive($order->getAdjustmentPositive() - $creditmemo->getAdjustmentPositive());
$order->setBaseAdjustmentPositive(
$order->getBaseAdjustmentPositive() - $creditmemo->getBaseAdjustmentPositive()
);
$order->setAdjustmentNegative($order->getAdjustmentNegative() - $creditmemo->getAdjustmentNegative());
$order->setBaseAdjustmentNegative(
$order->getBaseAdjustmentNegative() - $creditmemo->getBaseAdjustmentNegative()
);
$order->setDiscountRefunded($order->getDiscountRefunded() - $creditmemo->getDiscountAmount());
$order->setBaseDiscountRefunded($order->getBaseDiscountRefunded() - $creditmemo->getBaseDiscountAmount());
$this->setTotalandBaseTotal($creditmemo, $order);
// delete creditmemo info
$connection->rawQuery('DELETE FROM `'.$creditmemoGridTable.'` WHERE entity_id='.$creditmemoId);
$connection->rawQuery('DELETE FROM `'.$creditmemoTable.'` WHERE entity_id='.$creditmemoId);
$this->saveOrder($order);
return $order;
}
/**
* @param $creditmemo
* @param $order
*/
protected function setTotalandBaseTotal($creditmemo, $order)
{
if ($creditmemo->getDoTransaction()) {
$order->setTotalOnlineRefunded($order->getTotalOnlineRefunded() - $creditmemo->getGrandTotal());
$order->setBaseTotalOnlineRefunded($order->getBaseTotalOnlineRefunded() - $creditmemo->getBaseGrandTotal());
} else {
$order->setTotalOfflineRefunded($order->getTotalOfflineRefunded() - $creditmemo->getGrandTotal());
$order->setBaseTotalOfflineRefunded(
$order->getBaseTotalOfflineRefunded() - $creditmemo->getBaseGrandTotal()
);
}
}
/**
* @param $order
*/
protected function saveOrder($order)
{
if ($order->hasShipments() || $order->hasInvoices() || $order->hasCreditmemos()) {
$order->setState(\Magento\Sales\Model\Order::STATE_PROCESSING)
->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_PROCESSING))
->save();
} elseif (!$order->canInvoice() && !$order->canShip() && !$order->hasCreditmemos()) {
$order->setState(\Magento\Sales\Model\Order::STATE_COMPLETE)
->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_COMPLETE))
->save();
} else {
$order->setState(\Magento\Sales\Model\Order::STATE_NEW)
->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_NEW))
->save();
}
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Model\Invoice;
use Magento\Framework\App\ResourceConnection;
class Delete
{
/**
* @var ResourceConnection
*/
protected $resource;
/**
* @var \Bss\DeleteOrder\Helper\Data
*/
protected $data;
/**
* @var \Magento\Sales\Api\InvoiceRepositoryInterface
*/
protected $invoiceRepository;
/**
* @var \Magento\Sales\Model\Order
*/
protected $order;
/**
* Delete constructor.
* @param ResourceConnection $resource
* @param \Bss\DeleteOrder\Helper\Data $data
* @param \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository
* @param \Magento\Sales\Model\Order $order
*/
public function __construct(
ResourceConnection $resource,
\Bss\DeleteOrder\Helper\Data $data,
\Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository,
\Magento\Sales\Model\Order $order
) {
$this->resource = $resource;
$this->data = $data;
$this->invoiceRepository = $invoiceRepository;
$this->order = $order;
}
/**
* @param $invoiceId
* @return \Magento\Sales\Model\Order
* @throws \Exception
*/
public function deleteInvoice($invoiceId)
{
$connection = $this->resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
$invoiceGridTable = $connection->getTableName($this->data->getTableName('sales_invoice_grid'));
$invoiceTable = $connection->getTableName($this->data->getTableName('sales_invoice'));
$invoice = $this->invoiceRepository->get($invoiceId);
$orderId = $invoice->getOrder()->getId();
$order = $this->order->load($orderId);
$orderItems = $order->getAllItems();
$invoiceItems = $invoice->getAllItems();
// revert item in order
foreach ($orderItems as $item) {
foreach ($invoiceItems as $invoiceItem) {
if ($invoiceItem->getOrderItemId() == $item->getItemId()) {
$item->setQtyInvoiced($item->getQtyInvoiced() - $invoiceItem->getQty());
$item->setTaxInvoiced($item->getTaxInvoiced() - $invoiceItem->getTaxAmount());
$item->setBaseTaxInvoiced($item->getBaseTaxInvoiced() - $invoiceItem->getBaseTaxAmount());
$item->setDiscountTaxCompensationInvoiced(
$item->getDiscountTaxCompensationInvoiced() - $invoiceItem->getDiscountTaxCompensationAmount()
);
$baseDiscountTaxItem = $item->getBaseDiscountTaxCompensationInvoiced();
$baseDiscountTaxInvoice = $invoiceItem->getBaseDiscountTaxCompensationAmount();
$item->setBaseDiscountTaxCompensationInvoiced(
$baseDiscountTaxItem - $baseDiscountTaxInvoice
);
$item->setDiscountInvoiced($item->getDiscountInvoiced() - $invoiceItem->getDiscountAmount());
$item->setBaseDiscountInvoiced(
$item->getBaseDiscountInvoiced() - $invoiceItem->getBaseDiscountAmount()
);
$item->setRowInvoiced($item->getRowInvoiced() - $invoiceItem->getRowTotal());
$item->setBaseRowInvoiced($item->getBaseRowInvoiced() - $invoiceItem->getBaseRowTotal());
}
}
}
// revert info in order
$order->setTotalInvoiced($order->getTotalInvoiced() - $invoice->getGrandTotal());
$order->setBaseTotalInvoiced($order->getBaseTotalInvoiced() - $invoice->getBaseGrandTotal());
$order->setSubtotalInvoiced($order->getSubtotalInvoiced() - $invoice->getSubtotal());
$order->setBaseSubtotalInvoiced($order->getBaseSubtotalInvoiced() - $invoice->getBaseSubtotal());
$order->setTaxInvoiced($order->getTaxInvoiced() - $invoice->getTaxAmount());
$order->setBaseTaxInvoiced($order->getBaseTaxInvoiced() - $invoice->getBaseTaxAmount());
$order->setDiscountTaxCompensationInvoiced(
$order->getDiscountTaxCompensationInvoiced() - $invoice->getDiscountTaxCompensationAmount()
);
$order->setBaseDiscountTaxCompensationInvoiced(
$order->getBaseDiscountTaxCompensationInvoiced() - $invoice->getBaseDiscountTaxCompensationAmount()
);
$order->setShippingTaxInvoiced($order->getShippingTaxInvoiced() - $invoice->getShippingTaxAmount());
$order->setBaseShippingTaxInvoiced($order->getBaseShippingTaxInvoiced() - $invoice->getBaseShippingTaxAmount());
$order->setShippingInvoiced($order->getShippingInvoiced() - $invoice->getShippingAmount());
$order->setBaseShippingInvoiced($order->getBaseShippingInvoiced() - $invoice->getBaseShippingAmount());
$order->setDiscountInvoiced($order->getDiscountInvoiced() - $invoice->getDiscountAmount());
$order->setBaseDiscountInvoiced($order->getBaseDiscountInvoiced() - $invoice->getBaseDiscountAmount());
$order->setBaseTotalInvoicedCost($order->getBaseTotalInvoicedCost() - $invoice->getBaseCost());
if ($invoice->getState() == \Magento\Sales\Model\Order\Invoice::STATE_PAID) {
$order->setTotalPaid($order->getTotalPaid() - $invoice->getGrandTotal());
$order->setBaseTotalPaid($order->getBaseTotalPaid() - $invoice->getBaseGrandTotal());
}
// delete invoice info
$connection->rawQuery('DELETE FROM `'.$invoiceGridTable.'` WHERE entity_id='.$invoiceId);
$connection->rawQuery('DELETE FROM `'.$invoiceTable.'` WHERE entity_id='.$invoiceId);
if ($order->hasShipments() || $order->hasInvoices() || $order->hasCreditmemos()) {
$order->setState(\Magento\Sales\Model\Order::STATE_PROCESSING)
->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_PROCESSING))
->save();
} else {
$order->setState(\Magento\Sales\Model\Order::STATE_NEW)
->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_NEW))
->save();
}
return $order;
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Model\Order;
use Magento\Framework\App\ResourceConnection;
class Delete
{
/**
* @var ResourceConnection
*/
protected $resource;
/**
* @var \Bss\DeleteOrder\Helper\Data
*/
protected $data;
/**
* @var \Magento\Sales\Model\Order
*/
protected $order;
/**
* Delete constructor.
* @param ResourceConnection $resource
* @param \Bss\DeleteOrder\Helper\Data $data
* @param \Magento\Sales\Model\Order $order
*/
public function __construct(
ResourceConnection $resource,
\Bss\DeleteOrder\Helper\Data $data,
\Magento\Sales\Model\Order $order
) {
$this->resource = $resource;
$this->data = $data;
$this->order = $order;
}
/**
* @param $orderId
* @throws \Exception
*/
public function deleteOrder($orderId)
{
$connection = $this->resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
$invoiceGridTable = $connection->getTableName($this->data->getTableName('sales_invoice_grid'));
$shippmentGridTable = $connection->getTableName($this->data->getTableName('sales_shipment_grid'));
$creditmemoGridTable = $connection->getTableName($this->data->getTableName('sales_creditmemo_grid'));
$order = $this->order->load($orderId);
$order->delete();
$connection->rawQuery('DELETE FROM `'.$invoiceGridTable.'` WHERE order_id='.$orderId);
$connection->rawQuery('DELETE FROM `'.$shippmentGridTable.'` WHERE order_id='.$orderId);
$connection->rawQuery('DELETE FROM `'.$creditmemoGridTable.'` WHERE order_id='.$orderId);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Model\Shipment;
use Magento\Framework\App\ResourceConnection;
class Delete
{
/**
* @var ResourceConnection
*/
protected $resource;
/**
* @var \Bss\DeleteOrder\Helper\Data
*/
protected $data;
/**
* @var \Magento\Sales\Model\Order\Shipment
*/
protected $shipment;
/**
* @var \Magento\Sales\Model\Order
*/
protected $order;
/**
* Delete constructor.
* @param ResourceConnection $resource
* @param \Bss\DeleteOrder\Helper\Data $data
* @param \Magento\Sales\Model\Order\Shipment $shipment
* @param \Magento\Sales\Model\Order $order
*/
public function __construct(
ResourceConnection $resource,
\Bss\DeleteOrder\Helper\Data $data,
\Magento\Sales\Model\Order\Shipment $shipment,
\Magento\Sales\Model\Order $order
) {
$this->resource = $resource;
$this->data = $data;
$this->shipment = $shipment;
$this->order = $order;
}
/**
* @param $shipmentId
* @return \Magento\Sales\Model\Order
* @throws \Exception
*/
public function deleteShipment($shipmentId)
{
$connection = $this->resource->getConnection(\Magento\Framework\App\ResourceConnection::DEFAULT_CONNECTION);
$shipmentTable = $connection->getTableName($this->data->getTableName('sales_shipment'));
$shipmentGridTable = $connection->getTableName($this->data->getTableName('sales_shipment_grid'));
$shipment = $this->shipment->load($shipmentId);
$orderId = $shipment->getOrder()->getId();
$order = $this->order->load($orderId);
$orderItems = $order->getAllItems();
$shipmentItems = $shipment->getAllItems();
// revert item in order
foreach ($orderItems as $item) {
foreach ($shipmentItems as $shipmentItem) {
if ($shipmentItem->getOrderItemId() == $item->getItemId()) {
$item->setQtyShipped($item->getQtyShipped() - $shipmentItem->getQty());
}
}
}
// delete shipment info
$connection->rawQuery('DELETE FROM `'.$shipmentGridTable.'` WHERE entity_id='.$shipmentId);
$connection->rawQuery('DELETE FROM `'.$shipmentTable.'` WHERE entity_id='.$shipmentId);
if ($order->hasShipments() || $order->hasInvoices() || $order->hasCreditmemos()) {
$order->setState(\Magento\Sales\Model\Order::STATE_PROCESSING)
->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_PROCESSING))
->save();
} else {
$order->setState(\Magento\Sales\Model\Order::STATE_NEW)
->setStatus($order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_NEW))
->save();
}
return $order;
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Plugin\Creditmemo;
class PluginAfter extends \Bss\DeleteOrder\Plugin\PluginAbstract
{
/**
* @var \Magento\Backend\Helper\Data
*/
protected $data;
/**
* PluginAfter constructor.
* @param \Magento\Authorization\Model\Acl\AclRetriever $aclRetriever
* @param \Magento\Backend\Model\Auth\Session $authSession
* @param \Magento\Backend\Helper\Data $data
*/
public function __construct(
\Magento\Authorization\Model\Acl\AclRetriever $aclRetriever,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Backend\Helper\Data $data
) {
parent::__construct($aclRetriever, $authSession);
$this->data = $data;
}
/**
* @param \Magento\Sales\Block\Adminhtml\Order\Creditmemo\View $subject
* @param $result
* @return mixed
*/
public function afterGetBackUrl(\Magento\Sales\Block\Adminhtml\Order\Creditmemo\View $subject, $result)
{
if ($this->isAllowedResources()) {
$params = $subject->getRequest()->getParams();
$message = __('Are you sure you want to do this?');
if ($subject->getRequest()->getFullActionName() == 'sales_order_creditmemo_view') {
$subject->addButton(
'bss-delete',
['label' => __('Delete'), 'onclick' => 'confirmSetLocation(\'' . $message . '\',\'' . $this->getDeleteUrl($params['creditmemo_id']) . '\')', 'class' => 'bss-delete'],
-1
);
}
}
return $result;
}
/**
* @param string $creditmemoId
* @return mixed
*/
public function getDeleteUrl($creditmemoId)
{
return $this->data->getUrl(
'deleteorder/delete/creditmemo',
[
'creditmemo_id' => $creditmemoId
]
);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Plugin\Invoice;
class PluginAfter extends \Bss\DeleteOrder\Plugin\PluginAbstract
{
/**
* @var \Magento\Backend\Helper\Data
*/
protected $data;
/**
* PluginAfter constructor.
* @param \Magento\Authorization\Model\Acl\AclRetriever $aclRetriever
* @param \Magento\Backend\Model\Auth\Session $authSession
* @param \Magento\Backend\Helper\Data $data
*/
public function __construct(
\Magento\Authorization\Model\Acl\AclRetriever $aclRetriever,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Backend\Helper\Data $data
) {
parent::__construct($aclRetriever, $authSession);
$this->data = $data;
}
/**
* @param \Magento\Sales\Block\Adminhtml\Order\Invoice\View $subject
* @param $result
* @return mixed
*/
public function afterGetBackUrl(\Magento\Sales\Block\Adminhtml\Order\Invoice\View $subject, $result)
{
if ($this->isAllowedResources()) {
$params = $subject->getRequest()->getParams();
$message = __('Are you sure you want to do this?');
if ($subject->getRequest()->getFullActionName() == 'sales_order_invoice_view') {
$subject->addButton(
'bss-delete',
['label' => __('Delete'), 'onclick' => 'confirmSetLocation(\'' . $message . '\',\'' . $this->getDeleteUrl($params['invoice_id']) . '\')', 'class' => 'bss-delete'],
-1
);
}
}
return $result;
}
/**
* @param string $invoiceId
* @return mixed
*/
public function getDeleteUrl($invoiceId)
{
return $this->data->getUrl(
'deleteorder/delete/invoice',
[
'invoice_id' => $invoiceId
]
);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Plugin\Order;
class PluginAfter extends \Bss\DeleteOrder\Plugin\PluginAbstract
{
/**
* @var \Magento\Backend\Helper\Data
*/
protected $data;
/**
* PluginAfter constructor.
* @param \Magento\Authorization\Model\Acl\AclRetriever $aclRetriever
* @param \Magento\Backend\Model\Auth\Session $authSession
* @param \Magento\Backend\Helper\Data $data
*/
public function __construct(
\Magento\Authorization\Model\Acl\AclRetriever $aclRetriever,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Backend\Helper\Data $data
) {
parent::__construct($aclRetriever, $authSession);
$this->data = $data;
}
/**
* @param \Magento\Sales\Block\Adminhtml\Order\View $subject
* @param $result
* @return mixed
*/
public function afterGetBackUrl(\Magento\Sales\Block\Adminhtml\Order\View $subject, $result)
{
if ($this->isAllowedResources()) {
$params = $subject->getRequest()->getParams();
$message = __('Are you sure you want to do this?');
if ($subject->getRequest()->getFullActionName() == 'sales_order_view') {
$subject->addButton(
'bss-delete',
['label' => __('Delete'), 'onclick' => 'confirmSetLocation(\'' . $message . '\',\'' . $this->getDeleteUrl($params['order_id']) . '\')', 'class' => 'bss-delete'],
-1
);
}
}
return $result;
}
/**
* @param string $orderId
* @return mixed
*/
public function getDeleteUrl($orderId)
{
return $this->data->getUrl(
'deleteorder/delete/order',
[
'order_id' => $orderId
]
);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Plugin;
class PluginAbstract
{
/**
* @var \Magento\Authorization\Model\Acl\AclRetriever
*/
protected $aclRetriever;
/**
* @var \Magento\Backend\Model\Auth\Session
*/
protected $authSession;
/**
* PluginAbstract constructor.
* @param \Magento\Authorization\Model\Acl\AclRetriever $aclRetriever
* @param \Magento\Backend\Model\Auth\Session $authSession
*/
public function __construct(
\Magento\Authorization\Model\Acl\AclRetriever $aclRetriever,
\Magento\Backend\Model\Auth\Session $authSession
) {
$this->aclRetriever = $aclRetriever;
$this->authSession = $authSession;
}
/**
* @return bool
*/
public function isAllowedResources()
{
$user = $this->authSession->getUser();
$role = $user->getRole();
$resources = $this->aclRetriever->getAllowedResourcesByRole($role->getId());
if (in_array("Magento_Backend::all", $resources) || in_array("Bss_DeleteOrder::delete_order", $resources)) {
return true;
}
return false;
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Plugin\Shipment;
class PluginAfter extends \Bss\DeleteOrder\Plugin\PluginAbstract
{
/**
* @var \Magento\Backend\Helper\Data
*/
protected $data;
/**
* PluginAfter constructor.
* @param \Magento\Authorization\Model\Acl\AclRetriever $aclRetriever
* @param \Magento\Backend\Model\Auth\Session $authSession
* @param \Magento\Backend\Helper\Data $data
*/
public function __construct(
\Magento\Authorization\Model\Acl\AclRetriever $aclRetriever,
\Magento\Backend\Model\Auth\Session $authSession,
\Magento\Backend\Helper\Data $data
) {
parent::__construct($aclRetriever, $authSession);
$this->data = $data;
}
/**
* @param \Magento\Shipping\Block\Adminhtml\View $subject
* @param $result
* @return mixed
*/
public function afterGetBackUrl(\Magento\Shipping\Block\Adminhtml\View $subject, $result)
{
if ($this->isAllowedResources()) {
$params = $subject->getRequest()->getParams();
$message = __('Are you sure you want to do this?');
if ($subject->getRequest()->getFullActionName() == 'adminhtml_order_shipment_view') {
$subject->addButton(
'bss-delete',
['label' => __('Delete'), 'onclick' => 'confirmSetLocation(\'' . $message . '\',\'' . $this->getDeleteUrl($params['shipment_id']) . '\')', 'class' => 'bss-delete'],
-1
);
}
}
return $result;
}
/**
* @param string $shipmentId
* @return mixed
*/
public function getDeleteUrl($shipmentId)
{
return $this->data->getUrl(
'deleteorder/delete/shipment',
[
'shipment_id' => $shipmentId
]
);
}
}
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
namespace Bss\DeleteOrder\Ui\Component\Control;
use Magento\Ui\Component\Control\Action;
class DeleteAction extends Action
{
/**
* setup url
*/
public function prepare()
{
$config = $this->getConfiguration();
$context = $this->getContext();
$config['url'] = $context->getUrl(
$config['deleteAction'],
['order_id' => $context->getRequestParam('order_id')]
);
$this->setData('config', (array)$config);
parent::prepare();
}
}
{
"name": "bsscommerce/delete-order",
"description": "Bss Delete Order Modules",
"type": "magento2-module",
"version": "1.0.6",
"license": [
"OSL-3.0",
"AFL-3.0"
],
"autoload": {
"files": [
"registration.php"
],
"psr-4": {
"Bss\\DeleteOrder\\": ""
}
}
}
<?xml version="1.0"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
<acl>
<resources>
<resource id="Magento_Backend::admin">
<resource id="Bss_DeleteOrder::bss_delete_order" title="Bss Commerce" sortOrder="100">
<resource id="Bss_DeleteOrder::delete_order" title="Delete Order" sortOrder="80"/>
</resource>
</resource>
</resources>
</acl>
</config>
<?xml version="1.0"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="\Magento\Sales\Block\Adminhtml\Order\Invoice\View">
<plugin name="Bss_DeleteOrder::pluginAfterInvoice" type="Bss\DeleteOrder\Plugin\Invoice\PluginAfter" />
</type>
<type name="\Magento\Sales\Block\Adminhtml\Order\Creditmemo\View">
<plugin name="Bss_DeleteOrder::pluginAfterCreditmemo" type="Bss\DeleteOrder\Plugin\Creditmemo\PluginAfter" />
</type>
<type name="\Magento\Shipping\Block\Adminhtml\View">
<plugin name="Bss_DeleteOrder::pluginAfterShipment" type="Bss\DeleteOrder\Plugin\Shipment\PluginAfter" />
</type>
<type name="\Magento\Sales\Block\Adminhtml\Order\View">
<plugin name="Bss_DeleteOrder::pluginAfterOrder" type="Bss\DeleteOrder\Plugin\Order\PluginAfter" />
</type>
</config>
<?xml version="1.0"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="admin">
<route id="deleteorder" frontName="deleteorder">
<module name="Bss_DeleteOrder" />
</route>
</router>
</config>
<?xml version="1.0"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Bss_DeleteOrder" setup_version="1.0.6"/>
</config>
<?php
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Bss_DeleteOrder',
__DIR__
);
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="delete_creditmemos">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">bss_deleteCreditmemo</item>
<item name="label" xsi:type="string" translate="true">Delete Credit Memos</item>
<item name="url" xsi:type="url" path="deleteorder/delete/massCreditmemo"/>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Credit Memos</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected credit memo(s) ?</item>
</item>
</item>
</argument>
</action>
</massaction>
</listingToolbar>
</listing>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="export">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">bss_deleteOrder</item>
<item name="label" xsi:type="string" translate="true">Delete Orders</item>
<item name="url" xsi:type="url" path="deleteorder/delete/massOrder"/>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Orders</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected order(s) ?</item>
</item>
</item>
</argument>
</action>
</massaction>
</listingToolbar>
</listing>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="delete_invoices">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">bss_deleteInvoice</item>
<item name="label" xsi:type="string" translate="true">Delete Invoices</item>
<item name="url" xsi:type="url" path="deleteorder/delete/massInvoice"/>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Invoices</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected invoice(s) ?</item>
</item>
</item>
</argument>
</action>
</massaction>
</listingToolbar>
</listing>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="delete_shipments">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">bss_deleteShipment</item>
<item name="label" xsi:type="string" translate="true">Delete Shipments</item>
<item name="url" xsi:type="url" path="deleteorder/delete/massShipment"/>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Shipments</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected shipment(s) ?</item>
</item>
</item>
</argument>
</action>
</massaction>
</listingToolbar>
</listing>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="delete_creditmemos" class="Bss\DeleteOrder\Ui\Component\Control\DeleteAction">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">bss_deleteCreditmemo</item>
<item name="label" xsi:type="string" translate="true">Delete Credit Memos</item>
<item name="deleteAction" xsi:type="string">deleteorder/delete/massCreditmemo</item>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Credit Memos</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected credit memo(s) ?</item>
</item>
</item>
</argument>
</action>
</massaction>
</listingToolbar>
</listing>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="delete_invoices" class="Bss\DeleteOrder\Ui\Component\Control\DeleteAction">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">bss_deleteInvoice</item>
<item name="label" xsi:type="string" translate="true">Delete Invoices</item>
<item name="deleteAction" xsi:type="string">deleteorder/delete/massInvoice</item>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Invoices</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected invoice(s) ?</item>
</item>
</item>
</argument>
</action>
</massaction>
</listingToolbar>
</listing>
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* BSS Commerce Co.
*
* NOTICE OF LICENSE
*
* This source file is subject to the EULA
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://bsscommerce.com/Bss-Commerce-License.txt
*
* @category BSS
* @package Bss_DeleteOrder
* @author Extension Team
* @copyright Copyright (c) 2019-2019 BSS Commerce Co. ( http://bsscommerce.com )
* @license http://bsscommerce.com/Bss-Commerce-License.txt
*/
-->
<listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
<listingToolbar name="listing_top">
<massaction name="listing_massaction">
<action name="delete_shipments" class="Bss\DeleteOrder\Ui\Component\Control\DeleteAction">
<argument name="data" xsi:type="array">
<item name="config" xsi:type="array">
<item name="type" xsi:type="string">bss_deleteShipment</item>
<item name="label" xsi:type="string" translate="true">Delete Shipments</item>
<item name="deleteAction" xsi:type="string">deleteorder/delete/massShipment</item>
<item name="confirm" xsi:type="array">
<item name="title" xsi:type="string" translate="true">Delete Shipments</item>
<item name="message" xsi:type="string" translate="true">Are you sure you want to delete selected shipment(s) ?</item>
</item>
</item>
</argument>
</action>
</massaction>
</listingToolbar>
</listing>
<?php
namespace Customily\Categories\Api\Client;
use Customily\Categories\Helper\CustomilyHelper;
use GuzzleHttp\Client;
use GuzzleHttp\ClientFactory;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Psr7\ResponseFactory;
use Magento\Framework\Webapi\Rest\Request;
use Psr\Log\LoggerInterface;
/**
* Class ApiClient
*/
class ApiClient
{
private $API_CUSTOMILY_ENDPOINT;
private $THUMB_CUSTOMILY_ENDPOINT;
/**
* @var ResponseFactory
*/
private $responseFactory;
/**
* @var ClientFactory
*/
private $clientFactory;
/**
* @var \Customily\Categories\Helper\CustomilyHelper
*/
private $helper;
/**
* @var array
*/
private $settings;
/**
* @var LoggerInterface
*/
private $logger;
/**
* ApiClient constructor.
* @param CustomilyHelper $helper
* @param ClientFactory $clientFactory
* @param ResponseFactory $responseFactory
* @param LoggerInterface $logger
*/
public function __construct(
CustomilyHelper $helper,
ClientFactory $clientFactory,
ResponseFactory $responseFactory,
LoggerInterface $logger
) {
$this->helper = $helper;
$this->settings = $this->helper->getCustomilyConfig();
$this->clientFactory = $clientFactory;
$this->responseFactory = $responseFactory;
$this->logger = $logger;
$this->API_CUSTOMILY_ENDPOINT = isset($this->settings['api_endpoint']) && !empty($this->settings['api_endpoint'])
? $this->settings['api_endpoint']
: 'https://app.customily.com/api';
$this->THUMB_CUSTOMILY_ENDPOINT = isset($this->settings['thumbnails_endpoint']) &&
!empty($this->settings['thumbnails_endpoint'])
? $this->settings['thumbnails_endpoint']
: 'https://api.customily.com/magento';
}
/**
* @param $personalizationId
* @param $orderNumber
* @param $fileName
* @return \GuzzleHttp\Psr7\PumpStream|\GuzzleHttp\Psr7\Stream|\Psr\Http\Message\StreamInterface|null
*/
public function generateProductionFile($personalizationId, $orderNumber, $fileName) {
if (
isset($personalizationId) && !empty($personalizationId) &&
isset($orderNumber) && !empty($orderNumber) &&
isset($fileName) && !empty($fileName)
) {
$options = [];
$queryString = "?personalizationId={$personalizationId}&orderNumber={$orderNumber}&store=Magento&prodFileName={$fileName}";
$apiKey = $this->settings['user_api_key'];
if (!empty($apiKey)) {
$options['headers'] = [
'x-api-key' => $apiKey
];
$uri = "UserApiKey/EPSEngrave/GenerateProductionFile{$queryString}";
return $this->doPostRequest("{$this->API_CUSTOMILY_ENDPOINT}/", $uri, $options);
} else if (
isset($this->settings['x_api_key']) &&
!empty($this->settings['x_api_key']) &&
isset($this->settings['api_secret_key']) &&
!empty($this->settings['api_secret_key'])
) {
$apiKey = base64_decode($this->settings['x_api_key']);
$secretKey = base64_decode($this->settings['api_secret_key']);
$hmac = bin2hex(hash_hmac('sha256', $queryString, $secretKey, true));
$options['headers'] = [
'x-api-key' => $apiKey,
'hmac' => $hmac
];
$uri = "EPSEngrave/GenerateProductionFile{$queryString}";
return $this->doPostRequest("{$this->API_CUSTOMILY_ENDPOINT}/", $uri, $options);
}
}
return null;
}
/**
* @param $url
* @param $fileName
* @return Response|\Psr\Http\Message\ResponseInterface
*/
public function downloadFile($url, $fileName)
{
try {
/** @var Client $client */
$client = $this->clientFactory->create();
$response = $client->request('GET', $url, ['sink' => $fileName]);
} catch (GuzzleException $ex) {
/** @var Response $response */
$response = $this->responseFactory->create([
'status' => $ex->getCode(),
'reason' => $ex->getMessage()
]);
$this->logger->debug($ex->getTraceAsString());
}
return $response;
}
/**
* @param $productId
* @return mixed|null
*/
public function getProduct($productId)
{
if (isset($productId)) {
$options = [];
$apiKey = isset($this->settings['user_api_key']) ? trim($this->settings['user_api_key']) : '';
if (!empty($apiKey)) {
$options['headers'] = [
'x-api-key' => $apiKey
];
$uri = "UserApiKey/Product?productId={$productId}";
} else {
$uri = "Product/GetProduct?productId={$productId}";
}
return $this->doGetRequest($uri, $options);
}
return null;
}
/**
* @param $libraryId
* @return mixed
*/
public function getProductLibraryName($libraryId)
{
if (isset($libraryId)) {
$options = [];
$apiKey = $this->settings['user_api_key'];
if (!empty($apiKey)) {
$options['headers'] = [
'x-api-key' => $apiKey
];
$uri = "UserApiKey/Libraries/{$libraryId}/Name";
} else {
$uri = "Libraries/{$libraryId}/Name";
}
return $this->doGetRequest($uri, $options);
}
return null;
}
/**
* @param $libraryId
* @return mixed
*/
public function getProductLibraryCategories($libraryId)
{
if (isset($libraryId)) {
$options = [];
$apiKey = $this->settings['user_api_key'];
if (!empty($apiKey)) {
$options['headers'] = [
'x-api-key' => $apiKey
];
$uri = "UserApiKey/Libraries/{$libraryId}/Categories?searchString=&from=0&count=0";
} else {
$uri = "Libraries/{$libraryId}/Categories?searchString=&from=0&count=0";
}
return $this->doGetRequest($uri, $options);
}
return null;
}
/**
* @param $libraryId
* @param $categoryId
* @return mixed
*/
public function getProductElementsByCategoryLibrary($libraryId, $categoryId)
{
if (isset($libraryId)) {
$options = [];
$apiKey = $this->settings['user_api_key'];
if (!empty($apiKey)) {
$options['headers'] = [
'x-api-key' => $apiKey
];
$uri = "UserApiKey/Libraries/{$libraryId}/Categories/{$categoryId}/Elements?searchString=&from=0&count=0";
} else {
$uri = "Libraries/{$libraryId}/Categories/{$categoryId}/Elements?searchString=&from=0&count=0";
}
return $this->doGetRequest($uri, $options);
}
return null;
}
/**
* @param $libraryId
* @return mixed|null
*/
public function getProductLibraryElementPositions($libraryId)
{
if (isset($libraryId)) {
$options = [];
$apiKey = $this->settings['user_api_key'];
if (!empty($apiKey)) {
$options['headers'] = [
'x-api-key' => $apiKey
];
$uri = "UserApiKey/Libraries/{$libraryId}/Elements/Positions";
} else {
$uri = "Libraries/{$libraryId}/Elements/Positions";
}
return $this->doGetRequest($uri, $options);
}
return null;
}
/**
* @param $libraryId
* @param $position
* @return mixed|null
*/
public function getProductLibraryElementAtPosition($libraryId, $position)
{
if (isset($libraryId) && isset($position)) {
$options = [];
$apiKey = $this->settings['user_api_key'];
if (!empty($apiKey)) {
$options['headers'] = [
'x-api-key' => $apiKey
];
$uri = "UserApiKey/Libraries/{$libraryId}/Elements/Position/{$position}";
} else {
$uri = "Libraries/{$libraryId}/Elements/Position/{$position}";
}
return $this->doGetRequest($uri, $options);
}
return null;
}
/**
* @param $file
* @param string $fileType
* @return string|null
*/
public function uploadImageToMagento($file, $fileType = 'image')
{
if (isset($this->settings['m_api_key']) && !empty($this->settings['m_api_key'])) {
$magentoApiKey = $this->settings['m_api_key'];
$uri = 'uploadThumbnail';
$options = [];
$options['headers'] = [
'm-api-key' => $magentoApiKey,
'Content-Type' => 'application/json'
];
$options['body'] = json_encode([
'fileContent' => $fileType == 'svg' ? file_get_contents($file) : base64_encode(file_get_contents($file)),
'fileType' => $fileType
]);
$result = $this->doPostRequest("{$this->helper->getCustomilyApiEndpoint()}/", $uri, $options);
if (isset($result)) {
$result = json_decode($result, true);
if (isset($result['imageUrl'])) {
return $this->helper->getMagentoBaseUrls()['baseMediaUrl'] . $result['imageUrl'];
}
}
}
return null;
}
/**
* @param $file
* @return mixed|string|null
*/
public function uploadImageToCustomily($file)
{
$uri = 'savethumbnail/';
$options = [];
$option['headers'] = [
'Content-Type' => 'application/x-www-form-urlencoded'
];
$base64 = base64_encode(file_get_contents($file));
$option['body'] = 'image=' . rawurlencode("image/png;base64,{$base64}");
$result = $this->doPostRequest("{$this->THUMB_CUSTOMILY_ENDPOINT}/", $uri, $options);
if (isset($result)) {
return $result;
}
return null;
}
/**
* @param $uri
* @param array $options
* @return mixed|null
*/
private function doGetRequest($uri, $options = []) {
/* @var Response */
$response = $this->doRequest("{$this->API_CUSTOMILY_ENDPOINT}/", $uri, $options);
$statusCode = $response->getStatusCode();
if (isset($statusCode) && $statusCode == 200) {
try {
return json_decode($response->getBody()->getContents(), true);
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
} else {
$this->logger->debug("Error status code {$statusCode}");
}
return null;
}
/**
* Do API POST request with provided params
* @param $baseUri
* @param $uri
* @param array $options
* @return mixed|null
*/
private function doPostRequest($baseUri, $uri, $options = []) {
/* @var Response */
$response = $this->doRequest($baseUri, $uri, $options, Request::HTTP_METHOD_POST);
$statusCode = $response->getStatusCode();
if (isset($statusCode) && $statusCode == 200) {
try {
return json_decode($response->getBody()->getContents(), true);
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
} else {
$this->logger->debug("Error status code {$statusCode}");
}
return null;
}
/**
* Do API GET request with provided params
* @param $baseUri
* @param $uriEndpoint
* @param array $options
* @param string $requestMethod
* @return Response|\Psr\Http\Message\ResponseInterface
*/
private function doRequest($baseUri, $uriEndpoint, $options = [], $requestMethod = Request::HTTP_METHOD_GET) {
/** @var Client $client */
$client = $this->clientFactory->create(['config' => [
'base_uri' => $baseUri
]]);
$options['verify'] = false;
try {
$response = $client->request(
$requestMethod,
$uriEndpoint,
$options
);
} catch (GuzzleException $ex) {
/** @var Response $response */
$response = $this->responseFactory->create([
'status' => $ex->getCode(),
'reason' => $ex->getMessage()
]);
}
return $response;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 03/09/2020
*/
namespace Customily\Categories\Api\Server;
use Customily\Categories\Helper\CustomilyHelper;
use Customily\Categories\Util\ManageOptions;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\Webapi\Rest\Request;
use Magento\MediaStorage\Model\File\UploaderFactory;
use Psr\Log\LoggerInterface;
class ApiRestImpl implements ApiRestInterface
{
protected $helper;
protected $manageOptions;
protected $mediaDirectory;
protected $fileUploaderFactory;
protected $request;
protected $logger;
const SWATCH_THUMBNAILS_URL_PATH = 'catalog/product/customily/swatches/thumbnails/';
const PREVIEW_URL_PATH = 'catalog/product/customily/previews/';
const THUMBNAILS_URL_PATH = 'catalog/product/customily/previews/thumbnails/';
/**
* ApiRestImpl constructor.
* @param CustomilyHelper $helper
* @param ManageOptions $manageOptions
* @param Filesystem $filesystem
* @param UploaderFactory $fileUploaderFactory
* @param Request $request
* @param LoggerInterface $logger
* @throws \Magento\Framework\Exception\FileSystemException
*/
public function __construct(
CustomilyHelper $helper,
ManageOptions $manageOptions,
Filesystem $filesystem,
UploaderFactory $fileUploaderFactory,
Request $request,
LoggerInterface $logger
)
{
$this->helper = $helper;
$this->manageOptions = $manageOptions;
$this->mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->fileUploaderFactory = $fileUploaderFactory;
$this->request = $request;
$this->logger = $logger;
}
/**
* @return false|mixed|string
*/
public function testApi()
{
if (!$this->checkPermissions()) {
return false;
}
$this->logger->debug('CUSTOMILY: Test api.');
$count = $this->helper->getCustomilyProductCount();
$response = ['success' => true, 'products' => $count];
return json_encode($response);
}
/**
* @return false|mixed|string
*/
public function status()
{
$memoryLimit = ini_get('memory_limit');
if (preg_match('/^(\d+)(.)$/', $memoryLimit, $matches)) {
if ($matches[2] == 'M') {
$memoryLimit = $matches[1]; // nnnM -> nnn MB
} else if ($matches[2] == 'K') {
$memoryLimit = $matches[1] / 1024; // nnnK -> nnn KB
}
}
$response = [
'status' => 'active',
'version' => $this->helper->getModuleVersion(),
'memory_limit' => "{$memoryLimit}MB",
'max_input_vars' => ini_get('max_input_vars'),
'max_execution_time' => ini_get('max_execution_time')
];
return json_encode($response);
}
/**
* @return false|mixed|string
*/
public function uploadThumbnail()
{
if (!$this->checkPermissions()) {
return false;
}
$data = $this->request->getBodyParams();
if (isset($data) && isset($data['fileContent'])) {
$fileType = $data['fileType'] ?? 'image';
$targetDir = $this->mediaDirectory->getAbsolutePath(self::SWATCH_THUMBNAILS_URL_PATH);
$response = $this->saveImage(
$data['fileContent'],
$targetDir,
self::SWATCH_THUMBNAILS_URL_PATH,
$fileType
);
} else {
$response = ['success' => false, 'imageUrl' => false];
}
return json_encode($response);
}
/**
* @return false|mixed|string
*/
public function deleteThumbnail()
{
if (!$this->checkPermissions()) {
return false;
}
$data = $this->request->getBodyParams();
if (isset($data) && isset($data['thumbnailName'])) {
$file = $this->mediaDirectory->getAbsolutePath(self::SWATCH_THUMBNAILS_URL_PATH . $data['thumbnailName']);
$response = ['success' => unlink($file)];
} else {
$response = ['success' => false];
}
return json_encode($response);
}
/**
* @return false|mixed|string
*/
public function uploadPreview()
{
if (!$this->checkPermissions()) {
return false;
}
$data = $this->request->getBodyParams();
if (isset($data) && isset($data['productId']) && isset($data['fileContent'])) {
if (isset($data['isThumbnail'])) {
$urlPath = self::THUMBNAILS_URL_PATH;
} else {
$urlPath = self::PREVIEW_URL_PATH;
}
$targetDir = $this->mediaDirectory->getAbsolutePath($urlPath . $data['productId'] . '/');
$response = $this->saveImage($data['fileContent'], $targetDir, $urlPath . $data['productId'] . '/');
} else {
$response = ['success' => false, 'imageUrl' => false];
}
return json_encode($response);
}
/**
* @return false|mixed|string
*/
public function optionsFromTemplate()
{
if (!$this->checkPermissions()) {
return false;
}
$data = $this->request->getBodyParams();
if (isset($data) && isset($data['productId']) && isset($data['templateId']) && isset($data['lastSortOrder'])) {
$this->logger->debug(
"Importing options <=> ProductId: {$data['productId']}, TemplateId: {$data['templateId']}," .
" LastSortOrder : {$data['lastSortOrder']}"
);
$result = $this->manageOptions->optionsFromTemplate(
$data['productId'],
$data['templateId'],
$data['lastSortOrder']
);
$response = ['success' => $result];
} else {
$response = ['success' => false];
}
return json_encode($response);
}
/**
* @return bool|mixed
*/
public function createLog()
{
if (!$this->checkPermissions()) {
return false;
}
$data = $this->request->getBodyParams();
if (isset($data) && isset($data['productId']) && isset($data['title']) && isset($data['message'])) {
/* @var \Magento\Catalog\Model\Product $product */
$product = $this->helper->getProduct($data['productId']);
$templateId = $data['templateId'] ?? '';
if (isset($product) && !empty($product)) {
$this->logger->debug(
"CUSTOMILY: {$data['title']} (sku: {$product->getSku()}, productName: {$product->getName()}," .
" templateId: {$templateId})"
);
$this->logger->debug($data['message']);
}
}
return true;
}
/**
* @param $data
* @param $targetDir
* @param $urlPath
* @param string $fileType
* @return array|false
*/
private function saveImage($data, $targetDir, $urlPath, $fileType = 'image')
{
if (!$this->checkPermissions()) {
return false;
}
try {
if ($fileType == 'svg') {
$ext = 'svg';
} else {
$data = 'image/png;base64,' . $data;
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
list(, $ext) = explode('/', $type);
}
if (!file_exists($targetDir)) {
mkdir($targetDir, 0777, true);
}
$imageId = uniqid('', true);
$imageId = str_replace('.', '', $imageId);
$imagePath = $targetDir . $imageId . '.' . $ext;
$imageUrl = $urlPath . $imageId . '.' . $ext;
file_put_contents($imagePath, $data);
return [
'success' => true,
'imageUrl' => $imageUrl
];
} catch (\Exception $e) {
$this->logger->debug('CUSTOMILY: Error uploading swatch thumbnail.');
$this->logger->debug($e->getTraceAsString());
return [
'success' => false,
'imageUrl' => ''
];
}
}
/**
* @return bool
*/
private function checkPermissions()
{
try {
$settings = $this->helper->getCustomilyConfig();
$localApiKey = $settings['m_api_key'];
$apiKey = $this->request->getHeader('m-api-key');
if (
isset($localApiKey) && !empty($localApiKey) &&
isset($apiKey) && !empty($localApiKey) &&
base64_decode($localApiKey) == base64_decode($apiKey)
) {
return true;
}
} catch (\Exception $ex) {
$this->logger->debug('CUSTOMILY: Invalid api key.');
$this->logger->debug($ex->getTraceAsString());
}
return false;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 03/09/2020
*/
namespace Customily\Categories\Api\Server;
interface ApiRestInterface
{
/**
* @return mixed
*/
public function testApi();
/**
* @return mixed
*/
public function status();
/**
* @return mixed
*/
public function uploadThumbnail();
/**
* @return mixed
*/
public function deleteThumbnail();
/**
* @return mixed
*/
public function uploadPreview();
/**
* @return mixed
*/
public function optionsFromTemplate();
/**
* @return mixed
*/
public function createLog();
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
namespace Customily\Categories\Block\Product\View\Options\Type\Select;
use Magento\Catalog\Api\Data\ProductCustomOptionValuesInterface;
use Magento\Catalog\Block\Product\View\Options\AbstractOptions;
use Magento\Catalog\Model\Product\Option;
class Checkable extends AbstractOptions
{
/**
* @var string
*/
protected $_template = 'Customily_Categories::product/composite/fieldset/options/view/checkable.phtml';
/**
* @param ProductCustomOptionValuesInterface $value
* Returns formatted price
*/
public function formatPrice(ProductCustomOptionValuesInterface $value)
{
// @noinspection PhpMethodParametersCountMismatchInspection
return parent::_formatPrice(
[
'is_percent' => $value->getPriceType() === 'percent',
'pricing_value' => $value->getPrice($value->getPriceType() === 'percent')
]
);
}
/**
* @param ProductCustomOptionValuesInterface $value
* Returns current currency for store
*
* @return float|string
*/
public function getCurrencyByStore(ProductCustomOptionValuesInterface $value)
{
// @noinspection PhpMethodParametersCountMismatchInspection
return $this->pricingHelper->currencyByStore(
$value->getPrice(true),
$this->getProduct()->getStore(),
false
);
}
/**
* @param Option $option
* Returns preconfigured value for given option
*
* @return null|array|string
*/
public function getPreconfiguredValue(Option $option)
{
return $this->getProduct()->getPreconfiguredValues()->getData('options/' . $option->getId());
}
}
<?php
/**
* Copyright © Customily. All rights reserved.
*/
namespace Customily\Categories\Block\Product\View\Options\Type\Select;
use Magento\Catalog\Block\Product\View\Options\AbstractOptions;
use Magento\Catalog\Model\Product\Option;
use Magento\Framework\View\Element\Html\Select;
class Multiple extends AbstractOptions
{
/**
* @var bool
*/
private $existConfigValue = false;
/**
* {@inheritdoc}
*
* @throws \Magento\Framework\Exception\LocalizedException
*
* @return string
*/
protected function _toHtml()
{
$option = $this->getOption();
$optionType = $option->getType();
$configValue = $this->getProduct()->getPreconfiguredValues()->getData('options/' . $option->getId());
$require = $option->getIsRequire() ? ' required' : '';
$extraParams = '';
if ($configValue) {
$this->existConfigValue = true;
}
/** @var Select $select */
$select = $this->getLayout()->createBlock(Select::class)->setData(
[
'id' => 'select_' . $option->getId(),
'class' => $require . ' product-custom-option admin__control-select'
]
);
$select = $this->insertSelectOption($select, $option);
$select = $this->processSelectOption($select, $option);
if ($optionType === Option::OPTION_TYPE_MULTIPLE) {
$extraParams = ' multiple="multiple"';
}
if (!$this->getSkipJsReloadPrice()) {
$extraParams .= ' onchange="opConfig.reloadPrice()"';
}
$extraParams .= ' data-selector="' . $select->getName() . '"';
$select->setExtraParams($extraParams);
if ($this->existConfigValue) {
$select->setValue($configValue);
}
return $select->getHtml();
}
/**
* Returns select with inserted option give as a parameter
*/
private function insertSelectOption(Select $select, Option $option): Select
{
$require = $option->getIsRequire() ? ' required' : '';
if ($option->getType() === Option::OPTION_TYPE_DROP_DOWN) {
$select->setName('options[' . $option->getId() . ']')->addOption('', __('-- Please Select --'));
} else {
$select->setName('options[' . $option->getId() . '][]');
$select->setClass('multiselect admin__control-multiselect' . $require . ' product-custom-option');
}
return $select;
}
/**
* Returns select with formatted option prices
*/
private function processSelectOption(Select $select, Option $option): Select
{
$store = $this->getProduct()->getStore();
foreach ($option->getValues() as $_value) {
$isPercentPriceType = $_value->getPriceType() === 'percent';
$priceStr = $this->_formatPrice(
[
'is_percent' => $isPercentPriceType,
'pricing_value' => $_value->getPrice($isPercentPriceType)
],
false
);
$selectOption = [];
if (!$this->existConfigValue && $_value->getData('customily_is_default')) {
$selectOption = ['selected' => 'selected'];
}
$select->addOption(
$_value->getOptionTypeId(),
$_value->getTitle() . ' ' . strip_tags($priceStr) . '',
[
'price' => $this->pricingHelper->currencyByStore(
$_value->getPrice(true),
$store,
false
),
$selectOption
]
);
}
return $select;
}
}
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 13/11/2019
*/
namespace Customily\Categories\Helper;
use Magento\Checkout\Model\Cart;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Setup\Exception;
use Magento\Store\Model\ScopeInterface;
use Magento\Framework\Pricing\Helper\Data as PriceHelper;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\ResourceModel\Product\ActionFactory;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\ConfigurableFactory;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\Module\ModuleListInterface;
use Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory as OptionCollectionFactory;
use Magento\Quote\Model\ResourceModel\Quote\Item\CollectionFactory as QuoteItemCollectionFactory;
use Magento\Framework\Serialize\Serializer\Json;
use Psr\Log\LoggerInterface;
class CustomilyHelper extends AbstractHelper
{
const XML_PATH_CUSTOMILY = 'customily/';
const API_PATH_CUSTOMILY = 'rest/V1/customily';
private $priceHelper;
private $productRepository;
private $cart;
private $actionFactory;
private $collectionFactory;
private $configurableFactory;
private $productMetadataInterface;
private $storeManagerInterface;
private $moduleListInterface;
private $optionCollectionFactory;
private $quoteItemCollectionFactory;
private $serializer;
private $logger;
public function __construct(
Context $context,
PriceHelper $priceHelper,
ProductRepositoryInterface $productRepository,
Cart $cart,
ActionFactory $actionFactory,
CollectionFactory $collectionFactory,
ConfigurableFactory $configurableFactory,
ProductMetadataInterface $productMetadataInterface,
StoreManagerInterface $storeManagerInterface,
ModuleListInterface $moduleListInterface,
OptionCollectionFactory $optionCollectionFactory,
QuoteItemCollectionFactory $quoteItemCollectionFactory,
Json $serializer,
LoggerInterface $logger
) {
parent::__construct($context);
$this->priceHelper = $priceHelper;
$this->productRepository = $productRepository;
$this->actionFactory = $actionFactory;
$this->cart = $cart;
$this->collectionFactory = $collectionFactory;
$this->configurableFactory = $configurableFactory;
$this->productMetadataInterface = $productMetadataInterface;
$this->storeManagerInterface = $storeManagerInterface;
$this->moduleListInterface = $moduleListInterface;
$this->optionCollectionFactory = $optionCollectionFactory;
$this->quoteItemCollectionFactory = $quoteItemCollectionFactory;
$this->serializer = $serializer;
$this->logger = $logger;
}
/**
* @return LoggerInterface
*/
public function getLogger() {
return $this->logger;
}
/**
* @param $code
* @param string $path
* @param null $storeId
* @return mixed
*/
public function getConfig($code, $path = 'general', $storeId = null)
{
return $this->scopeConfig->getValue(
self::XML_PATH_CUSTOMILY . $path . '/' . $code,
ScopeInterface::SCOPE_STORE, $storeId
);
}
/**
* @param $quoteItemId
* @return array
*/
public function getQuoteBuyRequest($quoteItemId)
{
$optionValue = [];
$quoteItems = $this->cart->getQuote()->getAllItems();
/** @var \Magento\Quote\Model\Quote\Item $item */
foreach ($quoteItems as $item) {
if ($item->getId() == $quoteItemId) {
foreach ($item->getOptions() as $option) {
if ($option['code'] == 'info_buyRequest') {
$optionValue = json_decode($option['value'], true);
break 2;
}
}
}
}
return $optionValue;
}
/**
* @param $infoBuyRequest
* @param $option
* @return string|null
*/
public function getSelectedValue($infoBuyRequest, $option)
{
$result = null;
if (
isset($infoBuyRequest) &&
isset($infoBuyRequest['options']) &&
isset($infoBuyRequest['options'][$option->getOptionId()])
) {
if (
$option->getType() == 'file' &&
isset($infoBuyRequest['options'][$option->getOptionId()]['fullpath'])
) {
if ($infoBuyRequest['options'][$option->getOptionId()]['type'] == 'image/png') {
$prefix = 'data:image/png;base64,';
} else {
$prefix = 'data:image/jpeg;base64,';
}
$result = file_get_contents($infoBuyRequest['options'][$option->getOptionId()]['fullpath']);
$result = $prefix . base64_encode($result);
} else if ($option->getType() == 'checkbox') {
return $infoBuyRequest['options'][$option->getOptionId()][0];
} else {
$result = $infoBuyRequest['options'][$option->getOptionId()];
}
}
return $result;
}
/**
* @param $option
* @return string
*/
public function getDefaultValue($option)
{
$values = $option->getValues();
$result = '""';
if (isset($values) && !empty($values)) {
foreach ($values as $value) {
if (isset($value['customily_is_default']) && $value['customily_is_default'] == '1') {
$result = "{
\"label\": \"{$value->getTitle()}\",
\"value\": \"{$value['option_type_id']}\",
\"price\": \"{$this->priceHelper->currency($value['price'], true, false)}\"
}";
break;
}
}
}
return $result;
}
/**
* @param $infoBuyRequest
* @param $attributeId
* @return null
*/
public function getSelectedAttribute($infoBuyRequest, $attributeId)
{
$result = null;
if (
isset($infoBuyRequest) && isset($infoBuyRequest['super_attribute']) &&
isset($infoBuyRequest['super_attribute'][$attributeId])
) {
$result = $infoBuyRequest['super_attribute'][$attributeId];
}
return $result;
}
/**
* @return array
*/
public function getCustomilyConfig()
{
return [
'enable' => $this->getConfig('enable'),
'save_files_in' => $this->getConfig('save_files_in'),
'enable_swatches' => $this->getConfig('enable_swatches'),
'swatches_max_size' => $this->getConfig('swatches_max_size'),
'enable_logs' => $this->getConfig('enable_logs'),
'apply_options_styles' => $this->getConfig('apply_options_styles'),
'additional_frontend_styles' => $this->getConfig('additional_frontend_styles'),
'additional_frontend_scripts' => $this->getConfig('additional_frontend_scripts'),
'personalization_type' => $this->getConfig('type', 'personalization'),
'personalization_allow_optional' => $this->getConfig('allow_optional', 'personalization'),
'personalization_optional_attach_to' => $this->getConfig('optional_attach_to', 'personalization'),
'personalization_optional_behavior' => $this->getConfig('optional_behavior', 'personalization'),
'personalization_optional_label' => $this->getConfig('optional_label', 'personalization'),
'personalization_handle_prices' => $this->getConfig('handle_prices', 'personalization'),
'show_uploaded_image_url' => $this->getConfig('show_uploaded_image_url', 'mail'),
'export_preview' => $this->getConfig('export_preview', 'preview'),
'hover_zoom' => $this->getConfig('hover_zoom', 'preview'),
'resize_preview' => $this->getConfig('hover_zoom', 'preview'),
'save_placeholders_settings' => $this->getConfig('save_placeholders_settings', 'preview'),
'sticky_left' => $this->getConfig('sticky_left', 'preview'),
'sticky_right' => $this->getConfig('sticky_right', 'preview'),
'sticky_padding' => $this->getConfig('sticky_padding', 'preview'),
'export_file' => $this->getConfig('export_file', 'production_file'),
'rename_file' => $this->getConfig('rename_file', 'production_file'),
'rename_file_pattern' => $this->getConfig('rename_file_pattern', 'production_file'),
'represent_product' => $this->getConfig('represent_product', 'extension_plugins'),
'custom_cart_thumbnail' => $this->getConfig('custom_cart_thumbnail', 'extension_plugins'),
'custom_minicart_thumbnail' => $this->getConfig('custom_minicart_thumbnail', 'extension_plugins'),
'selectable_default_value' => $this->getConfig('selectable_default_value', 'extension_plugins'),
'user_api_key' => $this->getConfig('user_api_key', 'api'),
'api_endpoint' => $this->getConfig('api_endpoint', 'api'),
'cdn_endpoint' => $this->getConfig('cdn_endpoint', 'api'),
'thumbnails_endpoint' => $this->getConfig('thumbnails_endpoint', 'api'),
'x_api_key' => $this->getConfig('x_api_key', 'api'),
'm_api_key' => $this->getConfig('m_api_key', 'api'),
'api_secret_key' => $this->getConfig('api_secret_key', 'api')
];
}
/**
* @param $guid
* @return false|int
*/
public function validateGuid($guid) {
return preg_match('/^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$/', $guid);
}
/**
* @param $productId
* @return \Magento\Catalog\Api\Data\ProductInterface $product
*/
public function getProduct($productId) {
return $this->productRepository->getById($productId);
}
/**
* @param $sku
* @return \Magento\Catalog\Api\Data\ProductInterface $product
*/
public function getProductBySku($sku) {
return $this->productRepository->get($sku);
}
/**
* @param $productId
* @return false|mixed
*/
public function getParentProductId($productId) {
$ids = $this->configurableFactory->create()->getParentIdsByChild($productId);
return $ids[0] ?? false;
}
/**
* @param $productId
* @return array
*/
public function getChildProductsInfo($productId) {
$result = [];
$product = $this->getProduct($productId);
if ($product->getTypeId() == \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) {
$children = $product->getTypeInstance()->getUsedProducts($product);
/* @var \Magento\Catalog\Model\Product $child */
foreach ($children as $child) {
$isOptional = $child->getPersonalizationIsOptional();
$result[] = [
'id' => $child->getId(),
'personalizationIsOptional' => !empty($isOptional) ? $isOptional : '0'
];
}
}
return $result;
}
/**
* @param $productIds array
* @param $attributes array
* @param int $storeId
* @return bool
*/
public function updateProductsAttributes($productIds, $attributes, $storeId = 0) {
try {
$this->actionFactory->create()->updateAttributes($productIds, $attributes, $storeId);
return true;
} catch (\Exception $e) {
if ($this->getCustomilyConfig()['enable_logs'] == '1') {
$this->logger->debug($e->getTraceAsString());
}
return false;
}
}
/**
* @param $productId
* @return array|false
*/
public function getConfigurableProductAttributes($productId) {
/* @var \Magento\Catalog\Model\Product $product */
$product = $this->getProduct($productId);
$settings = $this->getCustomilyConfig();
$isCustomlyEnabled = $settings['enable'] ?? false;
$isCustomilyProduct = $product->getCustomProduct();
$isCustomilyProduct = $isCustomilyProduct ?? false;
$customilyProductId = $product->getProductCustomizationId();
$isValidCustomilyProductId = isset($customilyProductId) && $this->validateGuid(trim($customilyProductId));
if (
$isCustomlyEnabled === '1' &&
$isCustomilyProduct === '1' &&
$isValidCustomilyProductId &&
$product->getTypeId() == \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE
) {
/* @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable $productTypeInstance */
$productTypeInstance = $product->getTypeInstance();
return $productTypeInstance->getConfigurableAttributesAsArray($product);
}
return false;
}
/**
* @return mixed
*/
public function getCustomilyProductCount() {
$collection = $this->collectionFactory->create()->addAttributeToSelect('*')->addAttributeToFilter(
'custom_product',
'1'
);
return $collection->count();
}
/**
* @return string
*/
public function getMagentoVersion() {
return $this->productMetadataInterface->getVersion();
}
/**
* @return mixed
*/
public function getModuleVersion() {
try {
$moduleInfo = $this->moduleListInterface->getOne('Customily_Categories');
return $moduleInfo['setup_version'];
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
return '2.6.1';
}
}
/**
* @return array
*/
public function getMagentoBaseUrls()
{
/* @var \Magento\Store\Api\Data\StoreInterface $store */
$store = $this->storeManagerInterface->getStore();
return [
'baseUrl' => $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB, false),
'baseSecureUrl' => $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_WEB, true),
'baseMediaUrl' => $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA)
];
}
/**
* @return string
*/
public function getCustomilyApiEndpoint()
{
return $this->getMagentoBaseUrls()['baseUrl'] . self::API_PATH_CUSTOMILY;
}
/**
* @param \Magento\Sales\Model\Order $order
* @param \Magento\Sales\Model\Order\Item $orderItem
* @return string
*/
public function getProductionFileName($order, $orderItem) {
$result = '';
$settings = $this->getCustomilyConfig();
if (isset($settings['rename_file_pattern']) && !empty($settings['rename_file_pattern'])) {
$patternStrArray = explode('_', $settings['rename_file_pattern']);
for ($i = 0; $i < count($patternStrArray) - 1; $i++) {
$result .= "{$this->getPatternItemValue($patternStrArray[$i], $order, $orderItem)}_";
}
$result .= "{$this->getPatternItemValue($patternStrArray[count($patternStrArray) - 1], $order, $orderItem)}";
} else {
$result = "{$order->getIncrementId()}_{$orderItem->getSku()}";
}
return $result;
}
/**
* @param $str string
* @param \Magento\Sales\Model\Order $order
* @param \Magento\Sales\Model\Order\Item $orderItem
* @return string
*/
public function getPatternItemValue($str, $order, $orderItem) {
$str = strtolower($str);
switch ($str) {
case 'productid':
$result = $orderItem->getProductId();
break;
case 'sku':
$result = str_replace(' ', '-' , $orderItem->getSku());
break;
case 'productname':
$result = str_replace(' ', '-' , $orderItem->getProduct()->getName());
break;
case 'customer':
$fullName = "{$order->getBillingAddress()->getFirstname()} {$order->getBillingAddress()->getLastname()}";
$result = str_replace(' ', '-' , $fullName);
break;
case 'ordernumber':
$result = $order->getIncrementId();
break;
case 'random':
$result = rand(10000, 99999);
break;
default:
$result = $str;
break;
}
return $result;
}
/**
* @param bool $trim
* @return string
*/
public function guidv4($trim = true)
{
if (function_exists('com_create_guid') === true) {
if ($trim === true)
return trim(com_create_guid(), '{}');
else
return com_create_guid();
}
// OSX/Linux
if (function_exists('openssl_random_pseudo_bytes') === true) {
$data = openssl_random_pseudo_bytes(16);
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
// Fallback (PHP 4.2+)
mt_srand((double)microtime() * 10000);
$charid = strtolower(md5(uniqid(rand(), true)));
$hyphen = chr(45); // "-"
$lbrace = $trim ? "" : chr(123); // "{"
$rbrace = $trim ? "" : chr(125); // "}"
$guidv4 = $lbrace.
substr($charid, 0, 8).$hyphen.
substr($charid, 8, 4).$hyphen.
substr($charid, 12, 4).$hyphen.
substr($charid, 16, 4).$hyphen.
substr($charid, 20, 12).
$rbrace;
return $guidv4;
}
/**
* @param $array
* @param $key
* @return mixed
*/
public function shellSort($array, $key)
{
if (!$length = count($array)) {
return $array;
}
$k = 0;
$gap[0] = (int)($length / 2);
while($gap[$k] > 1) {
$k++;
$gap[$k] = (int)($gap[$k - 1] / 2);
}
for ($i = 0; $i <= $k; $i++) {
$step = $gap[$i];
for ($j = $step; $j < $length; $j++) {
$temp = $array[$j];
$p = $j - $step;
while ($p >= 0 && $temp[$key] < $array[$p][$key]) {
$array[$p + $step] = $array[$p];
$p = $p - $step;
}
$array[$p + $step] = $temp;
}
}
return $array;
}
/**
* @param null $array
* @param int $depth
* @return array|mixed[]
*/
public function arrayFlat($array = null, $depth = 1) {
$result = [];
if (!is_array($array)) $array = func_get_args();
foreach ($array as $key => $value) {
if (is_array($value) && $depth) {
$result = array_merge($result, $this->arrayFlat($value, $depth - 1));
} else {
$result = array_merge($result, [$key => $value]);
}
}
return $result;
}
/**
* get Personalized Item Count
*
* @param Items $items
* @return number $count
*/
public function getPersonalizedItemCount($items)
{
$count = 0;
foreach ($items as $item) {
if ($this->isMonogrammingOnlyItem($item)) {
$count += 1;
}
}
return $count;
}
/**
* Check Is Personalized Item
*
* @param Item $item
* @return bool
*/
public function isPersonalizedItem($item)
{
$data = $this->getQuoteBuyRequest($item->getId());
if (isset($data['customily']) && isset($data['customily']['personalization_id']) && !empty($data['customily']['personalization_id'])) {
return true;
}
return false;
}
/**
* Check Monogramming/Accessories Only
*
* @param Item $item
* @return bool
*/
public function isMonogrammingOnlyItem($item)
{
$data = $this->getQuoteBuyRequest($item->getId());
if (isset($data['options']) && isset($data['customily']) && isset($data['customily']['personalization_id']) && !empty($data['customily']['personalization_id'])) {
$product = $item->getProduct();
foreach ($data['options'] as $optionId => $optionValue) {
$option = $product->getOptionById((int)$optionId);
if ($option && in_array(strtolower($option->getType()), ['field', 'area'])) {
if ($optionValue != '') {
return true;
}
}
}
}
return false;
}
/**
* get Personalized Item Count from order
*
* @param Items $items
* @return number $count
*/
public function getPersonalizedOrderItemCount($items)
{
$count = 0;
foreach ($items as $item) {
if ($this->isPersonalizedOrderItem($item)) {
$count += 1;
}
}
return $count;
}
/**
* Check Is Personalized Order Item
*
* @param Item $_item
* @return bool
*/
public function isPersonalizedOrderItem($_item)
{
$data = [];
$itemOptions = $_item->getProductOptionByCode('additional_options');
$allOptions = $_item->getProductOptionByCode('options');
if (is_array($allOptions) || is_object($allOptions)) {
foreach ($allOptions as $option) {
if (in_array(strtolower($option['option_type']), ['field', 'area'])) {
if ($itemOptions != null && count($itemOptions) > 0) {
foreach ($itemOptions as $itemOption) {
if (($itemOption['label'] == 'Preview' || $itemOption['label'] == 'Production file') && $itemOption['value'] != '') {
$data[$itemOption['label']] = $itemOption['value'];
}
}
}
break;
}
}
}
if (array_key_exists('Preview', $data) && array_key_exists('Production file', $data)) {
return true;
}
return false;
}
/**
* Get Product Option Price
* @param null $item
* @param false $isOrderItem
* @return array|null Option Price
*/
public function getOptionPrice($item = null, $isOrderItem = false)
{
$product = $item->getProduct();
if (!$product && method_exists($item, 'getOrderItem')) {
$product = $item->getOrderItem()->getProduct();
}
$itemOptions = $product->getTypeInstance(true)->getOrderOptions($product);
if (isset($itemOptions['options'])) {
$customOptions = $itemOptions['options'];
} elseif (!empty($item->getProductOptionByCode('options')) && $isOrderItem) {
$customOptions = $item->getProductOptionByCode('options');
} else {
$customOptions = [];
}
if (!empty($customOptions)) {
$product = $this->getProduct($product->getEntityId());
$settings = $this->getCustomilyConfig();
$isCustomlyEnabled = $settings['enable'] ?? false;
$isCustomilyProduct = $product->getCustomProduct();
$isCustomilyProduct = $isCustomilyProduct ?? false;
$customilyProductId = $product->getProductCustomizationId();
$isValidCustomilyProductId = isset($customilyProductId) && $this->validateGuid(trim($customilyProductId));
if ($isCustomlyEnabled === '1' && $isCustomilyProduct === '1' && $isValidCustomilyProductId) {
$productOption = $this->optionCollectionFactory->create()->getProductOptions(
$product->getEntityId(),
$product->getStoreId(),
false
);
$optionData = [];
foreach ($productOption as $option) {
$optionId = $option->getId();
$optionValues = $product->getOptionById($optionId);
if ($optionValues === null) {
continue;
}
if (!(in_array($option->getType(), ['field', 'area']))) {
foreach ($optionValues->getValues() as $values) {
$optionData[$values->getOptionId()][$values->getOptionTypeId()] = [
'title' => $values->getTitle(),
'price' => $values->getPrice(),
'sku' => $values->getSku()
];
}
} else {
$optionData[$optionValues->getOptionId()] = [
'title' => $optionValues->getTitle(),
'price' => $optionValues->getPrice(),
'sku' => $optionValues->getSku()
];
}
}
$selectedOptionData = [];
$totalSelectedOptionPrice = 0;
foreach ($customOptions as $selectedOption) {
if (!(in_array($selectedOption['option_type'], ['field', 'area']))) {
$opData = $optionData[$selectedOption['option_id']][$selectedOption['option_value']];
if ($isOrderItem) {
if ($opData['sku'] != '') {
continue;
} else {
$selectedOption['price'] = $opData['price'];
$totalSelectedOptionPrice += $opData['price'];
}
} else {
$selectedOption['price'] = $opData['price'];
$selectedOption['sku'] = $opData['sku'];
$totalSelectedOptionPrice += $opData['price'];
}
} else {
$opData = $optionData[$selectedOption['option_id']];
if ($isOrderItem) {
if ($opData['sku'] != '') {
continue;
} else {
$selectedOption['price'] = $opData['price'];
$totalSelectedOptionPrice += $opData['price'];
}
} else {
$selectedOption['price'] = $opData['price'];
$selectedOption['sku'] = $opData['sku'];
$totalSelectedOptionPrice += $opData['price'];
}
}
$selectedOptionData[] = $selectedOption;
}
return [
'totalPersonalizationPrice' => $totalSelectedOptionPrice,
'optionsWithPrice' => $selectedOptionData
];
} else {
return null;
}
} else {
return null;
}
}
/**
* Get Buy Request from Quote ID
* @param $quoteItemId
* @return array
*/
public function getBuyRequestFromQuoteID($quoteItemId)
{
$optionValue = [];
$quoteItemCollection = $this->quoteItemCollectionFactory->create();
/* @var \Magento\Quote\Model\Quote\Item $quoteItem */
$quoteItem = $quoteItemCollection
->addFieldToSelect('*')
->addFieldToFilter('item_id', $quoteItemId)
->getFirstItem();
foreach ($quoteItem->getOptions() as $option) {
if ($option['code'] == 'info_buyRequest') {
$optionValue = $this->serializer->unserialize($option['value']);
break;
}
}
if (isset($optionValue['customily']) && !empty($optionValue['customily'])) {
return ['customily' => $optionValue['customily']];
} else {
return [];
}
}
/**
* Get productId from product customizable options
* @param $options
* @return null
*/
public function getProductIdFromOptions($options) {
$productId = null;
foreach ($options as $option) {
if ($option['label'] == 'magento_product_id') {
$productId = $option['value'];
break;
}
}
return $productId;
}
/**
* @param $anchor
* @return null
*/
public function getAnchorLink($anchor) {
$match = preg_match('/href=["\']?([^"\'>]+)["\']?/', $anchor, $result);
return $match === 1 ? $result[1] : null;
}
/**
* Get item options to show
* @param $options
* @param false $id
* @param false $sku
* @return array
*/
public function getItemOptionsToShow($options, $showImageUrl, $id = false, $sku = false) {
$product = null;
if (!empty($id)) {
$product = $this->getProduct($id);
} else if (!empty($sku)) {
$product = $this->getProductBySku($sku);
}
if (empty($product)) {
$id = $this->getProductIdFromOptions($options);
if (!empty($id)) {
$product = $this->getProduct($id);
}
}
$result = [];
foreach ($options as $option) {
$labelToLowerCase = strtolower($option['label']);
if (
$labelToLowerCase == 'magento_product_id' ||
$labelToLowerCase == 'personalization id' ||
$labelToLowerCase == 'thumbnail'
) {
continue;
}
if (
!empty($product) &&
(
($labelToLowerCase == 'preview' && $product->getPreviewLinkInEmail() !== '1') ||
($labelToLowerCase == 'production file' && $product->getProductionFileLinkInEmail() !== '1')
)
) {
continue;
}
if (isset($option['option_type']) && $option['option_type'] == 'file' && $showImageUrl === '1') {
$link = $this->getAnchorLink($option['value']);
if (!empty($link)) {
$option['value'] = $link;
}
}
$result[] = $option;
}
return $result;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib;
use Customily\Categories\Libraries\FontLib\Table\Type\name;
use Customily\Categories\Libraries\FontLib\TrueType\File;
/**
* Adobe Font Metrics file creation utility class.
*
* @package php-font-lib
*/
class AdobeFontMetrics {
private $f;
/**
* @var File
*/
private $font;
function __construct(File $font) {
$this->font = $font;
}
function write($file, $encoding = null) {
$map_data = array();
if ($encoding) {
$encoding = preg_replace("/[^a-z0-9-_]/", "", $encoding);
$map_file = dirname(__FILE__) . "/../maps/$encoding.map";
if (!file_exists($map_file)) {
throw new \Exception("Unkown encoding ($encoding)");
}
$map = new EncodingMap($map_file);
$map_data = $map->parse();
}
$this->f = fopen($file, "w+");
$font = $this->font;
$this->startSection("FontMetrics", 4.1);
$this->addPair("Notice", "Converted by PHP-font-lib");
$this->addPair("Comment", "https://github.com/PhenX/php-font-lib");
$encoding_scheme = ($encoding ? $encoding : "FontSpecific");
$this->addPair("EncodingScheme", $encoding_scheme);
$records = $font->getData("name", "records");
foreach ($records as $id => $record) {
if (!isset(name::$nameIdCodes[$id]) || preg_match("/[\r\n]/", $record->string)) {
continue;
}
$this->addPair(name::$nameIdCodes[$id], $record->string);
}
$os2 = $font->getData("OS/2");
$this->addPair("Weight", ($os2["usWeightClass"] > 400 ? "Bold" : "Medium"));
$post = $font->getData("post");
$this->addPair("ItalicAngle", $post["italicAngle"]);
$this->addPair("IsFixedPitch", ($post["isFixedPitch"] ? "true" : "false"));
$this->addPair("UnderlineThickness", $font->normalizeFUnit($post["underlineThickness"]));
$this->addPair("UnderlinePosition", $font->normalizeFUnit($post["underlinePosition"]));
$hhea = $font->getData("hhea");
if (isset($hhea["ascent"])) {
$this->addPair("FontHeightOffset", $font->normalizeFUnit($hhea["lineGap"]));
$this->addPair("Ascender", $font->normalizeFUnit($hhea["ascent"]));
$this->addPair("Descender", $font->normalizeFUnit($hhea["descent"]));
}
else {
$this->addPair("FontHeightOffset", $font->normalizeFUnit($os2["typoLineGap"]));
$this->addPair("Ascender", $font->normalizeFUnit($os2["typoAscender"]));
$this->addPair("Descender", -abs($font->normalizeFUnit($os2["typoDescender"])));
}
$head = $font->getData("head");
$this->addArray("FontBBox", array(
$font->normalizeFUnit($head["xMin"]),
$font->normalizeFUnit($head["yMin"]),
$font->normalizeFUnit($head["xMax"]),
$font->normalizeFUnit($head["yMax"]),
));
$glyphIndexArray = $font->getUnicodeCharMap();
if ($glyphIndexArray) {
$hmtx = $font->getData("hmtx");
$names = $font->getData("post", "names");
$this->startSection("CharMetrics", count($hmtx));
if ($encoding) {
foreach ($map_data as $code => $value) {
list($c, $name) = $value;
if (!isset($glyphIndexArray[$c])) {
continue;
}
$g = $glyphIndexArray[$c];
if (!isset($hmtx[$g])) {
$hmtx[$g] = $hmtx[0];
}
$this->addMetric(array(
"C" => ($code > 255 ? -1 : $code),
"WX" => $font->normalizeFUnit($hmtx[$g][0]),
"N" => $name,
));
}
}
else {
foreach ($glyphIndexArray as $c => $g) {
if (!isset($hmtx[$g])) {
$hmtx[$g] = $hmtx[0];
}
$this->addMetric(array(
"U" => $c,
"WX" => $font->normalizeFUnit($hmtx[$g][0]),
"N" => (isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $c)),
"G" => $g,
));
}
}
$this->endSection("CharMetrics");
$kern = $font->getData("kern", "subtable");
$tree = is_array($kern) ? $kern["tree"] : null;
if (!$encoding && is_array($tree)) {
$this->startSection("KernData");
$this->startSection("KernPairs", count($tree, COUNT_RECURSIVE) - count($tree));
foreach ($tree as $left => $values) {
if (!is_array($values)) {
continue;
}
if (!isset($glyphIndexArray[$left])) {
continue;
}
$left_gid = $glyphIndexArray[$left];
if (!isset($names[$left_gid])) {
continue;
}
$left_name = $names[$left_gid];
$this->addLine("");
foreach ($values as $right => $value) {
if (!isset($glyphIndexArray[$right])) {
continue;
}
$right_gid = $glyphIndexArray[$right];
if (!isset($names[$right_gid])) {
continue;
}
$right_name = $names[$right_gid];
$this->addPair("KPX", "$left_name $right_name $value");
}
}
$this->endSection("KernPairs");
$this->endSection("KernData");
}
}
$this->endSection("FontMetrics");
}
function addLine($line) {
fwrite($this->f, "$line\n");
}
function addPair($key, $value) {
$this->addLine("$key $value");
}
function addArray($key, $array) {
$this->addLine("$key " . implode(" ", $array));
}
function addMetric($data) {
$array = array();
foreach ($data as $key => $value) {
$array[] = "$key $value";
}
$this->addLine(implode(" ; ", $array));
}
function startSection($name, $value = "") {
$this->addLine("Start$name $value");
}
function endSection($name) {
$this->addLine("End$name");
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien M�nager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib;
/**
* Autoloads FontLib classes
*
* @package php-font-lib
*/
class Autoloader {
const PREFIX = 'FontLib';
/**
* Register the autoloader
*/
public static function register() {
spl_autoload_register(array(new self, 'autoload'));
}
/**
* Autoloader
*
* @param string
*/
public static function autoload($class) {
$prefixLength = strlen(self::PREFIX);
if (0 === strncmp(self::PREFIX, $class, $prefixLength)) {
$file = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, $prefixLength));
$file = realpath(__DIR__ . (empty($file) ? '' : DIRECTORY_SEPARATOR) . $file . '.php');
if (file_exists($file)) {
require_once $file;
}
}
}
}
Autoloader::register();
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib;
/**
* Generic font file binary stream.
*
* @package php-font-lib
*/
class BinaryStream {
/**
* @var resource The file pointer
*/
protected $f;
const uint8 = 1;
const int8 = 2;
const uint16 = 3;
const int16 = 4;
const uint32 = 5;
const int32 = 6;
const shortFrac = 7;
const Fixed = 8;
const FWord = 9;
const uFWord = 10;
const F2Dot14 = 11;
const longDateTime = 12;
const char = 13;
const modeRead = "rb";
const modeWrite = "wb";
const modeReadWrite = "rb+";
static function backtrace() {
var_dump(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS));
}
/**
* Open a font file in read mode
*
* @param string $filename The file name of the font to open
*
* @return bool
*/
public function load($filename) {
return $this->open($filename, self::modeRead);
}
/**
* Open a font file in a chosen mode
*
* @param string $filename The file name of the font to open
* @param string $mode The opening mode
*
* @throws \Exception
* @return bool
*/
public function open($filename, $mode = self::modeRead) {
if (!in_array($mode, array(self::modeRead, self::modeWrite, self::modeReadWrite))) {
throw new \Exception("Unkown file open mode");
}
$this->f = fopen($filename, $mode);
return $this->f != false;
}
/**
* Close the internal file pointer
*/
public function close() {
return fclose($this->f) != false;
}
/**
* Change the internal file pointer
*
* @param resource $fp
*
* @throws \Exception
*/
public function setFile($fp) {
if (!is_resource($fp)) {
throw new \Exception('$fp is not a valid resource');
}
$this->f = $fp;
}
/**
* Create a temporary file in write mode
*
* @param bool $allow_memory Allow in-memory files
*
* @return resource the temporary file pointer resource
*/
public static function getTempFile($allow_memory = true) {
$f = null;
if ($allow_memory) {
$f = fopen("php://temp", "rb+");
}
else {
$f = fopen(tempnam(sys_get_temp_dir(), "fnt"), "rb+");
}
return $f;
}
/**
* Move the internal file pinter to $offset bytes
*
* @param int $offset
*
* @return bool True if the $offset position exists in the file
*/
public function seek($offset) {
return fseek($this->f, $offset, SEEK_SET) == 0;
}
/**
* Gives the current position in the file
*
* @return int The current position
*/
public function pos() {
return ftell($this->f);
}
public function skip($n) {
fseek($this->f, $n, SEEK_CUR);
}
public function read($n) {
if ($n < 1) {
return "";
}
return fread($this->f, $n);
}
public function write($data, $length = null) {
if ($data === null || $data === "" || $data === false) {
return 0;
}
return fwrite($this->f, $data, $length);
}
public function readUInt8() {
return ord($this->read(1));
}
public function readUInt8Many($count) {
return array_values(unpack("C*", $this->read($count)));
}
public function writeUInt8($data) {
return $this->write(chr($data), 1);
}
public function readInt8() {
$v = $this->readUInt8();
if ($v >= 0x80) {
$v -= 0x100;
}
return $v;
}
public function readInt8Many($count) {
return array_values(unpack("c*", $this->read($count)));
}
public function writeInt8($data) {
if ($data < 0) {
$data += 0x100;
}
return $this->writeUInt8($data);
}
public function readUInt16() {
$a = unpack("nn", $this->read(2));
return $a["n"];
}
public function readUInt16Many($count) {
return array_values(unpack("n*", $this->read($count * 2)));
}
public function readUFWord() {
return $this->readUInt16();
}
public function writeUInt16($data) {
return $this->write(pack("n", $data), 2);
}
public function writeUFWord($data) {
return $this->writeUInt16($data);
}
public function readInt16() {
$a = unpack("nn", $this->read(2));
$v = $a["n"];
if ($v >= 0x8000) {
$v -= 0x10000;
}
return $v;
}
public function readInt16Many($count) {
$vals = array_values(unpack("n*", $this->read($count * 2)));
foreach ($vals as &$v) {
if ($v >= 0x8000) {
$v -= 0x10000;
}
}
return $vals;
}
public function readFWord() {
return $this->readInt16();
}
public function writeInt16($data) {
if ($data < 0) {
$data += 0x10000;
}
return $this->writeUInt16($data);
}
public function writeFWord($data) {
return $this->writeInt16($data);
}
public function readUInt32() {
$a = unpack("NN", $this->read(4));
return $a["N"];
}
public function writeUInt32($data) {
return $this->write(pack("N", $data), 4);
}
public function readFixed() {
$d = $this->readInt16();
$d2 = $this->readUInt16();
return round($d + $d2 / 0x10000, 4);
}
public function writeFixed($data) {
$left = floor($data);
$right = ($data - $left) * 0x10000;
return $this->writeInt16($left) + $this->writeUInt16($right);
}
public function readLongDateTime() {
$this->readUInt32(); // ignored
$date = $this->readUInt32() - 2082844800;
# PHP_INT_MIN isn't defined in PHP < 7.0
$php_int_min = defined("PHP_INT_MIN") ? PHP_INT_MIN : ~PHP_INT_MAX;
if (is_string($date) || $date > PHP_INT_MAX || $date < $php_int_min) {
$date = 0;
}
return strftime("%Y-%m-%d %H:%M:%S", $date);
}
public function writeLongDateTime($data) {
$date = strtotime($data);
$date += 2082844800;
return $this->writeUInt32(0) + $this->writeUInt32($date);
}
public function unpack($def) {
$d = array();
foreach ($def as $name => $type) {
$d[$name] = $this->r($type);
}
return $d;
}
public function pack($def, $data) {
$bytes = 0;
foreach ($def as $name => $type) {
$bytes += $this->w($type, $data[$name]);
}
return $bytes;
}
/**
* Read a data of type $type in the file from the current position
*
* @param mixed $type The data type to read
*
* @return mixed The data that was read
*/
public function r($type) {
switch ($type) {
case self::uint8:
return $this->readUInt8();
case self::int8:
return $this->readInt8();
case self::uint16:
return $this->readUInt16();
case self::int16:
return $this->readInt16();
case self::uint32:
return $this->readUInt32();
case self::int32:
return $this->readUInt32();
case self::shortFrac:
return $this->readFixed();
case self::Fixed:
return $this->readFixed();
case self::FWord:
return $this->readInt16();
case self::uFWord:
return $this->readUInt16();
case self::F2Dot14:
return $this->readInt16();
case self::longDateTime:
return $this->readLongDateTime();
case self::char:
return $this->read(1);
default:
if (is_array($type)) {
if ($type[0] == self::char) {
return $this->read($type[1]);
}
if ($type[0] == self::uint16) {
return $this->readUInt16Many($type[1]);
}
if ($type[0] == self::int16) {
return $this->readInt16Many($type[1]);
}
if ($type[0] == self::uint8) {
return $this->readUInt8Many($type[1]);
}
if ($type[0] == self::int8) {
return $this->readInt8Many($type[1]);
}
$ret = array();
for ($i = 0; $i < $type[1]; $i++) {
$ret[] = $this->r($type[0]);
}
return $ret;
}
return null;
}
}
/**
* Write $data of type $type in the file from the current position
*
* @param mixed $type The data type to write
* @param mixed $data The data to write
*
* @return int The number of bytes read
*/
public function w($type, $data) {
switch ($type) {
case self::uint8:
return $this->writeUInt8($data);
case self::int8:
return $this->writeInt8($data);
case self::uint16:
return $this->writeUInt16($data);
case self::int16:
return $this->writeInt16($data);
case self::uint32:
return $this->writeUInt32($data);
case self::int32:
return $this->writeUInt32($data);
case self::shortFrac:
return $this->writeFixed($data);
case self::Fixed:
return $this->writeFixed($data);
case self::FWord:
return $this->writeInt16($data);
case self::uFWord:
return $this->writeUInt16($data);
case self::F2Dot14:
return $this->writeInt16($data);
case self::longDateTime:
return $this->writeLongDateTime($data);
case self::char:
return $this->write($data, 1);
default:
if (is_array($type)) {
if ($type[0] == self::char) {
return $this->write($data, $type[1]);
}
$ret = 0;
for ($i = 0; $i < $type[1]; $i++) {
if (isset($data[$i])) {
$ret += $this->w($type[0], $data[$i]);
}
}
return $ret;
}
return null;
}
}
/**
* Converts a Uint32 value to string
*
* @param int $uint32
*
* @return string The string
*/
public function convertUInt32ToStr($uint32) {
return chr(($uint32 >> 24) & 0xFF) . chr(($uint32 >> 16) & 0xFF) . chr(($uint32 >> 8) & 0xFF) . chr($uint32 & 0xFF);
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\EOT;
/**
* EOT font file.
*
* @package php-font-lib
*/
class File extends \Customily\Categories\Libraries\FontLib\TrueType\File {
const TTEMBED_SUBSET = 0x00000001;
const TTEMBED_TTCOMPRESSED = 0x00000004;
const TTEMBED_FAILIFVARIATIONSIMULATED = 0x00000010;
const TTMBED_EMBEDEUDC = 0x00000020;
const TTEMBED_VALIDATIONTESTS = 0x00000040; // Deprecated
const TTEMBED_WEBOBJECT = 0x00000080;
const TTEMBED_XORENCRYPTDATA = 0x10000000;
/**
* @var Header
*/
public $header;
function parseHeader() {
if (!empty($this->header)) {
return;
}
$this->header = new Header($this);
$this->header->parse();
}
function parse() {
$this->parseHeader();
$flags = $this->header->data["Flags"];
if ($flags & self::TTEMBED_TTCOMPRESSED) {
$mtx_version = $this->readUInt8();
$mtx_copy_limit = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
$mtx_offset_1 = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
$mtx_offset_2 = $this->readUInt8() << 16 | $this->readUInt8() << 8 | $this->readUInt8();
/*
var_dump("$mtx_version $mtx_copy_limit $mtx_offset_1 $mtx_offset_2");
$pos = $this->pos();
$size = $mtx_offset_1 - $pos;
var_dump("pos: $pos");
var_dump("size: $size");*/
}
if ($flags & self::TTEMBED_XORENCRYPTDATA) {
// Process XOR
}
// TODO Read font data ...
}
/**
* Little endian version of the read method
*
* @param int $n The number of bytes to read
*
* @return string
*/
public function read($n) {
if ($n < 1) {
return "";
}
$string = fread($this->f, $n);
$chunks = str_split($string, 2);
$chunks = array_map("strrev", $chunks);
return implode("", $chunks);
}
public function readUInt32() {
$uint32 = parent::readUInt32();
return $uint32 >> 16 & 0x0000FFFF | $uint32 << 16 & 0xFFFF0000;
}
/**
* Get font copyright
*
* @return string|null
*/
function getFontCopyright() {
return null;
}
/**
* Get font name
*
* @return string|null
*/
function getFontName() {
return $this->header->data["FamilyName"];
}
/**
* Get font subfamily
*
* @return string|null
*/
function getFontSubfamily() {
return $this->header->data["StyleName"];
}
/**
* Get font subfamily ID
*
* @return string|null
*/
function getFontSubfamilyID() {
return $this->header->data["StyleName"];
}
/**
* Get font full name
*
* @return string|null
*/
function getFontFullName() {
return $this->header->data["FullName"];
}
/**
* Get font version
*
* @return string|null
*/
function getFontVersion() {
return $this->header->data["VersionName"];
}
/**
* Get font weight
*
* @return string|null
*/
function getFontWeight() {
return $this->header->data["Weight"];
}
/**
* Get font Postscript name
*
* @return string|null
*/
function getFontPostscriptName() {
return null;
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\EOT;
use Exception;
use Customily\Categories\Libraries\FontLib\Font;
/**
* TrueType font file header.
*
* @package php-font-lib
*
* @property File $font
*/
class Header extends \Customily\Categories\Libraries\FontLib\Header {
protected $def = array(
"format" => self::uint32,
"numTables" => self::uint16,
"searchRange" => self::uint16,
"entrySelector" => self::uint16,
"rangeShift" => self::uint16,
);
public function parse() {
$font = $this->font;
$this->data = $font->unpack(array(
"EOTSize" => self::uint32,
"FontDataSize" => self::uint32,
"Version" => self::uint32,
"Flags" => self::uint32,
"FontPANOSE" => array(self::uint8, 10),
"Charset" => self::uint8,
"Italic" => self::uint8,
"Weight" => self::uint32,
"fsType" => self::uint16,
"MagicNumber" => self::uint16,
"UnicodeRange1" => self::uint32,
"UnicodeRange2" => self::uint32,
"UnicodeRange3" => self::uint32,
"UnicodeRange4" => self::uint32,
"CodePageRange1" => self::uint32,
"CodePageRange2" => self::uint32,
"CheckSumAdjustment" => self::uint32,
"Reserved1" => self::uint32,
"Reserved2" => self::uint32,
"Reserved3" => self::uint32,
"Reserved4" => self::uint32,
));
$this->data["Padding1"] = $font->readUInt16();
$this->readString("FamilyName");
$this->data["Padding2"] = $font->readUInt16();
$this->readString("StyleName");
$this->data["Padding3"] = $font->readUInt16();
$this->readString("VersionName");
$this->data["Padding4"] = $font->readUInt16();
$this->readString("FullName");
switch ($this->data["Version"]) {
default:
throw new Exception("Unknown EOT version " . $this->data["Version"]);
case 0x00010000:
// Nothing to do more
break;
case 0x00020001:
$this->data["Padding5"] = $font->readUInt16();
$this->readString("RootString");
break;
case 0x00020002:
$this->data["Padding5"] = $font->readUInt16();
$this->readString("RootString");
$this->data["RootStringCheckSum"] = $font->readUInt32();
$this->data["EUDCCodePage"] = $font->readUInt32();
$this->data["Padding6"] = $font->readUInt16();
$this->readString("Signature");
$this->data["EUDCFlags"] = $font->readUInt32();
$this->data["EUDCFontSize"] = $font->readUInt32();
break;
}
if (!empty($this->data["RootString"])) {
$this->data["RootString"] = explode("\0", $this->data["RootString"]);
}
}
private function readString($name) {
$font = $this->font;
$size = $font->readUInt16();
$this->data["{$name}Size"] = $size;
$this->data[$name] = Font::UTF16ToUTF8($font->read($size));
}
public function encode() {
//return $this->font->pack($this->def, $this->data);
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib;
/**
* Encoding map used to map a code point to a Unicode char.
*
* @package php-font-lib
*/
class EncodingMap {
private $f;
function __construct($file) {
$this->f = fopen($file, "r");
}
function parse() {
$map = array();
while ($line = fgets($this->f)) {
if (preg_match('/^[\!\=]([0-9A-F]{2,})\s+U\+([0-9A-F]{2})([0-9A-F]{2})\s+([^\s]+)/', $line, $matches)) {
$unicode = (hexdec($matches[2]) << 8) + hexdec($matches[3]);
$map[hexdec($matches[1])] = array($unicode, $matches[4]);
}
}
ksort($map);
return $map;
}
}
<?php
namespace Customily\Categories\Libraries\FontLib\Exception;
class FontNotFoundException extends \Exception
{
public function __construct($fontPath)
{
$this->message = 'Font not found in: ' . $fontPath;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib;
use Customily\Categories\Libraries\FontLib\Exception\FontNotFoundException;
/**
* Generic font file.
*
* @package php-font-lib
*/
class Font {
static $debug = false;
/**
* @param string $file The font file
*
* @return TrueType\File|null $file
*/
public static function load($file) {
if(!file_exists($file)){
throw new FontNotFoundException($file);
}
$header = file_get_contents($file, false, null, null, 4);
$class = null;
switch ($header) {
case "\x00\x01\x00\x00":
case "true":
case "typ1":
$class = "TrueType\\File";
break;
case "OTTO":
$class = "OpenType\\File";
break;
case "wOFF":
$class = "WOFF\\File";
break;
case "ttcf":
$class = "TrueType\\Collection";
break;
// Unknown type or EOT
default:
$magicNumber = file_get_contents($file, false, null, 34, 2);
if ($magicNumber === "LP") {
$class = "EOT\\File";
}
}
if ($class) {
$class = "Customily\\Categories\\Libraries\\FontLib\\$class";
/** @var TrueType\File $obj */
$obj = new $class;
$obj->load($file);
return $obj;
}
return null;
}
static function d($str) {
if (!self::$debug) {
return;
}
echo "$str\n";
}
static function UTF16ToUTF8($str) {
return mb_convert_encoding($str, "utf-8", "utf-16");
}
static function UTF8ToUTF16($str) {
return mb_convert_encoding($str, "utf-16", "utf-8");
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
*/
namespace Customily\Categories\Libraries\FontLib\Glyph;
use Customily\Categories\Libraries\FontLib\Table\Type\glyf;
use Customily\Categories\Libraries\FontLib\TrueType\File;
use Customily\Categories\Libraries\FontLib\BinaryStream;
/**
* `glyf` font table.
*
* @package php-font-lib
*/
class Outline extends BinaryStream {
/**
* @var \Customily\Categories\Libraries\FontLib\Table\Type\glyf
*/
protected $table;
protected $offset;
protected $size;
// Data
public $numberOfContours;
public $xMin;
public $yMin;
public $xMax;
public $yMax;
public $raw;
/**
* @param glyf $table
* @param $offset
* @param $size
*
* @return Outline
*/
static function init(glyf $table, $offset, $size, BinaryStream $font) {
$font->seek($offset);
if ($font->readInt16() > -1) {
/** @var OutlineSimple $glyph */
$glyph = new OutlineSimple($table, $offset, $size);
}
else {
/** @var OutlineComposite $glyph */
$glyph = new OutlineComposite($table, $offset, $size);
}
$glyph->parse($font);
return $glyph;
}
/**
* @return File
*/
function getFont() {
return $this->table->getFont();
}
function __construct(glyf $table, $offset = null, $size = null) {
$this->table = $table;
$this->offset = $offset;
$this->size = $size;
}
function parse(BinaryStream $font) {
$font->seek($this->offset);
if (!$this->size) {
return;
}
$this->raw = $font->read($this->size);
}
function parseData() {
$font = $this->getFont();
$font->seek($this->offset);
$this->numberOfContours = $font->readInt16();
$this->xMin = $font->readFWord();
$this->yMin = $font->readFWord();
$this->xMax = $font->readFWord();
$this->yMax = $font->readFWord();
}
function encode() {
$font = $this->getFont();
return $font->write($this->raw, strlen($this->raw));
}
function getSVGContours() {
// Inherit
}
function getGlyphIDs() {
return array();
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
*/
namespace Customily\Categories\Libraries\FontLib\Glyph;
/**
* Glyph outline component
*
* @package php-font-lib
*/
class OutlineComponent {
public $flags;
public $glyphIndex;
public $a, $b, $c, $d, $e, $f;
public $point_compound;
public $point_component;
public $instructions;
function getMatrix() {
return array(
$this->a, $this->b,
$this->c, $this->d,
$this->e, $this->f,
);
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
*/
namespace Customily\Categories\Libraries\FontLib\Glyph;
/**
* Composite glyph outline
*
* @package php-font-lib
*/
class OutlineComposite extends Outline {
const ARG_1_AND_2_ARE_WORDS = 0x0001;
const ARGS_ARE_XY_VALUES = 0x0002;
const ROUND_XY_TO_GRID = 0x0004;
const WE_HAVE_A_SCALE = 0x0008;
const MORE_COMPONENTS = 0x0020;
const WE_HAVE_AN_X_AND_Y_SCALE = 0x0040;
const WE_HAVE_A_TWO_BY_TWO = 0x0080;
const WE_HAVE_INSTRUCTIONS = 0x0100;
const USE_MY_METRICS = 0x0200;
const OVERLAP_COMPOUND = 0x0400;
/**
* @var OutlineComponent[]
*/
public $components = array();
function getGlyphIDs() {
if (empty($this->components)) {
$this->parseData();
}
$glyphIDs = array();
foreach ($this->components as $_component) {
$glyphIDs[] = $_component->glyphIndex;
$_glyph = $this->table->data[$_component->glyphIndex];
if ($_glyph !== $this) {
$glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
}
}
return $glyphIDs;
}
/*function parse() {
//$this->parseData();
}*/
function parseData() {
parent::parseData();
$font = $this->getFont();
do {
$flags = $font->readUInt16();
$glyphIndex = $font->readUInt16();
$a = 1.0;
$b = 0.0;
$c = 0.0;
$d = 1.0;
$e = 0.0;
$f = 0.0;
$point_compound = null;
$point_component = null;
$instructions = null;
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
if ($flags & self::ARGS_ARE_XY_VALUES) {
$e = $font->readInt16();
$f = $font->readInt16();
}
else {
$point_compound = $font->readUInt16();
$point_component = $font->readUInt16();
}
}
else {
if ($flags & self::ARGS_ARE_XY_VALUES) {
$e = $font->readInt8();
$f = $font->readInt8();
}
else {
$point_compound = $font->readUInt8();
$point_component = $font->readUInt8();
}
}
if ($flags & self::WE_HAVE_A_SCALE) {
$a = $d = $font->readInt16();
}
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
$a = $font->readInt16();
$d = $font->readInt16();
}
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
$a = $font->readInt16();
$b = $font->readInt16();
$c = $font->readInt16();
$d = $font->readInt16();
}
//if ($flags & self::WE_HAVE_INSTRUCTIONS) {
//
//}
$component = new OutlineComponent();
$component->flags = $flags;
$component->glyphIndex = $glyphIndex;
$component->a = $a;
$component->b = $b;
$component->c = $c;
$component->d = $d;
$component->e = $e;
$component->f = $f;
$component->point_compound = $point_compound;
$component->point_component = $point_component;
$component->instructions = $instructions;
$this->components[] = $component;
} while ($flags & self::MORE_COMPONENTS);
}
function encode() {
$font = $this->getFont();
$gids = $font->getSubset();
$size = $font->writeInt16(-1);
$size += $font->writeFWord($this->xMin);
$size += $font->writeFWord($this->yMin);
$size += $font->writeFWord($this->xMax);
$size += $font->writeFWord($this->yMax);
foreach ($this->components as $_i => $_component) {
$flags = 0;
if ($_component->point_component === null && $_component->point_compound === null) {
$flags |= self::ARGS_ARE_XY_VALUES;
if (abs($_component->e) > 0x7F || abs($_component->f) > 0x7F) {
$flags |= self::ARG_1_AND_2_ARE_WORDS;
}
}
elseif ($_component->point_component > 0xFF || $_component->point_compound > 0xFF) {
$flags |= self::ARG_1_AND_2_ARE_WORDS;
}
if ($_component->b == 0 && $_component->c == 0) {
if ($_component->a == $_component->d) {
if ($_component->a != 1.0) {
$flags |= self::WE_HAVE_A_SCALE;
}
}
else {
$flags |= self::WE_HAVE_AN_X_AND_Y_SCALE;
}
}
else {
$flags |= self::WE_HAVE_A_TWO_BY_TWO;
}
if ($_i < count($this->components) - 1) {
$flags |= self::MORE_COMPONENTS;
}
$size += $font->writeUInt16($flags);
$new_gid = array_search($_component->glyphIndex, $gids);
$size += $font->writeUInt16($new_gid);
if ($flags & self::ARG_1_AND_2_ARE_WORDS) {
if ($flags & self::ARGS_ARE_XY_VALUES) {
$size += $font->writeInt16($_component->e);
$size += $font->writeInt16($_component->f);
}
else {
$size += $font->writeUInt16($_component->point_compound);
$size += $font->writeUInt16($_component->point_component);
}
}
else {
if ($flags & self::ARGS_ARE_XY_VALUES) {
$size += $font->writeInt8($_component->e);
$size += $font->writeInt8($_component->f);
}
else {
$size += $font->writeUInt8($_component->point_compound);
$size += $font->writeUInt8($_component->point_component);
}
}
if ($flags & self::WE_HAVE_A_SCALE) {
$size += $font->writeInt16($_component->a);
}
elseif ($flags & self::WE_HAVE_AN_X_AND_Y_SCALE) {
$size += $font->writeInt16($_component->a);
$size += $font->writeInt16($_component->d);
}
elseif ($flags & self::WE_HAVE_A_TWO_BY_TWO) {
$size += $font->writeInt16($_component->a);
$size += $font->writeInt16($_component->b);
$size += $font->writeInt16($_component->c);
$size += $font->writeInt16($_component->d);
}
}
return $size;
}
public function getSVGContours() {
$contours = array();
/** @var \Customily\Categories\Libraries\FontLib\Table\Type\glyf $glyph_data */
$glyph_data = $this->getFont()->getTableObject("glyf");
/** @var Outline[] $glyphs */
$glyphs = $glyph_data->data;
foreach ($this->components as $component) {
$_glyph = $glyphs[$component->glyphIndex];
if ($_glyph !== $this) {
$contours[] = array(
"contours" => $_glyph->getSVGContours(),
"transform" => $component->getMatrix(),
);
}
}
return $contours;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $
*/
namespace Customily\Categories\Libraries\FontLib\Glyph;
/**
* `glyf` font table.
*
* @package php-font-lib
*/
class OutlineSimple extends Outline {
const ON_CURVE = 0x01;
const X_SHORT_VECTOR = 0x02;
const Y_SHORT_VECTOR = 0x04;
const REPEAT = 0x08;
const THIS_X_IS_SAME = 0x10;
const THIS_Y_IS_SAME = 0x20;
public $instructions;
public $points;
function parseData() {
parent::parseData();
if (!$this->size) {
return;
}
$font = $this->getFont();
$noc = $this->numberOfContours;
if ($noc == 0) {
return;
}
$endPtsOfContours = $font->r(array(self::uint16, $noc));
$instructionLength = $font->readUInt16();
$this->instructions = $font->r(array(self::uint8, $instructionLength));
$count = $endPtsOfContours[$noc - 1] + 1;
// Flags
$flags = array();
for ($index = 0; $index < $count; $index++) {
$flags[$index] = $font->readUInt8();
if ($flags[$index] & self::REPEAT) {
$repeats = $font->readUInt8();
for ($i = 1; $i <= $repeats; $i++) {
$flags[$index + $i] = $flags[$index];
}
$index += $repeats;
}
}
$points = array();
foreach ($flags as $i => $flag) {
$points[$i]["onCurve"] = $flag & self::ON_CURVE;
$points[$i]["endOfContour"] = in_array($i, $endPtsOfContours);
}
// X Coords
$x = 0;
for ($i = 0; $i < $count; $i++) {
$flag = $flags[$i];
if ($flag & self::THIS_X_IS_SAME) {
if ($flag & self::X_SHORT_VECTOR) {
$x += $font->readUInt8();
}
}
else {
if ($flag & self::X_SHORT_VECTOR) {
$x -= $font->readUInt8();
}
else {
$x += $font->readInt16();
}
}
$points[$i]["x"] = $x;
}
// Y Coords
$y = 0;
for ($i = 0; $i < $count; $i++) {
$flag = $flags[$i];
if ($flag & self::THIS_Y_IS_SAME) {
if ($flag & self::Y_SHORT_VECTOR) {
$y += $font->readUInt8();
}
}
else {
if ($flag & self::Y_SHORT_VECTOR) {
$y -= $font->readUInt8();
}
else {
$y += $font->readInt16();
}
}
$points[$i]["y"] = $y;
}
$this->points = $points;
}
public function splitSVGPath($path) {
preg_match_all('/([a-z])|(-?\d+(?:\.\d+)?)/i', $path, $matches, PREG_PATTERN_ORDER);
return $matches[0];
}
public function makePoints($path) {
$path = $this->splitSVGPath($path);
$l = count($path);
$i = 0;
$points = array();
while ($i < $l) {
switch ($path[$i]) {
// moveTo
case "M":
$points[] = array(
"onCurve" => true,
"x" => $path[++$i],
"y" => $path[++$i],
"endOfContour" => false,
);
break;
// lineTo
case "L":
$points[] = array(
"onCurve" => true,
"x" => $path[++$i],
"y" => $path[++$i],
"endOfContour" => false,
);
break;
// quadraticCurveTo
case "Q":
$points[] = array(
"onCurve" => false,
"x" => $path[++$i],
"y" => $path[++$i],
"endOfContour" => false,
);
$points[] = array(
"onCurve" => true,
"x" => $path[++$i],
"y" => $path[++$i],
"endOfContour" => false,
);
break;
// closePath
/** @noinspection PhpMissingBreakStatementInspection */
case "z":
$points[count($points) - 1]["endOfContour"] = true;
default:
$i++;
break;
}
}
return $points;
}
function encode() {
if (empty($this->points)) {
return parent::encode();
}
return $this->size = $this->encodePoints($this->points);
}
public function encodePoints($points) {
$endPtsOfContours = array();
$flags = array();
$coords_x = array();
$coords_y = array();
$last_x = 0;
$last_y = 0;
$xMin = $yMin = 0xFFFF;
$xMax = $yMax = -0xFFFF;
foreach ($points as $i => $point) {
$flag = 0;
if ($point["onCurve"]) {
$flag |= self::ON_CURVE;
}
if ($point["endOfContour"]) {
$endPtsOfContours[] = $i;
}
// Simplified, we could do some optimizations
if ($point["x"] == $last_x) {
$flag |= self::THIS_X_IS_SAME;
}
else {
$x = intval($point["x"]);
$xMin = min($x, $xMin);
$xMax = max($x, $xMax);
$coords_x[] = $x - $last_x; // int16
}
// Simplified, we could do some optimizations
if ($point["y"] == $last_y) {
$flag |= self::THIS_Y_IS_SAME;
}
else {
$y = intval($point["y"]);
$yMin = min($y, $yMin);
$yMax = max($y, $yMax);
$coords_y[] = $y - $last_y; // int16
}
$flags[] = $flag;
$last_x = $point["x"];
$last_y = $point["y"];
}
$font = $this->getFont();
$l = 0;
$l += $font->writeInt16(count($endPtsOfContours)); // endPtsOfContours
$l += $font->writeFWord(isset($this->xMin) ? $this->xMin : $xMin); // xMin
$l += $font->writeFWord(isset($this->yMin) ? $this->yMin : $yMin); // yMin
$l += $font->writeFWord(isset($this->xMax) ? $this->xMax : $xMax); // xMax
$l += $font->writeFWord(isset($this->yMax) ? $this->yMax : $yMax); // yMax
// Simple glyf
$l += $font->w(array(self::uint16, count($endPtsOfContours)), $endPtsOfContours); // endPtsOfContours
$l += $font->writeUInt16(0); // instructionLength
$l += $font->w(array(self::uint8, count($flags)), $flags); // flags
$l += $font->w(array(self::int16, count($coords_x)), $coords_x); // xCoordinates
$l += $font->w(array(self::int16, count($coords_y)), $coords_y); // yCoordinates
return $l;
}
public function getSVGContours($points = null) {
$path = "";
if (!$points) {
if (empty($this->points)) {
$this->parseData();
}
$points = $this->points;
}
$length = count($points);
$firstIndex = 0;
$count = 0;
for ($i = 0; $i < $length; $i++) {
$count++;
if ($points[$i]["endOfContour"]) {
$path .= $this->getSVGPath($points, $firstIndex, $count);
$firstIndex = $i + 1;
$count = 0;
}
}
return $path;
}
protected function getSVGPath($points, $startIndex, $count) {
$offset = 0;
$path = "";
while ($offset < $count) {
$point = $points[$startIndex + $offset % $count];
$point_p1 = $points[$startIndex + ($offset + 1) % $count];
if ($offset == 0) {
$path .= "M{$point['x']},{$point['y']} ";
}
if ($point["onCurve"]) {
if ($point_p1["onCurve"]) {
$path .= "L{$point_p1['x']},{$point_p1['y']} ";
$offset++;
}
else {
$point_p2 = $points[$startIndex + ($offset + 2) % $count];
if ($point_p2["onCurve"]) {
$path .= "Q{$point_p1['x']},{$point_p1['y']},{$point_p2['x']},{$point_p2['y']} ";
}
else {
$path .= "Q{$point_p1['x']},{$point_p1['y']}," . $this->midValue($point_p1['x'], $point_p2['x']) . "," . $this->midValue($point_p1['y'], $point_p2['y']) . " ";
}
$offset += 2;
}
}
else {
if ($point_p1["onCurve"]) {
$path .= "Q{$point['x']},{$point['y']},{$point_p1['x']},{$point_p1['y']} ";
}
else {
$path .= "Q{$point['x']},{$point['y']}," . $this->midValue($point['x'], $point_p1['x']) . "," . $this->midValue($point['y'], $point_p1['y']) . " ";
}
$offset++;
}
}
$path .= "z ";
return $path;
}
function midValue($a, $b) {
return $a + ($b - $a) / 2;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib;
use Customily\Categories\Libraries\FontLib\TrueType\File;
/**
* Font header container.
*
* @package php-font-lib
*/
abstract class Header extends BinaryStream {
/**
* @var File
*/
protected $font;
protected $def = array();
public $data;
public function __construct(File $font) {
$this->font = $font;
}
public function encode() {
return $this->font->pack($this->def, $this->data);
}
public function parse() {
$this->data = $this->font->unpack($this->def);
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\OpenType;
/**
* Open Type font, the same as a TrueType one.
*
* @package php-font-lib
*/
class File extends \Customily\Categories\Libraries\FontLib\TrueType\File {
//
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\OpenType;
/**
* Open Type Table directory entry, the same as a TrueType one.
*
* @package php-font-lib
*/
class TableDirectoryEntry extends \Customily\Categories\Libraries\FontLib\TrueType\TableDirectoryEntry {
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table;
use Customily\Categories\Libraries\FontLib\TrueType\File;
use Customily\Categories\Libraries\FontLib\Font;
use Customily\Categories\Libraries\FontLib\BinaryStream;
/**
* Generic Font table directory entry.
*
* @package php-font-lib
*/
class DirectoryEntry extends BinaryStream {
/**
* @var File
*/
protected $font;
/**
* @var Table
*/
protected $font_table;
public $entryLength = 4;
public $tag;
public $checksum;
public $offset;
public $length;
protected $origF;
static function computeChecksum($data) {
$len = strlen($data);
$mod = $len % 4;
if ($mod) {
$data = str_pad($data, $len + (4 - $mod), "\0");
}
$len = strlen($data);
$hi = 0x0000;
$lo = 0x0000;
for ($i = 0; $i < $len; $i += 4) {
$hi += (ord($data[$i]) << 8) + ord($data[$i + 1]);
$lo += (ord($data[$i + 2]) << 8) + ord($data[$i + 3]);
$hi += $lo >> 16;
$lo = $lo & 0xFFFF;
$hi = $hi & 0xFFFF;
}
return ($hi << 8) + $lo;
}
function __construct(File $font) {
$this->font = $font;
$this->f = $font->f;
}
function parse() {
$this->tag = $this->font->read(4);
}
function open($filename, $mode = self::modeRead) {
// void
}
function setTable(Table $font_table) {
$this->font_table = $font_table;
}
function encode($entry_offset) {
Font::d("\n==== $this->tag ====");
//Font::d("Entry offset = $entry_offset");
$data = $this->font_table;
$font = $this->font;
$table_offset = $font->pos();
$this->offset = $table_offset;
$table_length = $data->encode();
$font->seek($table_offset);
$table_data = $font->read($table_length);
$font->seek($entry_offset);
$font->write($this->tag, 4);
$font->writeUInt32(self::computeChecksum($table_data));
$font->writeUInt32($table_offset);
$font->writeUInt32($table_length);
Font::d("Bytes written = $table_length");
$font->seek($table_offset + $table_length);
}
/**
* @return File
*/
function getFont() {
return $this->font;
}
function startRead() {
$this->font->seek($this->offset);
}
function endRead() {
//
}
function startWrite() {
$this->font->seek($this->offset);
}
function endWrite() {
//
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table;
use Customily\Categories\Libraries\FontLib\TrueType\File;
use Customily\Categories\Libraries\FontLib\Font;
use Customily\Categories\Libraries\FontLib\BinaryStream;
/**
* Generic font table.
*
* @package php-font-lib
*/
class Table extends BinaryStream {
/**
* @var DirectoryEntry
*/
protected $entry;
protected $def = array();
public $data;
final public function __construct(DirectoryEntry $entry) {
$this->entry = $entry;
$entry->setTable($this);
}
/**
* @return File
*/
public function getFont() {
return $this->entry->getFont();
}
protected function _encode() {
if (empty($this->data)) {
Font::d(" >> Table is empty");
return 0;
}
return $this->getFont()->pack($this->def, $this->data);
}
protected function _parse() {
$this->data = $this->getFont()->unpack($this->def);
}
protected function _parseRaw() {
$this->data = $this->getFont()->read($this->entry->length);
}
protected function _encodeRaw() {
return $this->getFont()->write($this->data, $this->entry->length);
}
public function toHTML() {
return "<pre>" . var_export($this->data, true) . "</pre>";
}
final public function encode() {
$this->entry->startWrite();
if (false && empty($this->def)) {
$length = $this->_encodeRaw();
}
else {
$length = $this->_encode();
}
$this->entry->endWrite();
return $length;
}
final public function parse() {
$this->entry->startRead();
if (false && empty($this->def)) {
$this->_parseRaw();
}
else {
$this->_parse();
}
$this->entry->endRead();
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
/**
* `cmap` font table.
*
* @package php-font-lib
*/
class cmap extends Table {
private static $header_format = array(
"version" => self::uint16,
"numberSubtables" => self::uint16,
);
private static $subtable_header_format = array(
"platformID" => self::uint16,
"platformSpecificID" => self::uint16,
"offset" => self::uint32,
);
private static $subtable_v4_format = array(
"length" => self::uint16,
"language" => self::uint16,
"segCountX2" => self::uint16,
"searchRange" => self::uint16,
"entrySelector" => self::uint16,
"rangeShift" => self::uint16,
);
private static $subtable_v12_format = array(
"length" => self::uint32,
"language" => self::uint32,
"ngroups" => self::uint32
);
protected function _parse() {
$font = $this->getFont();
$cmap_offset = $font->pos();
$data = $font->unpack(self::$header_format);
$subtables = array();
for ($i = 0; $i < $data["numberSubtables"]; $i++) {
$subtables[] = $font->unpack(self::$subtable_header_format);
}
$data["subtables"] = $subtables;
foreach ($data["subtables"] as $i => &$subtable) {
$font->seek($cmap_offset + $subtable["offset"]);
$subtable["format"] = $font->readUInt16();
// @todo Only CMAP version 4 and 12
if (($subtable["format"] != 4) && ($subtable["format"] != 12)) {
unset($data["subtables"][$i]);
$data["numberSubtables"]--;
continue;
}
if ($subtable["format"] == 12) {
$font->readUInt16();
$subtable += $font->unpack(self::$subtable_v12_format);
$glyphIndexArray = array();
$endCodes = array();
$startCodes = array();
for ($p = 0; $p < $subtable['ngroups']; $p++) {
$startCode = $startCodes[] = $font->readUInt32();
$endCode = $endCodes[] = $font->readUInt32();
$startGlyphCode = $font->readUInt32();
for ($c = $startCode; $c <= $endCode; $c++) {
$glyphIndexArray[$c] = $startGlyphCode;
$startGlyphCode++;
}
}
$subtable += array(
"startCode" => $startCodes,
"endCode" => $endCodes,
"glyphIndexArray" => $glyphIndexArray,
);
}
else if ($subtable["format"] == 4) {
$subtable += $font->unpack(self::$subtable_v4_format);
$segCount = $subtable["segCountX2"] / 2;
$subtable["segCount"] = $segCount;
$endCode = $font->readUInt16Many($segCount);
$font->readUInt16(); // reservedPad
$startCode = $font->readUInt16Many($segCount);
$idDelta = $font->readInt16Many($segCount);
$ro_start = $font->pos();
$idRangeOffset = $font->readUInt16Many($segCount);
$glyphIndexArray = array();
for ($i = 0; $i < $segCount; $i++) {
$c1 = $startCode[$i];
$c2 = $endCode[$i];
$d = $idDelta[$i];
$ro = $idRangeOffset[$i];
if ($ro > 0) {
$font->seek($subtable["offset"] + 2 * $i + $ro);
}
for ($c = $c1; $c <= $c2; $c++) {
if ($ro == 0) {
$gid = ($c + $d) & 0xFFFF;
}
else {
$offset = ($c - $c1) * 2 + $ro;
$offset = $ro_start + 2 * $i + $offset;
$font->seek($offset);
$gid = $font->readUInt16();
if ($gid != 0) {
$gid = ($gid + $d) & 0xFFFF;
}
}
if ($gid > 0) {
$glyphIndexArray[$c] = $gid;
}
}
}
$subtable += array(
"endCode" => $endCode,
"startCode" => $startCode,
"idDelta" => $idDelta,
"idRangeOffset" => $idRangeOffset,
"glyphIndexArray" => $glyphIndexArray,
);
}
}
$this->data = $data;
}
function _encode() {
$font = $this->getFont();
$subset = $font->getSubset();
$glyphIndexArray = $font->getUnicodeCharMap();
$newGlyphIndexArray = array();
foreach ($glyphIndexArray as $code => $gid) {
$new_gid = array_search($gid, $subset);
if ($new_gid !== false) {
$newGlyphIndexArray[$code] = $new_gid;
}
}
ksort($newGlyphIndexArray); // Sort by char code
$segments = array();
$i = -1;
$prevCode = 0xFFFF;
$prevGid = 0xFFFF;
foreach ($newGlyphIndexArray as $code => $gid) {
if (
$prevCode + 1 != $code ||
$prevGid + 1 != $gid
) {
$i++;
$segments[$i] = array();
}
$segments[$i][] = array($code, $gid);
$prevCode = $code;
$prevGid = $gid;
}
$segments[][] = array(0xFFFF, 0xFFFF);
$startCode = array();
$endCode = array();
$idDelta = array();
foreach ($segments as $codes) {
$start = reset($codes);
$end = end($codes);
$startCode[] = $start[0];
$endCode[] = $end[0];
$idDelta[] = $start[1] - $start[0];
}
$segCount = count($startCode);
$idRangeOffset = array_fill(0, $segCount, 0);
$searchRange = 1;
$entrySelector = 0;
while ($searchRange * 2 <= $segCount) {
$searchRange *= 2;
$entrySelector++;
}
$searchRange *= 2;
$rangeShift = $segCount * 2 - $searchRange;
$subtables = array(
array(
// header
"platformID" => 3, // Unicode
"platformSpecificID" => 1,
"offset" => null,
// subtable
"format" => 4,
"length" => null,
"language" => 0,
"segCount" => $segCount,
"segCountX2" => $segCount * 2,
"searchRange" => $searchRange,
"entrySelector" => $entrySelector,
"rangeShift" => $rangeShift,
"startCode" => $startCode,
"endCode" => $endCode,
"idDelta" => $idDelta,
"idRangeOffset" => $idRangeOffset,
"glyphIndexArray" => $newGlyphIndexArray,
)
);
$data = array(
"version" => 0,
"numberSubtables" => count($subtables),
"subtables" => $subtables,
);
$length = $font->pack(self::$header_format, $data);
$subtable_headers_size = $data["numberSubtables"] * 8; // size of self::$subtable_header_format
$subtable_headers_offset = $font->pos();
$length += $font->write(str_repeat("\0", $subtable_headers_size), $subtable_headers_size);
// write subtables data
foreach ($data["subtables"] as $i => $subtable) {
$length_before = $length;
$data["subtables"][$i]["offset"] = $length;
$length += $font->writeUInt16($subtable["format"]);
$before_subheader = $font->pos();
$length += $font->pack(self::$subtable_v4_format, $subtable);
$segCount = $subtable["segCount"];
$length += $font->w(array(self::uint16, $segCount), $subtable["endCode"]);
$length += $font->writeUInt16(0); // reservedPad
$length += $font->w(array(self::uint16, $segCount), $subtable["startCode"]);
$length += $font->w(array(self::int16, $segCount), $subtable["idDelta"]);
$length += $font->w(array(self::uint16, $segCount), $subtable["idRangeOffset"]);
$length += $font->w(array(self::uint16, $segCount), array_values($subtable["glyphIndexArray"]));
$after_subtable = $font->pos();
$subtable["length"] = $length - $length_before;
$font->seek($before_subheader);
$length += $font->pack(self::$subtable_v4_format, $subtable);
$font->seek($after_subtable);
}
// write subtables headers
$font->seek($subtable_headers_offset);
foreach ($data["subtables"] as $subtable) {
$font->pack(self::$subtable_header_format, $subtable);
}
return $length;
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
use Customily\Categories\Libraries\FontLib\Glyph\Outline;
use Customily\Categories\Libraries\FontLib\Glyph\OutlineSimple;
/**
* `glyf` font table.
*
* @package php-font-lib
* @property Outline[] $data
*/
class glyf extends Table {
protected function _parse() {
$font = $this->getFont();
$offset = $font->pos();
$loca = $font->getData("loca");
$real_loca = array_slice($loca, 0, -1); // Not the last dummy loca entry
$data = array();
foreach ($real_loca as $gid => $location) {
$_offset = $offset + $loca[$gid];
$_size = $loca[$gid + 1] - $loca[$gid];
$data[$gid] = Outline::init($this, $_offset, $_size, $font);
}
$this->data = $data;
}
public function getGlyphIDs($gids = array()) {
$glyphIDs = array();
foreach ($gids as $_gid) {
$_glyph = $this->data[$_gid];
$glyphIDs = array_merge($glyphIDs, $_glyph->getGlyphIDs());
}
return array_unique(array_merge($gids, $glyphIDs));
}
public function toHTML() {
$max = 160;
$font = $this->getFont();
$head = $font->getData("head");
$head_json = json_encode($head);
$os2 = $font->getData("OS/2");
$os2_json = json_encode($os2);
$hmtx = $font->getData("hmtx");
$hmtx_json = json_encode($hmtx);
$names = $font->getData("post", "names");
$glyphIndexArray = array_flip($font->getUnicodeCharMap());
$width = (abs($head["xMin"]) + $head["xMax"]);
$height = (abs($head["yMin"]) + $head["yMax"]);
$ratio = 1;
if ($width > $max || $height > $max) {
$ratio = max($width, $height) / $max;
$width = round($width / $ratio);
$height = round($height / $ratio);
}
$n = 500;
$s = "<h3>" . "Only the first $n simple glyphs are shown (" . count($this->data) . " total)
<div class='glyph-view simple'>Simple glyph</div>
<div class='glyph-view composite'>Composite glyph</div>
Zoom: <input type='range' value='100' max='400' onchange='Glyph.resize(this.value)' />
</h3>
<script>
Glyph.ratio = $ratio;
Glyph.head = $head_json;
Glyph.os2 = $os2_json;
Glyph.hmtx = $hmtx_json;
Glyph.width = $width;
Glyph.height = $height;
</script>";
foreach ($this->data as $g => $glyph) {
if ($n-- <= 0) {
break;
}
$glyph->parseData();
$shape = array(
"SVGContours" => $glyph->getSVGContours(),
"xMin" => $glyph->xMin,
"yMin" => $glyph->yMin,
"xMax" => $glyph->xMax,
"yMax" => $glyph->yMax,
);
$shape_json = json_encode($shape);
$type = ($glyph instanceof OutlineSimple ? "simple" : "composite");
$char = isset($glyphIndexArray[$g]) ? $glyphIndexArray[$g] : 0;
$name = isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $char);
$char = $char ? "&#{$glyphIndexArray[$g]};" : "";
$s .= "<div class='glyph-view $type' id='glyph-$g'>
<span class='glyph-id'>$g</span>
<span class='char'>$char</span>
<span class='char-name'>$name</span>
";
if ($type == "composite") {
foreach ($glyph->getGlyphIDs() as $_id) {
$s .= "<a href='#glyph-$_id' class='glyph-component-id'>$_id</a> ";
}
}
$s .= "<br />
<canvas width='$width' height='$height' id='glyph-canvas-$g'></canvas>
</div>
<script>Glyph.glyphs.push([$g,$shape_json]);</script>";
}
return $s;
}
protected function _encode() {
$font = $this->getFont();
$subset = $font->getSubset();
$data = $this->data;
$loca = array();
$length = 0;
foreach ($subset as $gid) {
$loca[] = $length;
$length += $data[$gid]->encode();
}
$loca[] = $length; // dummy loca
$font->getTableObject("loca")->data = $loca;
return $length;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
use Exception;
/**
* `head` font table.
*
* @package php-font-lib
*/
class head extends Table {
protected $def = array(
"tableVersion" => self::Fixed,
"fontRevision" => self::Fixed,
"checkSumAdjustment" => self::uint32,
"magicNumber" => self::uint32,
"flags" => self::uint16,
"unitsPerEm" => self::uint16,
"created" => self::longDateTime,
"modified" => self::longDateTime,
"xMin" => self::FWord,
"yMin" => self::FWord,
"xMax" => self::FWord,
"yMax" => self::FWord,
"macStyle" => self::uint16,
"lowestRecPPEM" => self::uint16,
"fontDirectionHint" => self::int16,
"indexToLocFormat" => self::int16,
"glyphDataFormat" => self::int16,
);
protected function _parse() {
parent::_parse();
if ($this->data["magicNumber"] != 0x5F0F3CF5) {
throw new Exception("Incorrect magic number (" . dechex($this->data["magicNumber"]) . ")");
}
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
/**
* `hhea` font table.
*
* @package php-font-lib
*/
class hhea extends Table {
protected $def = array(
"version" => self::Fixed,
"ascent" => self::FWord,
"descent" => self::FWord,
"lineGap" => self::FWord,
"advanceWidthMax" => self::uFWord,
"minLeftSideBearing" => self::FWord,
"minRightSideBearing" => self::FWord,
"xMaxExtent" => self::FWord,
"caretSlopeRise" => self::int16,
"caretSlopeRun" => self::int16,
"caretOffset" => self::FWord,
self::int16,
self::int16,
self::int16,
self::int16,
"metricDataFormat" => self::int16,
"numOfLongHorMetrics" => self::uint16,
);
function _encode() {
$font = $this->getFont();
$this->data["numOfLongHorMetrics"] = count($font->getSubset());
return parent::_encode();
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
/**
* `hmtx` font table.
*
* @package php-font-lib
*/
class hmtx extends Table {
protected function _parse() {
$font = $this->getFont();
$offset = $font->pos();
$numOfLongHorMetrics = $font->getData("hhea", "numOfLongHorMetrics");
$numGlyphs = $font->getData("maxp", "numGlyphs");
$font->seek($offset);
$data = array();
$metrics = $font->readUInt16Many($numOfLongHorMetrics * 2);
for ($gid = 0, $mid = 0; $gid < $numOfLongHorMetrics; $gid++) {
$advanceWidth = isset($metrics[$mid]) ? $metrics[$mid] : 0;
$mid += 1;
$leftSideBearing = isset($metrics[$mid]) ? $metrics[$mid] : 0;
$mid += 1;
$data[$gid] = array($advanceWidth, $leftSideBearing);
}
if ($numOfLongHorMetrics < $numGlyphs) {
$lastWidth = end($data);
$data = array_pad($data, $numGlyphs, $lastWidth);
}
$this->data = $data;
}
protected function _encode() {
$font = $this->getFont();
$subset = $font->getSubset();
$data = $this->data;
$length = 0;
foreach ($subset as $gid) {
$length += $font->writeUInt16($data[$gid][0]);
$length += $font->writeUInt16($data[$gid][1]);
}
return $length;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
/**
* `kern` font table.
*
* @package php-font-lib
*/
class kern extends Table {
protected function _parse() {
$font = $this->getFont();
$data = $font->unpack(array(
"version" => self::uint16,
"nTables" => self::uint16,
// only the first subtable will be parsed
"subtableVersion" => self::uint16,
"length" => self::uint16,
"coverage" => self::uint16,
));
$data["format"] = ($data["coverage"] >> 8);
$subtable = array();
switch ($data["format"]) {
case 0:
$subtable = $font->unpack(array(
"nPairs" => self::uint16,
"searchRange" => self::uint16,
"entrySelector" => self::uint16,
"rangeShift" => self::uint16,
));
$pairs = array();
$tree = array();
$values = $font->readUInt16Many($subtable["nPairs"] * 3);
for ($i = 0, $idx = 0; $i < $subtable["nPairs"]; $i++) {
$left = $values[$idx++];
$right = $values[$idx++];
$value = $values[$idx++];
if ($value >= 0x8000) {
$value -= 0x10000;
}
$pairs[] = array(
"left" => $left,
"right" => $right,
"value" => $value,
);
$tree[$left][$right] = $value;
}
//$subtable["pairs"] = $pairs;
$subtable["tree"] = $tree;
break;
case 1:
case 2:
case 3:
break;
}
$data["subtable"] = $subtable;
$this->data = $data;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
/**
* `loca` font table.
*
* @package php-font-lib
*/
class loca extends Table {
protected function _parse() {
$font = $this->getFont();
$offset = $font->pos();
$indexToLocFormat = $font->getData("head", "indexToLocFormat");
$numGlyphs = $font->getData("maxp", "numGlyphs");
$font->seek($offset);
$data = array();
// 2 bytes
if ($indexToLocFormat == 0) {
$d = $font->read(($numGlyphs + 1) * 2);
$loc = unpack("n*", $d);
for ($i = 0; $i <= $numGlyphs; $i++) {
$data[] = isset($loc[$i + 1]) ? $loc[$i + 1] * 2 : 0;
}
}
// 4 bytes
else {
if ($indexToLocFormat == 1) {
$d = $font->read(($numGlyphs + 1) * 4);
$loc = unpack("N*", $d);
for ($i = 0; $i <= $numGlyphs; $i++) {
$data[] = isset($loc[$i + 1]) ? $loc[$i + 1] : 0;
}
}
}
$this->data = $data;
}
function _encode() {
$font = $this->getFont();
$data = $this->data;
$indexToLocFormat = $font->getData("head", "indexToLocFormat");
$numGlyphs = $font->getData("maxp", "numGlyphs");
$length = 0;
// 2 bytes
if ($indexToLocFormat == 0) {
for ($i = 0; $i <= $numGlyphs; $i++) {
$length += $font->writeUInt16($data[$i] / 2);
}
}
// 4 bytes
else {
if ($indexToLocFormat == 1) {
for ($i = 0; $i <= $numGlyphs; $i++) {
$length += $font->writeUInt32($data[$i]);
}
}
}
return $length;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
/**
* `maxp` font table.
*
* @package php-font-lib
*/
class maxp extends Table {
protected $def = array(
"version" => self::Fixed,
"numGlyphs" => self::uint16,
"maxPoints" => self::uint16,
"maxContours" => self::uint16,
"maxComponentPoints" => self::uint16,
"maxComponentContours" => self::uint16,
"maxZones" => self::uint16,
"maxTwilightPoints" => self::uint16,
"maxStorage" => self::uint16,
"maxFunctionDefs" => self::uint16,
"maxInstructionDefs" => self::uint16,
"maxStackElements" => self::uint16,
"maxSizeOfInstructions" => self::uint16,
"maxComponentElements" => self::uint16,
"maxComponentDepth" => self::uint16,
);
function _encode() {
$font = $this->getFont();
$this->data["numGlyphs"] = count($font->getSubset());
return parent::_encode();
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
use Customily\Categories\Libraries\FontLib\Font;
/**
* `name` font table.
*
* @package php-font-lib
*/
class name extends Table {
private static $header_format = array(
"format" => self::uint16,
"count" => self::uint16,
"stringOffset" => self::uint16,
);
const NAME_COPYRIGHT = 0;
const NAME_NAME = 1;
const NAME_SUBFAMILY = 2;
const NAME_SUBFAMILY_ID = 3;
const NAME_FULL_NAME = 4;
const NAME_VERSION = 5;
const NAME_POSTSCRIPT_NAME = 6;
const NAME_TRADEMARK = 7;
const NAME_MANUFACTURER = 8;
const NAME_DESIGNER = 9;
const NAME_DESCRIPTION = 10;
const NAME_VENDOR_URL = 11;
const NAME_DESIGNER_URL = 12;
const NAME_LICENSE = 13;
const NAME_LICENSE_URL = 14;
const NAME_PREFERRE_FAMILY = 16;
const NAME_PREFERRE_SUBFAMILY = 17;
const NAME_COMPAT_FULL_NAME = 18;
const NAME_SAMPLE_TEXT = 19;
static $nameIdCodes = array(
0 => "Copyright",
1 => "FontName",
2 => "FontSubfamily",
3 => "UniqueID",
4 => "FullName",
5 => "Version",
6 => "PostScriptName",
7 => "Trademark",
8 => "Manufacturer",
9 => "Designer",
10 => "Description",
11 => "FontVendorURL",
12 => "FontDesignerURL",
13 => "LicenseDescription",
14 => "LicenseURL",
// 15
16 => "PreferredFamily",
17 => "PreferredSubfamily",
18 => "CompatibleFullName",
19 => "SampleText",
);
static $platforms = array(
0 => "Unicode",
1 => "Macintosh",
// 2 => Reserved
3 => "Microsoft",
);
static $platformSpecific = array(
// Unicode
0 => array(
0 => "Default semantics",
1 => "Version 1.1 semantics",
2 => "ISO 10646 1993 semantics (deprecated)",
3 => "Unicode 2.0 or later semantics",
),
// Macintosh
1 => array(
0 => "Roman",
1 => "Japanese",
2 => "Traditional Chinese",
3 => "Korean",
4 => "Arabic",
5 => "Hebrew",
6 => "Greek",
7 => "Russian",
8 => "RSymbol",
9 => "Devanagari",
10 => "Gurmukhi",
11 => "Gujarati",
12 => "Oriya",
13 => "Bengali",
14 => "Tamil",
15 => "Telugu",
16 => "Kannada",
17 => "Malayalam",
18 => "Sinhalese",
19 => "Burmese",
20 => "Khmer",
21 => "Thai",
22 => "Laotian",
23 => "Georgian",
24 => "Armenian",
25 => "Simplified Chinese",
26 => "Tibetan",
27 => "Mongolian",
28 => "Geez",
29 => "Slavic",
30 => "Vietnamese",
31 => "Sindhi",
),
// Microsoft
3 => array(
0 => "Symbol",
1 => "Unicode BMP (UCS-2)",
2 => "ShiftJIS",
3 => "PRC",
4 => "Big5",
5 => "Wansung",
6 => "Johab",
// 7 => Reserved
// 8 => Reserved
// 9 => Reserved
10 => "Unicode UCS-4",
),
);
protected function _parse() {
$font = $this->getFont();
$tableOffset = $font->pos();
$data = $font->unpack(self::$header_format);
$records = array();
for ($i = 0; $i < $data["count"]; $i++) {
$record = new nameRecord();
$record_data = $font->unpack(nameRecord::$format);
$record->map($record_data);
$records[] = $record;
}
$names = array();
foreach ($records as $record) {
$font->seek($tableOffset + $data["stringOffset"] + $record->offset);
$s = $font->read($record->length);
$record->string = Font::UTF16ToUTF8($s);
$names[$record->nameID] = $record;
}
$data["records"] = $names;
$this->data = $data;
}
protected function _encode() {
$font = $this->getFont();
/** @var nameRecord[] $records */
$records = $this->data["records"];
$count_records = count($records);
$this->data["count"] = $count_records;
$this->data["stringOffset"] = 6 + $count_records * 12; // 6 => uint16 * 3, 12 => sizeof self::$record_format
$length = $font->pack(self::$header_format, $this->data);
$offset = 0;
foreach ($records as $record) {
$record->length = mb_strlen($record->getUTF16(), "8bit");
$record->offset = $offset;
$offset += $record->length;
$length += $font->pack(nameRecord::$format, (array)$record);
}
foreach ($records as $record) {
$str = $record->getUTF16();
$length += $font->write($str, mb_strlen($str, "8bit"));
}
return $length;
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Font;
use Customily\Categories\Libraries\FontLib\BinaryStream;
/**
* Font table name record.
*
* @package php-font-lib
*/
class nameRecord extends BinaryStream {
public $platformID;
public $platformSpecificID;
public $languageID;
public $nameID;
public $length;
public $offset;
public $string;
public static $format = array(
"platformID" => self::uint16,
"platformSpecificID" => self::uint16,
"languageID" => self::uint16,
"nameID" => self::uint16,
"length" => self::uint16,
"offset" => self::uint16,
);
public function map($data) {
foreach ($data as $key => $value) {
$this->$key = $value;
}
}
public function getUTF8() {
return $this->string;
}
public function getUTF16() {
return Font::UTF8ToUTF16($this->string);
}
function __toString() {
return $this->string;
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
/**
* `OS/2` font table.
*
* @package php-font-lib
*/
class os2 extends Table {
protected $def = array(
"version" => self::uint16,
"xAvgCharWidth" => self::int16,
"usWeightClass" => self::uint16,
"usWidthClass" => self::uint16,
"fsType" => self::int16,
"ySubscriptXSize" => self::int16,
"ySubscriptYSize" => self::int16,
"ySubscriptXOffset" => self::int16,
"ySubscriptYOffset" => self::int16,
"ySuperscriptXSize" => self::int16,
"ySuperscriptYSize" => self::int16,
"ySuperscriptXOffset" => self::int16,
"ySuperscriptYOffset" => self::int16,
"yStrikeoutSize" => self::int16,
"yStrikeoutPosition" => self::int16,
"sFamilyClass" => self::int16,
"panose" => array(self::uint8, 10),
"ulCharRange" => array(self::uint32, 4),
"achVendID" => array(self::char, 4),
"fsSelection" => self::uint16,
"fsFirstCharIndex" => self::uint16,
"fsLastCharIndex" => self::uint16,
"typoAscender" => self::int16,
"typoDescender" => self::int16,
"typoLineGap" => self::int16,
"winAscent" => self::int16,
"winDescent" => self::int16,
);
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\Table\Type;
use Customily\Categories\Libraries\FontLib\Table\Table;
use Customily\Categories\Libraries\FontLib\TrueType\File;
/**
* `post` font table.
*
* @package php-font-lib
*/
class post extends Table {
protected $def = array(
"format" => self::Fixed,
"italicAngle" => self::Fixed,
"underlinePosition" => self::FWord,
"underlineThickness" => self::FWord,
"isFixedPitch" => self::uint32,
"minMemType42" => self::uint32,
"maxMemType42" => self::uint32,
"minMemType1" => self::uint32,
"maxMemType1" => self::uint32,
);
protected function _parse() {
$font = $this->getFont();
$data = $font->unpack($this->def);
$names = array();
switch ($data["format"]) {
case 1:
$names = File::$macCharNames;
break;
case 2:
$data["numberOfGlyphs"] = $font->readUInt16();
$glyphNameIndex = $font->readUInt16Many($data["numberOfGlyphs"]);
$data["glyphNameIndex"] = $glyphNameIndex;
$namesPascal = array();
for ($i = 0; $i < $data["numberOfGlyphs"]; $i++) {
$len = $font->readUInt8();
$namesPascal[] = $font->read($len);
}
foreach ($glyphNameIndex as $g => $index) {
if ($index < 258) {
$names[$g] = File::$macCharNames[$index];
}
else {
$names[$g] = $namesPascal[$index - 258];
}
}
break;
case 2.5:
// TODO
break;
case 3:
// nothing
break;
case 4:
// TODO
break;
}
$data["names"] = $names;
$this->data = $data;
}
function _encode() {
$font = $this->getFont();
$data = $this->data;
$data["format"] = 3;
$length = $font->pack($this->def, $data);
return $length;
/*
$subset = $font->getSubset();
switch($data["format"]) {
case 1:
// nothing to do
break;
case 2:
$old_names = $data["names"];
$glyphNameIndex = range(0, count($subset));
$names = array();
foreach($subset as $gid) {
$names[] = $data["names"][$data["glyphNameIndex"][$gid]];
}
$numberOfGlyphs = count($names);
$length += $font->writeUInt16($numberOfGlyphs);
foreach($glyphNameIndex as $gni) {
$length += $font->writeUInt16($gni);
}
//$names = array_slice($names, 257);
foreach($names as $name) {
$len = strlen($name);
$length += $font->writeUInt8($len);
$length += $font->write($name, $len);
}
break;
case 2.5:
// TODO
break;
case 3:
// nothing
break;
case 4:
// TODO
break;
}
return $length;*/
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\TrueType;
use Countable;
use Customily\Categories\Libraries\FontLib\BinaryStream;
use Iterator;
use OutOfBoundsException;
/**
* TrueType collection font file.
*
* @package php-font-lib
*/
class Collection extends BinaryStream implements Iterator, Countable {
/**
* Current iterator position.
*
* @var integer
*/
private $position = 0;
protected $collectionOffsets = array();
protected $collection = array();
protected $version;
protected $numFonts;
function parse() {
if (isset($this->numFonts)) {
return;
}
$this->read(4); // tag name
$this->version = $this->readFixed();
$this->numFonts = $this->readUInt32();
for ($i = 0; $i < $this->numFonts; $i++) {
$this->collectionOffsets[] = $this->readUInt32();
}
}
function getFont($fontId) {
$this->parse();
if (!isset($this->collectionOffsets[$fontId])) {
throw new OutOfBoundsException();
}
if (isset($this->collection[$fontId])) {
return $this->collection[$fontId];
}
$font = new File();
$font->f = $this->f;
$font->setTableOffset($this->collectionOffsets[$fontId]);
return $this->collection[$fontId] = $font;
}
#[\ReturnTypeWillChange]
function current() {
return $this->getFont($this->position);
}
#[\ReturnTypeWillChange]
function key() {
return $this->position;
}
#[\ReturnTypeWillChange]
function next() {
return ++$this->position;
}
#[\ReturnTypeWillChange]
function rewind() {
$this->position = 0;
}
#[\ReturnTypeWillChange]
function valid() {
$this->parse();
return isset($this->collectionOffsets[$this->position]);
}
#[\ReturnTypeWillChange]
function count() {
$this->parse();
return $this->numFonts;
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\TrueType;
use Customily\Categories\Libraries\FontLib\AdobeFontMetrics;
use Customily\Categories\Libraries\FontLib\Font;
use Customily\Categories\Libraries\FontLib\BinaryStream;
use Customily\Categories\Libraries\FontLib\Table\Table;
use Customily\Categories\Libraries\FontLib\Table\DirectoryEntry;
use Customily\Categories\Libraries\FontLib\Table\Type\glyf;
use Customily\Categories\Libraries\FontLib\Table\Type\name;
use Customily\Categories\Libraries\FontLib\Table\Type\nameRecord;
/**
* TrueType font file.
*
* @package php-font-lib
*/
class File extends BinaryStream {
/**
* @var Header
*/
public $header = array();
private $tableOffset = 0; // Used for TTC
private static $raw = false;
protected $directory = array();
protected $data = array();
protected $glyph_subset = array();
public $glyph_all = array();
static $macCharNames = array(
".notdef", ".null", "CR",
"space", "exclam", "quotedbl", "numbersign",
"dollar", "percent", "ampersand", "quotesingle",
"parenleft", "parenright", "asterisk", "plus",
"comma", "hyphen", "period", "slash",
"zero", "one", "two", "three",
"four", "five", "six", "seven",
"eight", "nine", "colon", "semicolon",
"less", "equal", "greater", "question",
"at", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "bracketleft",
"backslash", "bracketright", "asciicircum", "underscore",
"grave", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w",
"x", "y", "z", "braceleft",
"bar", "braceright", "asciitilde", "Adieresis",
"Aring", "Ccedilla", "Eacute", "Ntilde",
"Odieresis", "Udieresis", "aacute", "agrave",
"acircumflex", "adieresis", "atilde", "aring",
"ccedilla", "eacute", "egrave", "ecircumflex",
"edieresis", "iacute", "igrave", "icircumflex",
"idieresis", "ntilde", "oacute", "ograve",
"ocircumflex", "odieresis", "otilde", "uacute",
"ugrave", "ucircumflex", "udieresis", "dagger",
"degree", "cent", "sterling", "section",
"bullet", "paragraph", "germandbls", "registered",
"copyright", "trademark", "acute", "dieresis",
"notequal", "AE", "Oslash", "infinity",
"plusminus", "lessequal", "greaterequal", "yen",
"mu", "partialdiff", "summation", "product",
"pi", "integral", "ordfeminine", "ordmasculine",
"Omega", "ae", "oslash", "questiondown",
"exclamdown", "logicalnot", "radical", "florin",
"approxequal", "increment", "guillemotleft", "guillemotright",
"ellipsis", "nbspace", "Agrave", "Atilde",
"Otilde", "OE", "oe", "endash",
"emdash", "quotedblleft", "quotedblright", "quoteleft",
"quoteright", "divide", "lozenge", "ydieresis",
"Ydieresis", "fraction", "currency", "guilsinglleft",
"guilsinglright", "fi", "fl", "daggerdbl",
"periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
"Acircumflex", "Ecircumflex", "Aacute", "Edieresis",
"Egrave", "Iacute", "Icircumflex", "Idieresis",
"Igrave", "Oacute", "Ocircumflex", "applelogo",
"Ograve", "Uacute", "Ucircumflex", "Ugrave",
"dotlessi", "circumflex", "tilde", "macron",
"breve", "dotaccent", "ring", "cedilla",
"hungarumlaut", "ogonek", "caron", "Lslash",
"lslash", "Scaron", "scaron", "Zcaron",
"zcaron", "brokenbar", "Eth", "eth",
"Yacute", "yacute", "Thorn", "thorn",
"minus", "multiply", "onesuperior", "twosuperior",
"threesuperior", "onehalf", "onequarter", "threequarters",
"franc", "Gbreve", "gbreve", "Idot",
"Scedilla", "scedilla", "Cacute", "cacute",
"Ccaron", "ccaron", "dmacron"
);
function getTable() {
$this->parseTableEntries();
return $this->directory;
}
function setTableOffset($offset) {
$this->tableOffset = $offset;
}
function parse() {
$this->parseTableEntries();
$this->data = array();
foreach ($this->directory as $tag => $table) {
if (empty($this->data[$tag])) {
$this->readTable($tag);
}
}
}
function utf8toUnicode($str) {
$len = strlen($str);
$out = array();
for ($i = 0; $i < $len; $i++) {
$uni = -1;
$h = ord($str[$i]);
if ($h <= 0x7F) {
$uni = $h;
}
elseif ($h >= 0xC2) {
if (($h <= 0xDF) && ($i < $len - 1)) {
$uni = ($h & 0x1F) << 6 | (ord($str[++$i]) & 0x3F);
}
elseif (($h <= 0xEF) && ($i < $len - 2)) {
$uni = ($h & 0x0F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
}
elseif (($h <= 0xF4) && ($i < $len - 3)) {
$uni = ($h & 0x0F) << 18 | (ord($str[++$i]) & 0x3F) << 12 | (ord($str[++$i]) & 0x3F) << 6 | (ord($str[++$i]) & 0x3F);
}
}
if ($uni >= 0) {
$out[] = $uni;
}
}
return $out;
}
function getUnicodeCharMap() {
$subtable = null;
foreach ($this->getData("cmap", "subtables") as $_subtable) {
if ($_subtable["platformID"] == 0 || $_subtable["platformID"] == 3 && $_subtable["platformSpecificID"] == 1) {
$subtable = $_subtable;
break;
}
}
if ($subtable) {
return $subtable["glyphIndexArray"];
}
return null;
}
function setSubset($subset) {
if (!is_array($subset)) {
$subset = $this->utf8toUnicode($subset);
}
$subset = array_unique($subset);
$glyphIndexArray = $this->getUnicodeCharMap();
if (!$glyphIndexArray) {
return;
}
$gids = array(
0, // .notdef
1, // .null
);
foreach ($subset as $code) {
if (!isset($glyphIndexArray[$code])) {
continue;
}
$gid = $glyphIndexArray[$code];
$gids[$gid] = $gid;
}
/** @var glyf $glyf */
$glyf = $this->getTableObject("glyf");
$gids = $glyf->getGlyphIDs($gids);
sort($gids);
$this->glyph_subset = $gids;
$this->glyph_all = array_values($glyphIndexArray); // FIXME
}
function getSubset() {
if (empty($this->glyph_subset)) {
return $this->glyph_all;
}
return $this->glyph_subset;
}
function encode($tags = array()) {
if (!self::$raw) {
$tags = array_merge(array("head", "hhea", "cmap", "hmtx", "maxp", "glyf", "loca", "name", "post"), $tags);
}
else {
$tags = array_keys($this->directory);
}
$num_tables = count($tags);
$n = 16; // @todo
Font::d("Tables : " . implode(", ", $tags));
/** @var DirectoryEntry[] $entries */
$entries = array();
foreach ($tags as $tag) {
if (!isset($this->directory[$tag])) {
Font::d(" >> '$tag' table doesn't exist");
continue;
}
$entries[$tag] = $this->directory[$tag];
}
$this->header->data["numTables"] = $num_tables;
$this->header->encode();
$directory_offset = $this->pos();
$offset = $directory_offset + $num_tables * $n;
$this->seek($offset);
$i = 0;
foreach ($entries as $entry) {
$entry->encode($directory_offset + $i * $n);
$i++;
}
}
function parseHeader() {
if (!empty($this->header)) {
return;
}
$this->seek($this->tableOffset);
$this->header = new Header($this);
$this->header->parse();
}
function getFontType(){
$class_parts = explode("\\", get_class($this));
return $class_parts[4];
}
function parseTableEntries() {
$this->parseHeader();
if (!empty($this->directory)) {
return;
}
if (empty($this->header->data["numTables"])) {
return;
}
$type = $this->getFontType();
$class = "Customily\\Categories\\Libraries\\FontLib\\$type\\TableDirectoryEntry";
for ($i = 0; $i < $this->header->data["numTables"]; $i++) {
/** @var TableDirectoryEntry $entry */
$entry = new $class($this);
$entry->parse();
$this->directory[$entry->tag] = $entry;
}
}
function normalizeFUnit($value, $base = 1000) {
return round($value * ($base / $this->getData("head", "unitsPerEm")));
}
protected function readTable($tag) {
$this->parseTableEntries();
if (!self::$raw) {
$name_canon = preg_replace("/[^a-z0-9]/", "", strtolower($tag));
$class = "Customily\\Categories\\Libraries\\FontLib\\Table\\Type\\$name_canon";
if (!isset($this->directory[$tag]) || !@class_exists($class)) {
return;
}
}
else {
$class = "Customily\\Categories\\Libraries\\FontLib\\Table\\Table";
}
/** @var Table $table */
$table = new $class($this->directory[$tag]);
$table->parse();
$this->data[$tag] = $table;
}
/**
* @param $name
*
* @return Table
*/
public function getTableObject($name) {
return $this->data[$name];
}
public function setTableObject($name, Table $data) {
$this->data[$name] = $data;
}
public function getData($name, $key = null) {
$this->parseTableEntries();
if (empty($this->data[$name])) {
$this->readTable($name);
}
if (!isset($this->data[$name])) {
return null;
}
if (!$key) {
return $this->data[$name]->data;
}
else {
return $this->data[$name]->data[$key];
}
}
function addDirectoryEntry(DirectoryEntry $entry) {
$this->directory[$entry->tag] = $entry;
}
function saveAdobeFontMetrics($file, $encoding = null) {
$afm = new AdobeFontMetrics($this);
$afm->write($file, $encoding);
}
/**
* Get a specific name table string value from its ID
*
* @param int $nameID The name ID
*
* @return string|null
*/
function getNameTableString($nameID) {
/** @var nameRecord[] $records */
$records = $this->getData("name", "records");
if (!isset($records[$nameID])) {
return null;
}
return $records[$nameID]->string;
}
/**
* Get font copyright
*
* @return string|null
*/
function getFontCopyright() {
return $this->getNameTableString(name::NAME_COPYRIGHT);
}
/**
* Get font name
*
* @return string|null
*/
function getFontName() {
return $this->getNameTableString(name::NAME_NAME);
}
/**
* Get font subfamily
*
* @return string|null
*/
function getFontSubfamily() {
return $this->getNameTableString(name::NAME_SUBFAMILY);
}
/**
* Get font subfamily ID
*
* @return string|null
*/
function getFontSubfamilyID() {
return $this->getNameTableString(name::NAME_SUBFAMILY_ID);
}
/**
* Get font full name
*
* @return string|null
*/
function getFontFullName() {
return $this->getNameTableString(name::NAME_FULL_NAME);
}
/**
* Get font version
*
* @return string|null
*/
function getFontVersion() {
return $this->getNameTableString(name::NAME_VERSION);
}
/**
* Get font weight
*
* @return string|null
*/
function getFontWeight() {
return $this->getTableObject("OS/2")->data["usWeightClass"];
}
/**
* Get font Postscript name
*
* @return string|null
*/
function getFontPostscriptName() {
return $this->getNameTableString(name::NAME_POSTSCRIPT_NAME);
}
function reduce() {
$names_to_keep = array(
name::NAME_COPYRIGHT,
name::NAME_NAME,
name::NAME_SUBFAMILY,
name::NAME_SUBFAMILY_ID,
name::NAME_FULL_NAME,
name::NAME_VERSION,
name::NAME_POSTSCRIPT_NAME,
);
foreach ($this->data["name"]->data["records"] as $id => $rec) {
if (!in_array($id, $names_to_keep)) {
unset($this->data["name"]->data["records"][$id]);
}
}
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\TrueType;
/**
* TrueType font file header.
*
* @package php-font-lib
*/
class Header extends \Customily\Categories\Libraries\FontLib\Header {
protected $def = array(
"format" => self::uint32,
"numTables" => self::uint16,
"searchRange" => self::uint16,
"entrySelector" => self::uint16,
"rangeShift" => self::uint16,
);
public function parse() {
parent::parse();
$format = $this->data["format"];
$this->data["formatText"] = $this->convertUInt32ToStr($format);
}
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\TrueType;
use Customily\Categories\Libraries\FontLib\Table\DirectoryEntry;
/**
* TrueType table directory entry.
*
* @package php-font-lib
*/
class TableDirectoryEntry extends DirectoryEntry {
function __construct(File $font) {
parent::__construct($font);
}
function parse() {
parent::parse();
$font = $this->font;
$this->checksum = $font->readUInt32();
$this->offset = $font->readUInt32();
$this->length = $font->readUInt32();
$this->entryLength += 12;
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\WOFF;
use Customily\Categories\Libraries\FontLib\Table\DirectoryEntry;
/**
* WOFF font file.
*
* @package php-font-lib
*
* @property TableDirectoryEntry[] $directory
*/
class File extends \Customily\Categories\Libraries\FontLib\TrueType\File {
function parseHeader() {
if (!empty($this->header)) {
return;
}
$this->header = new Header($this);
$this->header->parse();
}
public function load($file) {
parent::load($file);
$this->parseTableEntries();
$dataOffset = $this->pos() + count($this->directory) * 20;
$fw = $this->getTempFile(false);
$fr = $this->f;
$this->f = $fw;
$offset = $this->header->encode();
foreach ($this->directory as $entry) {
// Read ...
$this->f = $fr;
$this->seek($entry->offset);
$data = $this->read($entry->length);
if ($entry->length < $entry->origLength) {
$data = gzuncompress($data);
}
// Prepare data ...
$length = strlen($data);
$entry->length = $entry->origLength = $length;
$entry->offset = $dataOffset;
// Write ...
$this->f = $fw;
// Woff Entry
$this->seek($offset);
$offset += $this->write($entry->tag, 4); // tag
$offset += $this->writeUInt32($dataOffset); // offset
$offset += $this->writeUInt32($length); // length
$offset += $this->writeUInt32($length); // origLength
$offset += $this->writeUInt32(DirectoryEntry::computeChecksum($data)); // checksum
// Data
$this->seek($dataOffset);
$dataOffset += $this->write($data, $length);
}
$this->f = $fw;
$this->seek(0);
// Need to re-parse this, don't know why
$this->header = null;
$this->directory = array();
$this->parseTableEntries();
}
}
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\WOFF;
/**
* WOFF font file header.
*
* @package php-font-lib
*/
class Header extends \Customily\Categories\Libraries\FontLib\TrueType\Header {
protected $def = array(
"format" => self::uint32,
"flavor" => self::uint32,
"length" => self::uint32,
"numTables" => self::uint16,
self::uint16,
"totalSfntSize" => self::uint32,
"majorVersion" => self::uint16,
"minorVersion" => self::uint16,
"metaOffset" => self::uint32,
"metaLength" => self::uint32,
"metaOrigLength" => self::uint32,
"privOffset" => self::uint32,
"privLength" => self::uint32,
);
}
\ No newline at end of file
<?php
/**
* @package php-font-lib
* @link https://github.com/PhenX/php-font-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace Customily\Categories\Libraries\FontLib\WOFF;
use Customily\Categories\Libraries\FontLib\Table\DirectoryEntry;
/**
* WOFF font file table directory entry.
*
* @package php-font-lib
*/
class TableDirectoryEntry extends DirectoryEntry {
public $origLength;
function __construct(File $font) {
parent::__construct($font);
}
function parse() {
parent::parse();
$font = $this->font;
$this->offset = $font->readUInt32();
$this->length = $font->readUInt32();
$this->origLength = $font->readUInt32();
$this->checksum = $font->readUInt32();
}
}
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 30/09/2020
*/
namespace Customily\Categories\Model\Config;
use Customily\Categories\Helper\CustomilyHelper;
use Magento\Config\Model\Config\CommentInterface;
class ModuleEnableComment implements CommentInterface
{
private $helper;
/**
* ModuleEnableComment constructor.
* @param CustomilyHelper $helper
*/
public function __construct(CustomilyHelper $helper)
{
$this->helper = $helper;
}
/**
* Retrieve element comment by element value
* @param string $elementValue
* @return string
*/
public function getCommentText($elementValue)
{
$moduleVersion = $this->helper->getModuleVersion();
$productCount = $this->helper->getCustomilyProductCount();
return '<b>Module Version: </b>' . $moduleVersion . '&nbsp;&nbsp;&nbsp;&nbsp;<b>Products Count: </b>' . $productCount;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 25/08/2020
*/
namespace Customily\Categories\Model\Config\Source;
class PersonalizationAttachTo implements \Magento\Framework\Data\OptionSourceInterface
{
/**
* Options getter
*
* @return array
*/
public function toOptionArray()
{
return [
['value' => 'default', 'label' => __('Default')],
['value' => 'child', 'label' => __('Child Product')]
];
}
/**
* Get options in "key-value" format
*
* @return array
*/
public function toArray()
{
return ['default' => __('Default'), 'child' => __('Child Product')];
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 25/08/2020
*/
namespace Customily\Categories\Model\Config\Source;
class PersonalizationBehavior implements \Magento\Framework\Data\OptionSourceInterface
{
/**
* Options getter
*
* @return array
*/
public function toOptionArray()
{
return [
['value' => 'visible', 'label' => __('Visible by Default')],
['value' => 'hidden', 'label' => __('Hidden by Default')]
];
}
/**
* Get options in "key-value" format
*
* @return array
*/
public function toArray()
{
return ['visible' => __('Visible by Default'), 'hidden' => __('Hidden by Default')];
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 25/08/2020
*/
namespace Customily\Categories\Model\Config\Source;
class PersonalizationType implements \Magento\Framework\Data\OptionSourceInterface
{
/**
* Options getter
*
* @return array
*/
public function toOptionArray()
{
return [
['value' => 'page-preview', 'label' => __('Product Page Preview')],
['value' => 'modal-preview', 'label' => __('Modal Preview')]
];
}
/**
* Get options in "key-value" format
*
* @return array
*/
public function toArray()
{
return ['page-preview' => __('Product Page Preview'), 'modal-preview' => __('Modal Preview')];
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 04/09/2020
*/
namespace Customily\Categories\Model\Config\Source;
class ServerToSaveFile implements \Magento\Framework\Data\OptionSourceInterface
{
/**
* Options getter
*
* @return array
*/
public function toOptionArray()
{
return [
['value' => 'magento', 'label' => __('Magento Server')],
['value' => 'customily', 'label' => __('Customily Server')]
];
}
/**
* Get options in "key-value" format
*
* @return array
*/
public function toArray()
{
return ['magento' => __('Magento Server'), 'customily' => __('Customily Server')];
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
/**
* Author: Customily
* Date: 18-07-18
* Time: 06:41 PM
*/
namespace Customily\Categories\Observer\Frontend;
use Customily\Categories\Api\Client\ApiClient;
use Customily\Categories\Helper\CustomilyHelper;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
use Psr\Log\LoggerInterface;
class QuoteSubmitBeforeObserver implements ObserverInterface
{
private $quoteItems = [];
/* @var Magento\Payment\Model\Cart\SalesModel\Quote */
private $quote = null;
/* @var \Magento\Sales\Model\Order */
private $order = null;
private $helper;
private $apiClient;
private $logger;
private $settings;
public function __construct(
CustomilyHelper $helper,
ApiClient $apiClient,
LoggerInterface $logger
)
{
$this->helper = $helper;
$this->apiClient = $apiClient;
$this->logger = $logger;
$this->settings = $helper->getCustomilyConfig();
}
/**
* @param EventObserver $observer
* @return void
*/
public function execute(EventObserver $observer) {
$this->quote = $observer->getQuote();
$this->order = $observer->getOrder();
if (!$this->quote->getItems()) {
return $this;
}
$this->initQuoteItems();
$index = 0;
/* @var \Magento\Sales\Model\Order\Item $orderItem */
foreach ($this->order->getItems() as $orderItem) {
if (!$orderItem->getParentItemId()) {
/* @var \Magento\Quote\Model\Quote\Item $quoteItem */
if ($quoteItem = $this->getQuoteItemById($orderItem->getQuoteItemId())) {
/* @var \Magento\Framework\DataObject $infoBuyRequest */
$infoBuyRequest = $quoteItem->getBuyRequest();
$additionalOptions = array();
$index++;
if ($additionalOption = $quoteItem->getOptionByCode('additional_options')) {
$additionalOptions = json_decode($additionalOption->getValue(), true);
}
if (isset($infoBuyRequest)) {
$customilyInfo = $infoBuyRequest->getCustomily();
if (isset($customilyInfo)) {
if (isset($customilyInfo['url_thumbnail']) && !empty($customilyInfo['url_thumbnail'])) {
$additionalOptions[] = [
'label' => 'Thumbnail',
'value' => $customilyInfo['url_thumbnail']
];
}
if (isset($customilyInfo['url_preview']) && !empty($customilyInfo['url_preview'])) {
$additionalOptions[] = [
'label' => 'Preview',
'value' => $customilyInfo['url_preview']
];
}
if (isset($customilyInfo['magento_product_id']) && !empty($customilyInfo['magento_product_id'])) {
$additionalOptions[] = [
'label' => 'magento_product_id',
'value' => $customilyInfo['magento_product_id']
];
}
if (isset($customilyInfo['personalization_id']) && !empty($customilyInfo['personalization_id'])) {
$additionalOptions[] = [
'label' => 'Personalization Id',
'value' => $customilyInfo['personalization_id']
];
if (isset($this->settings['enable_logs']) && $this->settings['enable_logs'] === '1') {
$this->logger->debug("Customily Magento: generating production file for orderId: {$this->order->getIncrementId()}, personalizationId {$customilyInfo['personalization_id']}, sku: {$quoteItem->getSku()}, productName: {$quoteItem->getName()}.");
}
$response = $this->exportProductionFile($customilyInfo['personalization_id'], $orderItem, $index);
if (isset($response) && isset($response['Url'])) {
$additionalOptions[] = [
'label' => 'Production file',
'value' => $response['Url']
];
if (isset($this->settings['enable_logs']) && $this->settings['enable_logs'] === '1') {
$this->logger->debug("Customily Magento: production file generated for orderId: {$this->order->getIncrementId()}, sku: {$quoteItem->getSku()}, productName: {$quoteItem->getName()}, productionFileUrl: {$response['Url']}.");
}
} else {
if (isset($this->settings['enable_logs']) && $this->settings['enable_logs'] === '1') {
$this->logger->debug("Customily Magento: Error generating production file for orderId: {$this->order->getIncrementId()}, personalizationId {$customilyInfo['personalization_id']}, sku: {$quoteItem->getSku()}, productName: {$quoteItem->getName()}.");
}
}
}
}
}
if (count($additionalOptions) > 0) {
$options = $orderItem->getProductOptions();
$options['additional_options'] = $additionalOptions;
$orderItem->setProductOptions($options);
}
}
}
}
}
private function initQuoteItems() {
/* @var \Magento\Quote\Model\Quote\Item $item */
foreach ($this->quote->getItems() as $item) {
if (!$item->getParentItemId()) {
$this->quoteItems[$item->getId()] = $item;
}
}
}
/**
* @param $id
* @return \Magento\Sales\Model\Order\Item|null
*/
private function getQuoteItemById($id) {
if (array_key_exists($id, $this->quoteItems)) {
return $this->quoteItems[$id];
}
return null;
}
/**
* @param $personalizationId
* @param $orderItem
* @param $index
* @return \GuzzleHttp\Psr7\PumpStream|\GuzzleHttp\Psr7\Stream|\Psr\Http\Message\StreamInterface|null
*/
private function exportProductionFile($personalizationId, $orderItem, $index) {
if (isset($this->settings['rename_file']) && $this->settings['rename_file'] === '1') {
$fileName = $this->helper->getProductionFileName($this->order, $orderItem) . '_' . $index;
} else {
$fileName = $this->helper->guidv4();
}
return $this->apiClient->generateProductionFile($personalizationId, $this->order->getIncrementId(), $fileName);
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
namespace Customily\Categories\Plugin\Catalog\Block\Product\View\Options\Type;
use Customily\Categories\Helper\CustomilyHelper;
use Magento\Catalog\Block\Product\View\Options\Type\Select as TypeSelect;
use Magento\Catalog\Model\Product\Option;
use Psr\Log\LoggerInterface;
use Customily\Categories\Block\Product\View\Options\Type\Select\Multiple;
use Customily\Categories\Block\Product\View\Options\Type\Select\Checkable;
final class Select
{
private $helper;
private $logger;
private $multipleBlock;
private $checkableBlock;
/**
* Select constructor.
* @param CustomilyHelper $helper
* @param LoggerInterface $logger
* @param Multiple $multipleBlock
* @param Checkable $checkableBlock
*/
public function __construct(
CustomilyHelper $helper,
LoggerInterface $logger,
Multiple $multipleBlock,
Checkable $checkableBlock
)
{
$this->helper = $helper;
$this->logger = $logger;
$this->multipleBlock = $multipleBlock;
$this->checkableBlock = $checkableBlock;
}
public function aroundGetValuesHtml(TypeSelect $subject, \Closure $proceed)
{
$settings = $this->helper->getCustomilyConfig();
if (isset($settings) && $settings['enable'] === '1' && $settings['selectable_default_value'] === '1') {
try {
$option = $subject->getOption();
$optionType = $option->getType();
if ($optionType === Option::OPTION_TYPE_DROP_DOWN || $optionType === Option::OPTION_TYPE_MULTIPLE) {
return $this->multipleBlock
->setOption($option)
->setProduct($subject->getProduct())
->setSkipJsReloadPrice(1)
->toHtml();
}
if ($optionType === Option::OPTION_TYPE_RADIO || $optionType === Option::OPTION_TYPE_CHECKBOX) {
return $this->checkableBlock
->setOption($option)
->setProduct($subject->getProduct())
->setSkipJsReloadPrice(1)
->toHtml();
}
} catch (\Exception $e) {
if ($settings['enable_logs'] === '1') {
$this->logger->debug($e->getTraceAsString());
}
}
}
return $proceed();
}
}
<?php
/**
* Copyright © Customily. All rights reserved.
*/
namespace Customily\Categories\Plugin\Catalog\Ui\DataProvider\Product\Form\Modifier;
use Customily\Categories\Helper\CustomilyHelper;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions as BaseCustomOptions;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Element\Input;
use Magento\Ui\Component\Form\Element\Hidden;
use Magento\Ui\Component\Form\Element\Textarea;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Element\Checkbox;
use Magento\Ui\Component\Form\Element\DataType\Number;
use Magento\Ui\Component\Form\Element\DataType\Text;
class CustomOptions
{
const FIELD_CUSTOMILY_FUNCTIONS = 'customily_functions';
const FIELD_CUSTOMILY_CONDITIONS = 'customily_conditions';
const FIELD_CUSTOMILY_IS_SWATCH = 'customily_is_swatch';
const FIELD_CUSTOMILY_SWATCH_SETTINGS = 'customily_swatch_settings';
const FIELD_CUSTOMILY_TEXT_DEFAULT_VALUE = 'customily_text_default_value';
const FIELD_CUSTOMILY_TEXT_TRANSFORM = 'customily_text_transform';
const FIELD_CUSTOMILY_IMAGE_MIN_SIZE_X = 'customily_image_min_size_x';
const FIELD_CUSTOMILY_IMAGE_MIN_SIZE_Y = 'customily_image_min_size_y';
const FIELD_CUSTOMILY_INDEX_POSITIONS = 'customily_index_positions';
const FIELD_CUSTOMILY_INDEX_COLOR = 'customily_index_color';
const FIELD_CUSTOMILY_INDEX_THUMBNAIL = 'customily_index_thumbnail';
const FIELD_CUSTOMILY_IS_DEFAULT = 'customily_is_default';
const FIELD_CUSTOMILY_IS_REQUIRED = 'customily_is_required';
const FIELD_MAGENTO_IS_REQUIRE = 'is_require';
/* @var \Customily\Categories\Helper\CustomilyHelper */
private $helper;
private $isCustomlyEnabled;
private $isSwatchesEnabled;
/**
* @var array
*/
private $meta = [];
/**
* CustomOptions constructor.
* @param CustomilyHelper $helper
*/
public function __construct(CustomilyHelper $helper) {
$this->helper = $helper;
$settings = $this->helper->getCustomilyConfig();
$this->isCustomlyEnabled = $settings['enable'] ?? false;
$this->isSwatchesEnabled = $settings['enable_swatches'] ?? false;
}
/**
* Add customily fields
* @param BaseCustomOptions $subject
* @param array $result
* @return array|mixed
*/
public function afterModifyMeta($subject, $result) {
$requestUri = $_SERVER['REQUEST_URI'];
$isMageWorxPage = strpos($requestUri, 'mageworx_optiontemplates/group/edit');
if ($this->isCustomlyEnabled === '1' && $isMageWorxPage === false) {
$this->meta = $result;
$this->addCustomiyFields();
return $this->meta;
}
return $result;
}
/**
* Adds fields to the meta-data
*/
private function addCustomiyFields()
{
$groupCustomOptionsName = BaseCustomOptions::GROUP_CUSTOM_OPTIONS_NAME;
$optionContainerName = BaseCustomOptions::CONTAINER_OPTION;
$commonOptionContainerName = BaseCustomOptions::CONTAINER_COMMON_NAME;
$staticOptionContainerName = BaseCustomOptions::CONTAINER_TYPE_STATIC_NAME;
// Add fields to the common option container
$this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children']
[$optionContainerName]['children'][$commonOptionContainerName]['children'] = array_replace_recursive(
$this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children']
[$optionContainerName]['children'][$commonOptionContainerName]['children'],
$this->getCommonOptionFieldsConfig()
);
// Add fields to the static option container
$this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children']
[$optionContainerName]['children'][$staticOptionContainerName]['children'] = array_replace_recursive(
$this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children']
[$optionContainerName]['children'][$staticOptionContainerName]['children'],
$this->getStaticOptionFieldsConfig()
);
// Add fields to the values
$this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children']
[$optionContainerName]['children']['values']['children']['record']['children'] = array_replace_recursive(
$this->meta[$groupCustomOptionsName]['children']['options']['children']['record']['children']
[$optionContainerName]['children']['values']['children']['record']['children'],
$this->getValueFieldsConfig()
);
}
/**
* The common option fields config
*
* @return array
*/
private function getCommonOptionFieldsConfig()
{
$fields = [];
$fields[static::FIELD_MAGENTO_IS_REQUIRE] = $this->getMagentoIsRequireFieldConfig(40);
$fields[static::FIELD_CUSTOMILY_IS_REQUIRED] = $this->getCustomilyIsRequiredFieldConfig(41);
$fields[static::FIELD_CUSTOMILY_FUNCTIONS] = $this->getCustomilyFunctionsFieldConfig(42);
$fields[static::FIELD_CUSTOMILY_CONDITIONS] = $this->getCustomilyConditionsFieldConfig(43);
if ($this->isSwatchesEnabled === '1') {
$fields[static::FIELD_CUSTOMILY_IS_SWATCH] = $this->getCustomilyIsSwatchFieldConfig(44);
$fields[static::FIELD_CUSTOMILY_SWATCH_SETTINGS] = $this->getCustomilySwatchSettingsFieldConfig(45);
}
return $fields;
}
/**
* The static option fields config
*
* @return array
*/
private function getStaticOptionFieldsConfig()
{
return [
static::FIELD_CUSTOMILY_TEXT_DEFAULT_VALUE => $this->getCustomilyTextDefaultValueFieldConfig(54),
static::FIELD_CUSTOMILY_TEXT_TRANSFORM => $this->getCustomilyTextTransformFieldConfig(55),
static::FIELD_CUSTOMILY_IMAGE_MIN_SIZE_X => $this->getCustomilyImageMinSizeXFieldConfig(56),
static::FIELD_CUSTOMILY_IMAGE_MIN_SIZE_Y => $this->getCustomilyImageMinSizeYFieldConfig(57)
];
}
/**
* The custom option fields config
*
* @return array
*/
private function getValueFieldsConfig()
{
$fields = [];
$fields[static::FIELD_CUSTOMILY_INDEX_POSITIONS] = $this->getCustomilyIndexPositionsFieldConfig(41);
if ($this->isSwatchesEnabled === '1') {
$fields[static::FIELD_CUSTOMILY_INDEX_COLOR] = $this->getCustomilyIndexColorFieldConfig(42);
$fields[static::FIELD_CUSTOMILY_INDEX_THUMBNAIL] = $this->getCustomilyIndexThumbnailFieldConfig(43);
}
$fields[static::FIELD_CUSTOMILY_IS_DEFAULT] = $this->getCustomilyIsDefaultFieldConfig(44);
return $fields;
}
/**
* Get config for "Customily Functions" field
*
* @param $sortOrder
* @return array
*/
private function getCustomilyFunctionsFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Functions'),
'componentType' => Field::NAME,
'formElement' => Textarea::NAME,
'dataScope' => static::FIELD_CUSTOMILY_FUNCTIONS,
'dataType' => Text::NAME,
'valueUpdate' => ['afterkeydown', 'input', 'blur', 'change'],
'textInput' => 'value',
'sortOrder' => $sortOrder
]
]
]
];
}
/**
* Get config for "Customily Conditions" field
* @param $sortOrder
* @return array
* @since 1.0.1
*/
private function getCustomilyConditionsFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Conditions'),
'componentType' => Field::NAME,
'formElement' => Textarea::NAME,
'dataScope' => static::FIELD_CUSTOMILY_CONDITIONS,
'dataType' => Text::NAME,
'valueUpdate' => ['afterkeydown', 'input', 'blur', 'change'],
'textInput' => 'value',
'sortOrder' => $sortOrder
]
]
]
];
}
/**
* Get config for "Customily Is Swatch" field
*
* @param $sortOrder
* @return array
*/
private function getCustomilyIsSwatchFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Is Swatch?'),
'componentType' => Field::NAME,
'formElement' =>Checkbox::NAME,
'dataScope' => static::FIELD_CUSTOMILY_IS_SWATCH,
'additionalClasses' => 'cl-hidden',
'dataType' => Text::NAME,
'sortOrder' => $sortOrder,
'visible' => false,
'value' => '1',
'valueMap' => [
'true' => '1',
'false' => '0'
]
]
]
]
];
}
/**
* Get config for "Customily Swatch Settings" field
*
* @param $sortOrder
* @return array
*/
private function getCustomilySwatchSettingsFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Swatch Settings'),
'componentType' => Field::NAME,
'formElement' => Textarea::NAME,
'dataScope' => static::FIELD_CUSTOMILY_SWATCH_SETTINGS,
'dataType' => Text::NAME,
'valueUpdate' => ['afterkeydown', 'input', 'blur', 'change'],
'textInput' => 'value',
'sortOrder' => $sortOrder
]
]
]
];
}
/**
* Get config for "Customily Index Positions" field
* @param $sortOrder
* @return array
* @since 1.0.1
*/
private function getCustomilyIndexPositionsFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Positions'),
'componentType' => Field::NAME,
'formElement' => Hidden::NAME,
'dataScope' => static::FIELD_CUSTOMILY_INDEX_POSITIONS,
'dataType' => Text::NAME,
'valueUpdate' => ['afterkeydown', 'input', 'blur', 'change'],
'textInput' => 'value',
'sortOrder' => $sortOrder
]
]
]
];
}
/**
* Get config for "Customily Index Color" field
* @param $sortOrder
* @return array
* @since 1.0.1
*/
private function getCustomilyIndexColorFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Swatch Color'),
'componentType' => Field::NAME,
'formElement' => Input::NAME,
'dataScope' => static::FIELD_CUSTOMILY_INDEX_COLOR,
'dataType' => Text::NAME,
'valueUpdate' => ['afterkeydown', 'input', 'blur', 'change'],
'textInput' => 'value',
'sortOrder' => $sortOrder
]
]
]
];
}
/**
* Get config for "Customily Index Thumbnail" field
* @param $sortOrder
* @return array
* @since 1.0.1
*/
private function getCustomilyIndexThumbnailFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Swatch Image'),
'componentType' => Field::NAME,
'formElement' => Hidden::NAME,
'dataScope' => static::FIELD_CUSTOMILY_INDEX_THUMBNAIL,
'dataType' => Text::NAME,
'valueUpdate' => ['afterkeydown', 'input', 'blur', 'change'],
'textInput' => 'value',
'sortOrder' => $sortOrder
]
]
]
];
}
/**
* Get config for "Customily Is Default" field
* @param $sortOrder
* @return \array[][][]
*/
private function getCustomilyIsDefaultFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Default'),
'componentType' => Field::NAME,
'formElement' =>Checkbox::NAME,
'dataScope' => static::FIELD_CUSTOMILY_IS_DEFAULT,
'additionalClasses' => 'cl-is_default-checkbox',
'dataType' => Text::NAME,
'valueUpdate' => ['afterkeydown', 'input', 'blur', 'change'],
'sortOrder' => $sortOrder,
'visible' => true,
'value' => '0',
'valueMap' => [
'true' => '1',
'false' => '0'
]
]
]
]
];
}
/**
* Get config for "Customily Is Required" field
*
* @param int $sortOrder
* @return array
* @since 1.6.1
*/
private function getCustomilyIsRequiredFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Required'),
'componentType' => Field::NAME,
'formElement' => Checkbox::NAME,
'dataScope' => static::FIELD_CUSTOMILY_IS_REQUIRED,
'dataType' => Text::NAME,
'sortOrder' => $sortOrder,
'value' => '0',
'valueMap' => [
'true' => '1',
'false' => '0'
]
]
]
]
];
}
/**
* Get config for "Required" field
*
* @param int $sortOrder
* @return array
* @since 2.0.13
*/
protected function getMagentoIsRequireFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Required'),
'componentType' => Field::NAME,
'formElement' => Checkbox::NAME,
'dataScope' => static::FIELD_MAGENTO_IS_REQUIRE,
'dataType' => Text::NAME,
'sortOrder' => $sortOrder,
'value' => '0',
'valueMap' => [
'true' => '1',
'false' => '0'
]
]
]
]
];
}
/**
* Get config for "Default Value" field
*
* @param int $sortOrder
* @return array
* @since 2.3.0
*/
protected function getCustomilyTextDefaultValueFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Default Value'),
'componentType' => Field::NAME,
'formElement' => Input::NAME,
'dataScope' => static::FIELD_CUSTOMILY_TEXT_DEFAULT_VALUE,
'dataType' => Text::NAME,
'sortOrder' => $sortOrder
]
]
]
];
}
/**
* Get config for "Text Transform" field
*
* @param int $sortOrder
* @return array
* @since 2.1.0
*/
protected function getCustomilyTextTransformFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Text Transform'),
'componentType' => Field::NAME,
'formElement' => Select::NAME,
'dataScope' => static::FIELD_CUSTOMILY_TEXT_TRANSFORM,
'dataType' => Text::NAME,
'sortOrder' => $sortOrder,
'options' => [
['value' => 'none', 'label' => __('None')],
['value' => 'capitalize', 'label' => __('Capitalize')],
['value' => 'lowercase', 'label' => __('Lowercase')],
['value' => 'uppercase', 'label' => __('Uppercase')]
],
'disableLabel' => true,
'multiple' => false
]
]
]
];
}
/**
* Get config for "Minimum Image Width" field
*
* @param int $sortOrder
* @return array
* @since 2.1.0
*/
protected function getCustomilyImageMinSizeXFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Minimum Image Size'),
'notice' => __('Please leave blank if it is not an image.'),
'addafter' => __('px'),
'component' => 'Magento_Catalog/js/components/custom-options-component',
'componentType' => Field::NAME,
'formElement' => Input::NAME,
'dataScope' => static::FIELD_CUSTOMILY_IMAGE_MIN_SIZE_X,
'dataType' => Number::NAME,
'sortOrder' => $sortOrder,
'validation' => [
'validate-zero-or-greater' => true
]
]
]
]
];
}
/**
* Get config for "Minimum Image Height" field
*
* @param int $sortOrder
* @return array
* @since 2.1.0
*/
protected function getCustomilyImageMinSizeYFieldConfig($sortOrder)
{
return [
'arguments' => [
'data' => [
'config' => [
'label' => ' ',
'addafter' => __('px'),
'component' => 'Magento_Catalog/js/components/custom-options-component',
'componentType' => Field::NAME,
'formElement' => Input::NAME,
'dataScope' => static::FIELD_CUSTOMILY_IMAGE_MIN_SIZE_Y,
'dataType' => Number::NAME,
'sortOrder' => $sortOrder,
'validation' => [
'validate-zero-or-greater' => true
]
]
]
]
];
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 09/12/2019
*/
namespace Customily\Categories\Plugin\Checkout\Block\Cart\Item;
use Customily\Categories\Helper\CustomilyHelper;
use Psr\Log\LoggerInterface;
class Renderer
{
private $helper;
private $logger;
/**
* Renderer constructor.
* @param CustomilyHelper $helper
* @param LoggerInterface $logger
*/
public function __construct(CustomilyHelper $helper, LoggerInterface $logger)
{
$this->helper = $helper;
$this->logger = $logger;
}
public function afterGetImage($subject, $result)
{
$settings = $this->helper->getCustomilyConfig();
if (isset($settings) && $settings['enable'] === '1' && $settings['custom_cart_thumbnail'] === '1') {
try {
$item = $subject->getItem();
$data = $this->helper->getQuoteBuyRequest($item->getId());
if (
isset($data['customily']) &&
isset($data['customily']['url_thumbnail']) &&
!empty($data['customily']['url_thumbnail'])
) {
$result->setImageUrl($data['customily']['url_thumbnail']);
}
} catch (\Exception $e) {
if ($settings['enable_logs'] === '1') {
$this->logger->debug($e->getTraceAsString());
}
}
}
return $result;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 09/12/2019
*/
namespace Customily\Categories\Plugin\Checkout\CustomerData;
use Customily\Categories\Helper\CustomilyHelper;
use Psr\Log\LoggerInterface;
class AbstractItem
{
private $helper;
private $logger;
/**
* CustomMiniCartItemImage constructor.
* @param CustomilyHelper $helper
* @param LoggerInterface $logger
*/
public function __construct(CustomilyHelper $helper, LoggerInterface $logger)
{
$this->helper = $helper;
$this->logger = $logger;
}
public function aroundGetItemData($subject, $proceed, $item)
{
$result = $proceed($item);
$settings = $this->helper->getCustomilyConfig();
if (isset($settings) && $settings['enable'] === '1' && $settings['custom_minicart_thumbnail'] === '1') {
try {
$data = $this->helper->getQuoteBuyRequest($result['item_id']);
if (
isset($data['customily']) &&
isset($data['customily']['url_thumbnail']) &&
!empty($data['customily']['url_thumbnail'])
) {
$result['product_image']['src'] = $data['customily']['url_thumbnail'];
}
} catch (\Exception $e) {
if ($settings['enable_logs'] === '1') {
$this->logger->debug($e->getTraceAsString());
}
}
}
return $result;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 30/04/2020
*/
namespace Customily\Categories\Plugin\Quote\Model\Quote;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Customily\Categories\Helper\CustomilyHelper;
use Psr\Log\LoggerInterface;
class Item
{
private $helper;
private $productRepository;
private $logger;
/**
* AddNewProductToCart constructor.
* @param CustomilyHelper $helper
* @param ProductRepositoryInterface $productRepository
* @param LoggerInterface $logger
*/
public function __construct(
CustomilyHelper $helper,
ProductRepositoryInterface $productRepository,
LoggerInterface $logger
)
{
$this->productRepository = $productRepository;
$this->helper = $helper;
$this->logger = $logger;
}
public function afterRepresentProduct($subject, $result)
{
try {
$settings = $this->helper->getCustomilyConfig();
$isCustomilyEnabled = $settings['enable'] ?? false;
$representProduct = $settings['represent_product'] ?? false;
if ($isCustomilyEnabled === '1' && $representProduct === '1') {
$product = $subject->getProduct();
$product = $this->productRepository->getById($product->getId());
$isCustomilyProduct = $product->getCustomProduct();
$isCustomilyProduct = $isCustomilyProduct ?? false;
$customilyProductId = $product->getProductCustomizationId();
$isValidCustomilyProductId = isset($customilyProductId) && $this->helper->validateGuid(
trim($customilyProductId)
);
$isPersonalizedItem = $this->helper->isPersonalizedItem($subject);
if ($isCustomilyProduct === '1' && $isValidCustomilyProductId && $isPersonalizedItem) {
$result = false;
}
}
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
return $result;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 15/12/2021
*/
namespace Customily\Categories\Plugin\Sales\Block\Order\Email\Items;
use Magento\Sales\Block\Order\Email\Items\DefaultItems as BaseDefaultItems;
use Customily\Categories\Helper\CustomilyHelper;
use Psr\Log\LoggerInterface;
class DefaultItems
{
private $helper;
private $logger;
/**
* DefaultItems constructor.
* @param CustomilyHelper $helper
* @param LoggerInterface $logger
*/
public function __construct(
CustomilyHelper $helper,
LoggerInterface $logger
)
{
$this->helper = $helper;
$this->logger = $logger;
}
/**
* @param BaseDefaultItems $subject
* @param array $options
* @return array|mixed
*/
public function afterGetItemOptions($subject, $options) {
try {
$settings = $this->helper->getCustomilyConfig();
if (count($options) > 0 && isset($settings) && $settings['enable'] === '1') {
return $this->helper->getItemOptionsToShow($options, $settings['show_uploaded_image_url']);
}
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
return $options;
}
}
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 15/12/2021
*/
namespace Customily\Categories\Plugin\Sales\Block\Order\Email\Items\Order;
use Magento\Sales\Block\Order\Email\Items\Order\DefaultOrder as BaseDefaultOrder;
use Customily\Categories\Helper\CustomilyHelper;
use Psr\Log\LoggerInterface;
class DefaultOrder
{
private $helper;
private $logger;
/**
* DefaultOrder constructor.
* @param CustomilyHelper $helper
* @param LoggerInterface $logger
*/
public function __construct(
CustomilyHelper $helper,
LoggerInterface $logger
)
{
$this->helper = $helper;
$this->logger = $logger;
}
/**
* @param BaseDefaultOrder $subject
* @param array $options
* @return array|mixed
*/
public function afterGetItemOptions($subject, $options) {
try {
$settings = $this->helper->getCustomilyConfig();
if (count($options) > 0 && isset($settings) && $settings['enable'] === '1') {
return $this->helper->getItemOptionsToShow($options, $settings['show_uploaded_image_url']);
}
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
return $options;
}
}
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 28/07/2021
*/
namespace Customily\Categories\Plugin\Sales\Block\Order\Item\Renderer;
use Magento\Sales\Block\Order\Item\Renderer\DefaultRenderer as BaseDefaultRenderer;
use Customily\Categories\Helper\CustomilyHelper;
use Psr\Log\LoggerInterface;
class DefaultRenderer
{
private $helper;
private $logger;
/**
* DefaultRenderer constructor.
* @param CustomilyHelper $helper
* @param LoggerInterface $logger
*/
public function __construct(
CustomilyHelper $helper,
LoggerInterface $logger
)
{
$this->helper = $helper;
$this->logger = $logger;
}
/**
* @param BaseDefaultRenderer $subject
* @param array $options
* @return array|mixed
*/
public function afterGetItemOptions($subject, $options) {
try {
$settings = $this->helper->getCustomilyConfig();
if (count($options) > 0 && isset($settings) && $settings['enable'] === '1') {
return $this->helper->getItemOptionsToShow($options, $settings['show_uploaded_image_url'], false, $subject->getSku());
}
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
return $options;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
/**
* Author: Customily
* Date: 28-03-17
* Time: 09:05 PM
*/
namespace Customily\Categories\Setup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\ActionFactory;
use Psr\Log\LoggerInterface;
class InstallData implements InstallDataInterface
{
private $eavSetupFactory;
private $collectionFactory;
private $actionFactory;
private $logger;
/**
* InstallData constructor.
* @param EavSetupFactory $eavSetupFactory
* @param CollectionFactory $collectionFactory
* @param ActionFactory $actionFactory
* @param LoggerInterface $logger
*/
public function __construct(
EavSetupFactory $eavSetupFactory,
CollectionFactory $collectionFactory,
ActionFactory $actionFactory,
LoggerInterface $logger
)
{
$this->eavSetupFactory = $eavSetupFactory;
$this->collectionFactory = $collectionFactory;
$this->actionFactory = $actionFactory;
$this->logger = $logger;
}
/**
* Installs data for a module
*
* @param ModuleDataSetupInterface $setup
* @param ModuleContextInterface $context
* @return void
*/
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'product_customization_id',
[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Product Customization Id',
'input' => 'text',
'class' => '',
'source' => '',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => '',
'group'=> 'General'
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'custom_product',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Enable Customization',
'input' => 'boolean',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'collapsible_options',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Collapsible Options',
'input' => 'boolean',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'sticky_preview',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Sticky Preview',
'input' => 'boolean',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'attributes_options',
[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Attributes Options',
'input' => 'textarea',
'class' => '',
'source' => '',
'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => false,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'is_wysiwyg_enabled' => false,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'preview_link_in_email',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Add Preview to Order Email',
'input' => 'boolean',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'production_file_link_in_email',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Add Production File to Order Email',
'input' => 'boolean',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'personalization_is_optional',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Personalization Optional',
'input' => 'boolean',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
try {
/* @var \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection */
$productCollection = $this->collectionFactory->create();
$collection = $productCollection->addAttributeToSelect('*')->load();
$productIds = [];
foreach ($collection as $product) {
$productIds[] = $product->getId();
}
/* @var $productActionObject \Magento\Catalog\Model\Product\Action */
$productActionObject = $this->actionFactory->create();
$attributes = [];
$attributes['custom_product'] = '0';
$attributes['collapsible_options'] = '0';
$attributes['sticky_preview'] = '0';
$attributes['preview_link_in_email'] = '0';
$attributes['production_file_link_in_email'] = '0';
$attributes['personalization_is_optional'] = '0';
$productActionObject->updateAttributes($productIds, $attributes, 0);
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
/**
* Author: Customily
* Date: 03-11-17
* Time: 11:11 AM
*/
namespace Customily\Categories\Setup;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;
class InstallSchema implements InstallSchemaInterface
{
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
// Get table catalog_product_option
$tableName = $setup->getTable('catalog_product_option');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_functions',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily functions'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_conditions',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily conditions'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_is_swatch',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily is swatch'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_swatch_settings',
[
'type' => Table::TYPE_TEXT,
'length' => '500',
'nullable' => true,
'default' => '',
'comment' => 'Customily swatch settings'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_is_required',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily is required field'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_imported_from_template_id',
[
'type' => Table::TYPE_TEXT,
'length' => '50',
'nullable' => true,
'default' => '',
'comment' => 'Customily option imported from template id'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_text_default_value',
[
'type' => Table::TYPE_TEXT,
'length' => '250',
'nullable' => true,
'default' => '',
'comment' => 'Customily text default value'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_text_transform',
[
'type' => Table::TYPE_TEXT,
'length' => '20',
'nullable' => true,
'default' => 'none',
'comment' => 'Customily text transform'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_image_min_size_x',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily image minimum width'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_image_min_size_y',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily image minimum height'
]
);
}
// Get table catalog_product_option_type_value
$tableName = $setup->getTable('catalog_product_option_type_value');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_index_positions',
[
'type' => Table::TYPE_TEXT,
'length' => '500',
'nullable' => true,
'default' => '',
'comment' => 'Customily index positions'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_index_color',
[
'type' => Table::TYPE_TEXT,
'length' => '50',
'nullable' => true,
'default' => '',
'comment' => 'Customily index color'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_index_thumbnail',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily index thumbnail'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_is_default',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily is default value'
]
);
}
$setup->endSetup();
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
/**
* Author: Customily
* Date: 03-12-19
* Time: 09:25 AM
*/
namespace Customily\Categories\Setup;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\Setup\UpgradeDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\ActionFactory;
use Psr\Log\LoggerInterface;
class UpgradeData implements UpgradeDataInterface
{
private $eavSetupFactory;
private $collectionFactory;
private $actionFactory;
private $logger;
/**
* UpgradeData constructor.
* @param EavSetupFactory $eavSetupFactory
* @param CollectionFactory $collectionFactory
* @param ActionFactory $actionFactory
* @param LoggerInterface $logger
*/
public function __construct(
EavSetupFactory $eavSetupFactory,
CollectionFactory $collectionFactory,
ActionFactory $actionFactory,
LoggerInterface $logger
)
{
$this->eavSetupFactory = $eavSetupFactory;
$this->collectionFactory = $collectionFactory;
$this->actionFactory = $actionFactory;
$this->logger = $logger;
}
public function upgrade(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
$eavSetup = $this->eavSetupFactory->create(['setup' => $setup]);
$attributes = [];
if (version_compare($context->getVersion(), '1.0.0.1', '<=')) {
$setup->getConnection()->query("UPDATE sales_order_item SET product_options = REPLACE(product_options, 'blogtreat', 'customily')");
$setup->getConnection()->query("UPDATE quote_item_option SET value = REPLACE(value, 'blogtreat', 'customily')");
if ($setup->getConnection()->tableColumnExists('catalog_product_option_type_value', 'customily_index') == true) {
$setup->getConnection()->query("UPDATE catalog_product_option_type_value SET customily_index = sku");
}
}
if (version_compare($context->getVersion(), '1.2.2', '<')) {
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_functions = REPLACE(customily_functions, 'dynamic-image', 'dynamic_image')");
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_functions = REPLACE(customily_functions, 'dynamic-vector', 'dynamic_vector')");
$setup->getConnection()->query("UPDATE catalog_product_option_type_value AS v SET v.customily_index_positions = CONCAT('[{\"id\":0,\"type\":\"', (SELECT c.customily_functions FROM catalog_product_option AS c WHERE c.option_id = v.option_id), '\",\"position\":\"', v.customily_index_positions,'\"}]')");
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_functions = CONCAT('[{\"id\":0,\"type\":\"', customily_functions, '\",\"element_id\":\"', customily_conditions,'\"}]')");
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_functions = CONCAT('[{\"id\":0,\"type\":\"text\",\"element_id\":\"', customily_conditions,'\"}]') WHERE type = 'field' AND customily_conditions IS NOT NULL AND customily_conditions <> ''");
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_functions = CONCAT('[{\"id\":0,\"type\":\"file\",\"element_id\":\"', customily_conditions,'\"}]') WHERE type = 'file' AND customily_conditions IS NOT NULL AND customily_conditions <> ''");
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_functions = '[{\"id\":0,\"type\":\"product\",\"element_id\":\"\"}]' WHERE customily_functions = 'product'");
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_conditions = ''");
}
if (version_compare($context->getVersion(), '1.2.5', '<')) {
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'collapsible_options',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Collapsible Options',
'input' => 'select',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => 0,
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'sticky_preview',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Sticky Preview',
'input' => 'select',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => 0,
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$attributes['collapsible_options'] = '0';
$attributes['sticky_preview'] = '0';
}
if (version_compare($context->getVersion(), '1.2.7', '<')) {
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'attributes_options',
[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Attributes Options',
'input' => 'textarea',
'class' => '',
'source' => '',
'global' => \Magento\Catalog\Model\ResourceModel\Eav\Attribute::SCOPE_GLOBAL,
'visible' => true,
'required' => false,
'user_defined' => false,
'default' => '',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'is_wysiwyg_enabled' => false,
'unique' => false,
'apply_to' => ''
]
);
}
if (version_compare($context->getVersion(), '1.6.1', '<')) {
$setup->getConnection()->query("UPDATE catalog_product_option SET customily_is_required = is_require");
}
if (version_compare($context->getVersion(), '1.6.2', '<')) {
$setup->getConnection()->query("UPDATE catalog_product_option SET is_require = '0' WHERE customily_is_required = '1'");
}
if (version_compare($context->getVersion(), '1.8.0', '<')) {
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'preview_link_in_email',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Preview Link in Order Email',
'input' => 'select',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'production_file_link_in_email',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Production File Link in Order Email',
'input' => 'select',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$attributes['preview_link_in_email'] = '0';
$attributes['production_file_link_in_email'] = '0';
}
if (version_compare($context->getVersion(), '2.0.5', '<')) {
$setup->getConnection()->query("UPDATE catalog_eav_attribute cea JOIN eav_attribute ea ON ea.attribute_id = cea.attribute_id SET cea.is_filterable = '0', cea.is_filterable_in_search = '0' WHERE ea.attribute_code = 'product_customization_id' OR ea.attribute_code = 'attributes_options'");
}
if (version_compare($context->getVersion(), '2.1.6', '<')) {
$eavSetup->addAttribute(
\Magento\Catalog\Model\Product::ENTITY,
'personalization_is_optional',[
'type' => 'text',
'backend' => 'Magento\Eav\Model\Entity\Attribute\Backend\ArrayBackend',
'frontend' => '',
'label' => 'Personalization Optional',
'input' => 'boolean',
'class' => '',
'source' => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
'global' => \Magento\Eav\Model\Entity\Attribute\ScopedAttributeInterface::SCOPE_GLOBAL,
'visible' => true,
'required' => true,
'user_defined' => false,
'default' => '0',
'searchable' => false,
'filterable' => false,
'comparable' => false,
'visible_on_front' => false,
'used_in_product_listing' => true,
'unique' => false,
'apply_to' => ''
]
);
$attributes['personalization_is_optional'] = '0';
$setup->getConnection()->query("UPDATE eav_attribute SET frontend_input = 'boolean' WHERE entity_type_id = 4 AND attribute_code IN ('custom_product', 'collapsible_options', 'sticky_preview', 'preview_link_in_email', 'production_file_link_in_email')");
}
if (count($attributes) > 0) {
try {
/* @var \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection */
$productCollection = $this->collectionFactory->create();
$collection = $productCollection->addAttributeToSelect('*')->load();
$productIds = [];
foreach ($collection as $product) {
$productIds[] = $product->getId();
}
/* @var $productActionObject \Magento\Catalog\Model\Product\Action */
$productActionObject = $this->actionFactory->create();
$productActionObject->updateAttributes($productIds, $attributes, 0);
} catch (\Exception $e) {
$this->logger->debug($e->getTraceAsString());
}
}
$setup->endSetup();
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
/**
* Author: Customily
* Date: 10-11-17
* Time: 09:25 AM
*/
namespace Customily\Categories\Setup;
use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;
class UpgradeSchema implements UpgradeSchemaInterface
{
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$setup->startSetup();
if (version_compare($context->getVersion(), '1.0.0.1', '<=')) {
// Get table catalog_product_option
$tableName = $setup->getTable('catalog_product_option');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_functions',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily functions'
]
);
if ($setup->getConnection()->tableColumnExists($tableName, 'customily_placeholder_id') == true) {
$setup->getConnection()->changeColumn(
$setup->getTable($tableName),
'customily_placeholder_id',
'customily_conditions',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily conditions'
]
);
}
}
// Get table catalog_product_option_type_value
$tableName = $setup->getTable('catalog_product_option_type_value');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
if ($setup->getConnection()->tableColumnExists($tableName, 'customily_placeholder_id') == true) {
$setup->getConnection()->changeColumn(
$setup->getTable($tableName),
'customily_placeholder_id',
'customily_index_positions',
[
'type' => Table::TYPE_TEXT,
'length' => '500',
'nullable' => true,
'default' => '',
'comment' => 'Customily index positions'
]
);
}
}
}
if (version_compare($context->getVersion(), '1.2.2', '<')) {
// Get table catalog_product_option
$tableName = $setup->getTable('catalog_product_option');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
if ($setup->getConnection()->tableColumnExists($tableName, 'customily_function_type') == true) {
$setup->getConnection()->changeColumn(
$setup->getTable($tableName),
'customily_function_type',
'customily_functions',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily functions'
]
);
}
if ($setup->getConnection()->tableColumnExists($tableName, 'customily_element_id') == true) {
$setup->getConnection()->changeColumn(
$setup->getTable($tableName),
'customily_element_id',
'customily_conditions',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily functions'
]
);
}
$setup->getConnection()->addColumn(
$tableName,
'customily_is_swatch',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily is swatch'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_swatch_settings',
[
'type' => Table::TYPE_TEXT,
'length' => '500',
'nullable' => true,
'default' => '',
'comment' => 'Customily swatch settings'
]
);
}
// Get table catalog_product_option_type_value
$tableName = $setup->getTable('catalog_product_option_type_value');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
if ($setup->getConnection()->tableColumnExists($tableName, 'customily_index') == true) {
$setup->getConnection()->changeColumn(
$setup->getTable($tableName),
'customily_index',
'customily_index_positions',
[
'type' => Table::TYPE_TEXT,
'length' => '500',
'nullable' => true,
'default' => '',
'comment' => 'Customily index positions'
]
);
}
$setup->getConnection()->addColumn(
$tableName,
'customily_index_color',
[
'type' => Table::TYPE_TEXT,
'length' => '50',
'nullable' => true,
'default' => '',
'comment' => 'Customily index color'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_index_thumbnail_base64',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily index thumbnail base64'
]
);
}
}
if (version_compare($context->getVersion(), '1.6.1', '<')) {
// Get table catalog_product_option
$tableName = $setup->getTable('catalog_product_option');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_is_required',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily is required field'
]
);
}
// Get table catalog_product_option_type_value
$tableName = $setup->getTable('catalog_product_option_type_value');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_is_default',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily is default value'
]
);
}
}
if (version_compare($context->getVersion(), '1.7.0', '<')) {
$tableName = $setup->getTable('catalog_product_option_type_value');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
if ($setup->getConnection()->tableColumnExists($tableName, 'customily_index_thumbnail') == false &&
$setup->getConnection()->tableColumnExists($tableName, 'customily_index_thumbnail_base64') == true) {
$setup->getConnection()->changeColumn(
$setup->getTable($tableName),
'customily_index_thumbnail_base64',
'customily_index_thumbnail',
[
'type' => Table::TYPE_TEXT,
'length' => '2M',
'nullable' => true,
'default' => '',
'comment' => 'Customily index thumbnail'
]
);
}
}
}
if (version_compare($context->getVersion(), '2.0.8', '<')) {
$tableName = $setup->getTable('catalog_product_option');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_imported_from_template_id',
[
'type' => Table::TYPE_TEXT,
'length' => '50',
'nullable' => true,
'default' => '',
'comment' => 'Customily option imported from template id'
]
);
}
}
if (version_compare($context->getVersion(), '2.1.0', '<')) {
$tableName = $setup->getTable('catalog_product_option');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_text_transform',
[
'type' => Table::TYPE_TEXT,
'length' => '20',
'nullable' => true,
'default' => 'none',
'comment' => 'Customily text transform'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_image_min_size_x',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily image minimum width'
]
);
$setup->getConnection()->addColumn(
$tableName,
'customily_image_min_size_y',
[
'type' => Table::TYPE_SMALLINT,
'nullable' => true,
'default' => 0,
'comment' => 'Customily image minimum height'
]
);
}
}
if (version_compare($context->getVersion(), '2.3.0', '<')) {
$tableName = $setup->getTable('catalog_product_option');
// Check if the table already exists
if ($setup->getConnection()->isTableExists($tableName) == true) {
$setup->getConnection()->addColumn(
$tableName,
'customily_text_default_value',
[
'type' => Table::TYPE_TEXT,
'length' => '250',
'nullable' => true,
'default' => '',
'comment' => 'Customily text default value'
]
);
}
}
$setup->endSetup();
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
namespace Customily\Categories\Ui\DataProvider\Product\Form\Modifier;
use Customily\Categories\Helper\CustomilyHelper;
use Magento\Catalog\Model\Locator\LocatorInterface;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Catalog\Model\ProductOptions\ConfigInterface;
use Magento\Catalog\Model\Config\Source\Product\Options\Price as ProductOptionsPrice;
use Magento\Framework\UrlInterface;
use Magento\Framework\Stdlib\ArrayManager;
use Magento\Ui\Component\Form\Field;
use Magento\Ui\Component\Form\Element\Select;
use Magento\Ui\Component\Form\Element\DataType\Text;
use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions as ProductCustomOptions;
/**
* Data provider for "Customizable Options" panel
*
* @api
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @since 101.0.0
*/
class CustomOptions extends ProductCustomOptions
{
/**
* CUSTOMILY FIELDS
*/
const FIELD_CUSTOMILY_FUNCTIONS = 'customily_functions';
const FIELD_CUSTOMILY_CONDITIONS = 'customily_conditions';
const FIELD_CUSTOMILY_IS_SWATCH = 'customily_is_swatch';
const FIELD_CUSTOMILY_SWATCH_SETTINGS = 'customily_swatch_settings';
const FIELD_CUSTOMILY_TEXT_DEFAULT_VALUE = 'customily_text_default_value';
const FIELD_CUSTOMILY_TEXT_TRANSFORM = 'customily_text_transform';
const FIELD_CUSTOMILY_IMAGE_MIN_SIZE_X = 'customily_image_min_size_x';
const FIELD_CUSTOMILY_IMAGE_MIN_SIZE_Y = 'customily_image_min_size_y';
/* @var \Customily\Categories\Helper\CustomilyHelper */
private $helper;
private $isCustomlyEnabled;
private $isSwatchesEnabled;
/**#@-*/
/**
* CustomOptions constructor.
* @param LocatorInterface $locator
* @param StoreManagerInterface $storeManager
* @param ConfigInterface $productOptionsConfig
* @param ProductOptionsPrice $productOptionsPrice
* @param UrlInterface $urlBuilder
* @param ArrayManager $arrayManager
*/
public function __construct(
LocatorInterface $locator,
StoreManagerInterface $storeManager,
ConfigInterface $productOptionsConfig,
ProductOptionsPrice $productOptionsPrice,
UrlInterface $urlBuilder,
ArrayManager $arrayManager,
CustomilyHelper $helper
) {
parent::__construct(
$locator, $storeManager, $productOptionsConfig,
$productOptionsPrice, $urlBuilder, $arrayManager
);
$this->helper = $helper;
$settings = $this->helper->getCustomilyConfig();
$this->isCustomlyEnabled = $settings['enable'] ?? false;
$this->isSwatchesEnabled = $settings['enable_swatches'] ?? false;
}
/**
* Get config for "Option Type" field
*
* @param int $sortOrder
* @return array
* @since 101.0.0
*/
protected function getTypeFieldConfig($sortOrder)
{
if ($this->isCustomlyEnabled === '1') {
$groupsConfig = [
'text' => [
'values' => ['field', 'area'],
'indexes' => [
static::CONTAINER_TYPE_STATIC_NAME,
static::FIELD_PRICE_NAME,
static::FIELD_PRICE_TYPE_NAME,
static::FIELD_SKU_NAME,
static::FIELD_CUSTOMILY_FUNCTIONS,
static::FIELD_CUSTOMILY_CONDITIONS,
static::FIELD_MAX_CHARACTERS_NAME,
static::FIELD_CUSTOMILY_TEXT_DEFAULT_VALUE,
static::FIELD_CUSTOMILY_TEXT_TRANSFORM
]
],
'file' => [
'values' => ['file'],
'indexes' => [
static::CONTAINER_TYPE_STATIC_NAME,
static::FIELD_PRICE_NAME,
static::FIELD_PRICE_TYPE_NAME,
static::FIELD_SKU_NAME,
static::FIELD_CUSTOMILY_FUNCTIONS,
static::FIELD_CUSTOMILY_CONDITIONS,
static::FIELD_FILE_EXTENSION_NAME,
static::FIELD_CUSTOMILY_IMAGE_MIN_SIZE_X,
static::FIELD_CUSTOMILY_IMAGE_MIN_SIZE_Y,
static::FIELD_IMAGE_SIZE_X_NAME,
static::FIELD_IMAGE_SIZE_Y_NAME
]
],
$this->isSwatchesEnabled === '1' ? 'swatches' : 'radio' => [
'values' => ['radio'],
'indexes' => $this->isSwatchesEnabled === '1' ? [
static::FIELD_CUSTOMILY_FUNCTIONS,
static::FIELD_CUSTOMILY_CONDITIONS,
static::FIELD_CUSTOMILY_IS_SWATCH,
static::FIELD_CUSTOMILY_SWATCH_SETTINGS,
static::GRID_TYPE_SELECT_NAME
] : [
static::FIELD_CUSTOMILY_FUNCTIONS,
static::FIELD_CUSTOMILY_CONDITIONS,
static::GRID_TYPE_SELECT_NAME
]
],
'select' => [
'values' => ['drop_down', 'checkbox', 'multiple'],
'indexes' => [
static::FIELD_CUSTOMILY_FUNCTIONS,
static::FIELD_CUSTOMILY_CONDITIONS,
static::GRID_TYPE_SELECT_NAME
]
],
'data' => [
'values' => ['date', 'date_time', 'time'],
'indexes' => [
static::CONTAINER_TYPE_STATIC_NAME,
static::FIELD_PRICE_NAME,
static::FIELD_PRICE_TYPE_NAME,
static::FIELD_SKU_NAME
]
]
];
} else {
$groupsConfig = [
'text' => [
'values' => ['field', 'area'],
'indexes' => [
static::CONTAINER_TYPE_STATIC_NAME,
static::FIELD_PRICE_NAME,
static::FIELD_PRICE_TYPE_NAME,
static::FIELD_SKU_NAME,
static::FIELD_MAX_CHARACTERS_NAME
]
],
'file' => [
'values' => ['file'],
'indexes' => [
static::CONTAINER_TYPE_STATIC_NAME,
static::FIELD_PRICE_NAME,
static::FIELD_PRICE_TYPE_NAME,
static::FIELD_SKU_NAME,
static::FIELD_FILE_EXTENSION_NAME,
static::FIELD_IMAGE_SIZE_X_NAME,
static::FIELD_IMAGE_SIZE_Y_NAME
]
],
'select' => [
'values' => ['drop_down', 'radio', 'checkbox', 'multiple'],
'indexes' => [
static::GRID_TYPE_SELECT_NAME
]
],
'data' => [
'values' => ['date', 'date_time', 'time'],
'indexes' => [
static::CONTAINER_TYPE_STATIC_NAME,
static::FIELD_PRICE_NAME,
static::FIELD_PRICE_TYPE_NAME,
static::FIELD_SKU_NAME
]
]
];
}
return [
'arguments' => [
'data' => [
'config' => [
'label' => __('Option Type'),
'componentType' => Field::NAME,
'formElement' => Select::NAME,
'component' => 'Magento_Catalog/js/custom-options-type',
'elementTmpl' => 'ui/grid/filters/elements/ui-select',
'selectType' => 'optgroup',
'dataScope' => static::FIELD_TYPE_NAME,
'dataType' => Text::NAME,
'sortOrder' => $sortOrder,
'options' => $this->getProductOptionTypes(),
'disableLabel' => true,
'multiple' => false,
'selectedPlaceholders' => [
'defaultPlaceholder' => __('-- Please select --'),
],
'validation' => [
'required-entry' => true
],
'groupsConfig' => $groupsConfig
]
]
]
];
}
/**
* Get options for drop-down control with product option types
*
* @return array
* @since 101.0.0
*/
public function getProductOptionTypes()
{
$options = [];
$groupIndex = 0;
foreach ($this->productOptionsConfig->getAll() as $option) {
if (
$this->isCustomlyEnabled === '1' &&
$this->isSwatchesEnabled === '1' &&
strtolower($option['label']) == 'select'
) {
$group = [
'value' => $groupIndex,
'label' => 'Swatches',
'optgroup' => []
];
$group['optgroup'][] = [
'label' => 'Swatch',
'value' => 'radio'
];
$options[] = $group;
$groupIndex++;
}
$group = [
'value' => $groupIndex,
'label' => $option['label'],
'optgroup' => []
];
foreach ($option['types'] as $type) {
if (
$type['disabled'] ||
(
$this->isCustomlyEnabled === '1' &&
$this->isSwatchesEnabled === '1' &&
$type['name'] == 'radio'
)
) {
continue;
}
$group['optgroup'][] = [
'label' => $type['label'],
'value' => $type['name']
];
}
if (count($group['optgroup'])) {
$options[] = $group;
$groupIndex++;
}
}
return $options;
}
}
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
* Date: 24/11/2020
*/
namespace Customily\Categories\Util;
use Customily\Categories\Api\Client\ApiClient;
use Customily\Categories\Libraries\FontLib\Font;
use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface;
use Magento\Catalog\Model\Product\OptionFactory;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Filesystem;
use Psr\Log\LoggerInterface;
use Customily\Categories\Helper\CustomilyHelper;
class ManageOptions
{
const CUSTOMILY_DOWNLOAD_DIR = 'catalog/product/customily/download/';
private $CDN_CUSTOMILY_ENDPOINT;
private $helper;
private $apiClient;
private $settings;
private $productRepository;
private $optionRepository;
private $optionFactory;
private $resourceConnection;
private $downloadDirectory;
private $downloadPath;
private $logger;
private $generatedLibraries = [];
private $generatedCategories = [];
private $generatedThumbnails = [];
private $options = [];
private $swatchMaxSize;
/**
* ManageOptions constructor.
* @param CustomilyHelper $helper
* @param ApiClient $apiClient
* @param ProductRepositoryInterface $productRepository
* @param ProductCustomOptionRepositoryInterface $optionRepository
* @param OptionFactory $optionFactory
* @param ResourceConnection $resourceConnection
* @param LoggerInterface $logger
* @param Filesystem $fileSystem
* @throws FileSystemException
*/
public function __construct(
CustomilyHelper $helper,
ApiClient $apiClient,
ProductRepositoryInterface $productRepository,
ProductCustomOptionRepositoryInterface $optionRepository,
OptionFactory $optionFactory,
ResourceConnection $resourceConnection,
LoggerInterface $logger,
Filesystem $fileSystem
)
{
$this->helper = $helper;
$this->apiClient = $apiClient;
$this->logger = $logger;
$this->settings = $this->helper->getCustomilyConfig();
$this->productRepository = $productRepository;
$this->optionRepository = $optionRepository;
$this->resourceConnection = $resourceConnection;
$this->optionFactory = $optionFactory;
$this->downloadDirectory = $fileSystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->CDN_CUSTOMILY_ENDPOINT = isset($this->settings['cdn_endpoint']) && !empty($this->settings['cdn_endpoint'])
? $this->settings['cdn_endpoint']
: 'https://cdn.customily.com';
$this->swatchMaxSize = isset($this->settings['swatches_max_size']) && !empty($this->settings['swatches_max_size'])
? $this->settings['swatches_max_size']
: 120;
}
/**
* @param $productId
* @param $templateId
* @param $lastSortOrder
* @return bool
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function optionsFromTemplate($productId, $templateId, $lastSortOrder)
{
$result = false;
$this->downloadPath = self::CUSTOMILY_DOWNLOAD_DIR . uniqid();
$downloadFullPath = $this->downloadDirectory->getAbsolutePath($this->downloadPath);
/* @var \Magento\Catalog\Model\Product $product */
$product = $this->productRepository->getById($productId);
$storeId = $product->getStoreId();
try {
if (!file_exists($downloadFullPath)) {
mkdir($downloadFullPath, 0777, true);
}
$this->createOptions($templateId);
$this->options = $this->helper->shellSort($this->options, 'sort_order');
$this->logger->debug('Importing options count: ' . count($this->options));
$this->deleteExistingOptions($product, $templateId);
$index = $lastSortOrder + 1;
foreach ($this->options as $data) {
$data['sort_order'] = $index;
$data['customily_imported_from_template_id'] = $templateId;
/* @var \Magento\Catalog\Model\Product\Option $option */
$option = $this->optionFactory->create();
$option->setProduct($product)->setStoreId($storeId)->addData($data);
$this->optionRepository->save($option);
$index++;
}
$attributes = [];
$attributes['product_customization_id'] = $templateId;
$attributes['custom_product'] = '1';
$collapsibleOptions = $product->getCustomAttribute('collapsible_options');
$attributes['collapsible_options'] = isset($collapsibleOptions) && $collapsibleOptions->getValue() == 1 ? '1' : '0';
$stickyPreview = $product->getCustomAttribute('sticky_preview');
$attributes['sticky_preview'] = isset($stickyPreview) && $stickyPreview->getValue() == 1 ? '1' : '0';
$previewLink = $product->getCustomAttribute('preview_link_in_email');
$attributes['preview_link_in_email'] = isset($previewLink) && $previewLink->getValue() == 1 ? '1' : '0';
$productionFileLink = $product->getCustomAttribute('production_file_link_in_email');
$attributes['production_file_link_in_email'] = isset($productionFileLink) && $productionFileLink->getValue() == 1 ? '1' : '0';
$this->helper->updateProductsAttributes([$product->getId()], $attributes);
$this->deleteOptionsBySku($product->getSku(), $storeId);
$result = true;
} catch (\Exception $ex) {
$this->deleteExistingOptions($product, $templateId);
$this->logger->error($ex->getTraceAsString());
}
if (file_exists($downloadFullPath)) {
try {
$this->removeDirectory($downloadFullPath);
} catch (\Exception $ex) {
$this->logger->debug($ex->getTraceAsString());
}
}
return $result;
}
/**
* @param $templateId
*/
public function createOptions($templateId)
{
$template = $this->apiClient->getProduct($templateId);
if (isset($template) && isset($template['preview'])) {
$textsPreview = [];
if (isset($template['preview']['textsPreview']) && count($template['preview']['textsPreview']) > 0) {
$textsPreview = array_merge($textsPreview, $template['preview']['textsPreview']);
}
if (
isset($template['preview']['circularTextsPreview']) &&
count($template['preview']['circularTextsPreview']) > 0
) {
$textsPreview = array_merge($textsPreview, $template['preview']['circularTextsPreview']);
}
foreach ($textsPreview as $textPreview) {
$elementName = isset($textPreview['name']) && !empty($textPreview['name'])
? $textPreview['name']
: "Text ${textPreview['id']}";
$this->generateTextOption($textPreview['id'], $elementName);
$this->generateFontOption($textPreview);
$this->generateColorOption($textPreview, 'color');
}
$imagesPreview = [];
if (
isset($template['preview']['imagePlaceHoldersPreview']) &&
count($template['preview']['imagePlaceHoldersPreview']) > 0
) {
$imagesPreview = array_merge($imagesPreview, $template['preview']['imagePlaceHoldersPreview']);
}
foreach ($imagesPreview as $imagePreview) {
$this->generateImageOption($imagePreview);
}
$vectorsPreview = [];
if (isset($template['preview']['vectorEPSPreview']) && count($template['preview']['vectorEPSPreview']) > 0) {
$vectorsPreview = array_merge($vectorsPreview, $template['preview']['vectorEPSPreview']);
}
foreach ($vectorsPreview as $vectorPreview) {
$this->generateVectorOption($vectorPreview);
}
}
}
/**
* @param $url
* @return string
*/
public function getFilePath($url) {
$path = parse_url($url, PHP_URL_PATH);
$fileName = $this->helper->guidv4();
$extension = pathinfo($path, PATHINFO_EXTENSION);
return $this->downloadDirectory->getAbsolutePath("/{$this->downloadPath}/{$fileName}.{$extension}");
}
/**
* @param $url
* @return string|null
*/
public function downloadFile($url)
{
try {
$fileName = $this->getFilePath($url);
$response = $this->apiClient->downloadFile($url, $fileName);
if ($response->getStatusCode() == 200) {
return $fileName;
}
} catch (\Exception $ex) {
$this->logger->debug($ex->getTraceAsString());
}
return null;
}
/**
* @param $width
* @param $height
* @param $size
* @return array|float[]|int[]
*/
public function calculateSize($width, $height, $size) {
$ratio = $width / $height;
if ($width > $height) {
$newWidth = $size;
$newHeight = $size / $ratio;
} else {
$newWidth = $size * $ratio;
$newHeight = $size;
}
return [
'width' => $newWidth,
'height' => $newHeight
];
}
/**
* @param $file
* @param $size
* @return null
*/
public function resizeImage($file, $size)
{
try {
list($width, $height) = getimagesize($file);
$newSize = $this->calculateSize($width, $height, $size);
$extension = pathinfo($file, PATHINFO_EXTENSION);
$sourceFile = $extension == 'jpg' || $extension == 'jpeg'
? imagecreatefromjpeg($file)
: imagecreatefrompng($file);
$destinationFile = imagecreatetruecolor($newSize['width'], $newSize['height']);
imagealphablending($destinationFile, false);
imagesavealpha($destinationFile,true);
imagecopyresampled(
$destinationFile,
$sourceFile,
0,
0,
0,
0,
$newSize['width'],
$newSize['height'],
$width,
$height
);
$this->saveImage($destinationFile, $file);
return $file;
} catch (\Exception $ex) {
$this->logger->debug($ex->getTraceAsString());
return null;
}
}
/**
* @param $file
* @param $size
*/
public function resizeSvg($file, $size) {
$dom = new \DOMDocument('1.0', 'utf-8');
$dom->load($file);
$svg = $dom->documentElement;
if (!$svg->hasAttribute('viewBox')) {
$pattern = '/^(\d*\.\d+|d+)(px)?$/';
$interpretable = preg_match($pattern, $svg->getAttribute('width'), $width) &&
preg_match($pattern, $svg->getAttribute('height'), $height);
if ($interpretable) {
$viewBox = implode(' ', [0, 0, $width[0], $height[0]]);
$svg->setAttribute('viewBox', $viewBox);
} else {
$this->logger->debug('Error resizing SVG file: viewBox is dependent on environment.');
return false;
}
}
$size = $this->calculateSize(
(int)$svg->getAttribute('width'),
(int)$svg->getAttribute('height'),
$size
);
$svg->setAttribute('width', $size['width']);
$svg->setAttribute('height', $size['height']);
$dom->save($file);
return true;
}
/**
* @param $resource
* @param $file
* @return bool
*/
public function saveImage($resource, $file)
{
$extension = pathinfo($file, PATHINFO_EXTENSION);
if ($extension == 'jpg' || $extension == 'jpeg') {
header('Content-Type: image/jpeg');
$result = imagejpeg($resource, $file);
} else {
header('Content-Type: image/png');
$result = imagepng($resource, $file);
}
return $result;
}
/**
* @param $file
* @param string $fileType
* @return mixed|string|null
*/
public function uploadImage($file, $fileType = 'image')
{
if ($this->settings['save_files_in'] == 'magento' || $fileType == 'svg') {
return $this->apiClient->uploadImageToMagento($file, $fileType);
} else {
return $this->apiClient->uploadImageToCustomily($file);
}
}
/**
* @param $type
* @param $elementId
* @param $title
*/
public function generateTextOption($elementId, $title)
{
$functions = [
'id' => 0,
'type' => 'text',
'element_id' => "{$elementId}"
];
$this->options [] = [
'title' => $title,
'price_type' => 'fixed',
'price' => '0.00',
'type' => isset($element['multiline']) && $element['multiline'] == 1 ? 'area' : 'field',
'is_require' => 0,
'sort_order' => $elementId * 100000,
'customily_text_default_value' => '',
'customily_functions' => '[' . json_encode($functions) . ']'
];
}
/**
* @param $textPreview
*/
public function generateFontOption($textPreview)
{
$multiply = 100000;
$plus = 5000;
if (isset($textPreview['fontLibraryId']) && !empty($textPreview['fontLibraryId'])) {
$positions = $this->apiClient->getProductLibraryElementPositions($textPreview['fontLibraryId']);
if (count($positions) > 1) {
$categories = $this->apiClient->getProductLibraryCategories($textPreview['fontLibraryId']);
$libraryName = $this->apiClient->getProductLibraryName($textPreview['fontLibraryId']);
if (count($categories) > 1) {
$option = $this->createCategoryOption(
'font',
$textPreview['id'],
$categories,
$libraryName,
$multiply,
$plus
);
$this->populateCategories(
$categories,
$option,
$textPreview,
$multiply,
$textPreview['fontLibraryId'],
'font',
'Text'
);
} else {
if (isset($libraryName) && !empty($libraryName)) {
$fontName = $libraryName;
} else if (isset($textPreview['name']) && !empty($textPreview['name'])) {
$fontName = "{$textPreview['name']} Font";
} else {
$fontName = "Font {$textPreview['id']}";
}
$option = $this->createDynamicOption($textPreview['id'], $fontName, $multiply, $plus, 'font');
$elements = $this->generateOptionsFromLibrary('font', $textPreview['fontLibraryId'], $positions);
$option['values'] = $this->createDynamicValues($textPreview['id'], $elements, 'font');
$this->options[] = $option;
}
}
} else if (isset($textPreview['fontsMap']) && !empty($textPreview['fontsMap'])) {
$fontsMap = json_decode($textPreview['fontsMap'], true);
if (count($fontsMap) > 1) {
$fontName = isset($textPreview['name']) && !empty($textPreview['name'])
? "{$textPreview['name']} Font"
: "Font {$textPreview['id']}";
$option = $this->createDynamicOption($textPreview['id'], $fontName, $multiply, $plus, 'font');
$elements = [];
$index = 0;
foreach ($fontsMap as $font) {
$index++;
$elements[] = [
'name' => "Text Font {$index}",
'position' => $font[0],
'path' => $font[1]
];
}
$option['values'] = $this->createDynamicValues($textPreview['id'], $elements, 'font');
$this->options[] = $option;
}
}
}
/**
* @param $previewElement
* @param $optionType
*/
public function generateColorOption($previewElement, $optionType)
{
$multiply = 100000;
$plus = 0;
$placeholderType = null;
switch ($optionType) {
case 'color':
$placeholderType = 'Text';
$plus = 15000;
break;
case 'image_color':
$placeholderType = 'Image';
$plus = 35000;
break;
case 'vector_color':
$placeholderType = 'Vector';
$plus = 65000;
break;
}
if (isset($previewElement['colorLibraryId']) && !empty($previewElement['colorLibraryId'])) {
$positions = $this->apiClient->getProductLibraryElementPositions($previewElement['colorLibraryId']);
if (count($positions) > 1) {
$categories = $this->apiClient->getProductLibraryCategories($previewElement['colorLibraryId']);
$libraryName = $this->apiClient->getProductLibraryName($previewElement['colorLibraryId']);
if (count($categories) > 1) {
$option = $this->createCategoryOption(
'color',
$previewElement['id'],
$categories,
$libraryName,
$multiply,
$plus
);
$this->populateCategories(
$categories,
$option,
$previewElement,
$multiply,
$previewElement['colorLibraryId'],
'color',
$placeholderType
);
} else {
if (isset($libraryName) && !empty($libraryName)) {
$colorName = $libraryName;
} else if (isset($previewElement['name']) && !empty($previewElement['name'])) {
$colorName = "{$previewElement['name']} Color";
} else {
$colorName = "{$placeholderType} Color ${$previewElement['id']}";
}
$option = $this->createDynamicOption(
$previewElement['id'],
$colorName,
$multiply,
$plus,
$optionType
);
$elements = $this->generateOptionsFromLibrary(
'color',
$previewElement['colorLibraryId'],
$positions
);
$option['values'] = $this->createDynamicValues($previewElement['id'], $elements, $optionType);
$this->options[] = $option;
}
}
} else if (isset($previewElement['colors']) && count($previewElement['colors']) > 1) {
$colorName = isset($previewElement['name']) && !empty($previewElement['name'])
? "{$previewElement['name']} Color"
: "{$placeholderType} Color ${$previewElement['id']}";
$elements = [];
foreach ($previewElement['colors'] as $color) {
$elementName = isset($color['Name']) && !empty($color['Name']) ? $color['Name'] : '';
$elements[] = [
'type' => 'color',
'position' => $color['position'],
'hex' => $color['hex'],
'name' => $elementName,
'id' => $color['ColorId']
];
}
$option = $this->createDynamicOption($previewElement['id'], $colorName, $multiply, $plus, $optionType);
$option['values'] = $this->createDynamicValues($previewElement['id'], $elements, $optionType);
$this->options[] = $option;
} else if (
$optionType == 'color' &&
isset($previewElement['fontColorsMap']) &&
!empty($previewElement['fontColorsMap'])
) {
$colorsMap = json_decode($previewElement['fontColorsMap'], true);
if (count($colorsMap) > 1) {
$colorName = isset($previewElement['name']) && !empty($previewElement['name'])
? "{$previewElement['name']} Color"
: "Color {$previewElement['id']}";
$option = $this->createDynamicOption($previewElement['id'], $colorName, $multiply, $plus, 'color');
$elements = [];
$index = 0;
foreach ($colorsMap as $color) {
$index++;
$elements[] = [
'name' => "Text Color {$index}",
'position' => $color[0],
'hex' => $color[1]['hex']
];
}
$option['values'] = $this->createDynamicValues($previewElement['id'], $elements, 'color');
$this->options[] = $option;
}
}
}
/**
* @param $imagePreview
*/
public function generateImageOption($imagePreview)
{
$multiply = 100000;
$plus = 30000;
$isDynamic = false;
if (isset($imagePreview['imageLibraryId']) && !empty($imagePreview['imageLibraryId'])) {
$positions = $this->apiClient->getProductLibraryElementPositions($imagePreview['imageLibraryId']);
if (count($positions) > 1) {
$categories = $this->apiClient->getProductLibraryCategories($imagePreview['imageLibraryId']);
$libraryName = $this->apiClient->getProductLibraryName($imagePreview['imageLibraryId']);
if (count($categories) > 1) {
$option = $this->createCategoryOption(
'dynamic_image',
$imagePreview['id'],
$categories,
$libraryName,
$multiply,
$plus
);
$this->populateCategories(
$categories,
$option,
$imagePreview,
$multiply,
$imagePreview['imageLibraryId'],
'dynamic_image',
'Image'
);
} else {
if (isset($imagePreview['name']) && !empty($imagePreview['name'])) {
$imageName = $imagePreview['name'];
} else if (isset($libraryName) && !empty($libraryName)) {
$imageName = $libraryName;
} else {
$imageName = "Image {$imagePreview['id']}";
}
$option = $this->createDynamicOption(
$imagePreview['id'],
$imageName,
$multiply,
$plus,
'dynamic_image'
);
$elements = $this->generateOptionsFromLibrary(
'dynamic_image',
$imagePreview['imageLibraryId'],
$positions
);
$option['values'] = $this->createDynamicValues(
$imagePreview['id'],
$elements,
'dynamic_image'
);
$this->options[] = $option;
}
$isDynamic = true;
}
} else if (isset($imagePreview['dynamicImagesPath']) && !empty($imagePreview['dynamicImagesPath'])) {
$dynamicImages = json_decode($imagePreview['dynamicImagesPath'], true);
if (count($dynamicImages) > 1) {
$imageName = isset($imagePreview['name']) && !empty($imagePreview['name'])
? $imagePreview['name']
: "Image {$imagePreview['id']}";
$option = $this->createDynamicOption(
$imagePreview['id'],
$imageName,
$multiply,
$plus,
'dynamic_image'
);
$elements = [];
$index = 0;
foreach ($dynamicImages as $image) {
$index++;
$elements[] = [
'name' => "Image {$index}",
'position' => $image[0],
'path' => $image[1]
];
}
$option['values'] = $this->createDynamicValues($imagePreview['id'], $elements, 'dynamic_image');
$this->options[] = $option;
}
$isDynamic = true;
}
if (!$isDynamic) {
$imageName = isset($imagePreview['name']) && !empty($imagePreview['name'])
? $imagePreview['name']
: "Image {$imagePreview['id']}";
$this->generateFileUploadOption('file', $imagePreview['id'], $imageName);
}
if (
(isset($imagePreview['colorLibraryId']) && !empty($imagePreview['colorLibraryId'])) ||
count($imagePreview['colors']) > 1
) {
$this->generateColorOption($imagePreview, 'image_color');
}
}
/**
* @param $vectorPreview
*/
public function generateVectorOption($vectorPreview)
{
$multiply = 100000;
$plus = 60000;
$isDynamic = false;
if (isset($vectorPreview['vectorLibraryId']) && !empty($vectorPreview['vectorLibraryId'])) {
$positions = $this->apiClient->getProductLibraryElementPositions($vectorPreview['vectorLibraryId']);
if (count($positions) > 1) {
$categories = $this->apiClient->getProductLibraryCategories($vectorPreview['vectorLibraryId']);
$libraryName = $this->apiClient->getProductLibraryName($vectorPreview['vectorLibraryId']);
if (count($categories) > 1) {
$option = $this->createCategoryOption(
'dynamic_vector',
$vectorPreview['id'],
$categories,
$libraryName,
$multiply,
$plus
);
$this->populateCategories(
$categories,
$option,
$vectorPreview,
$multiply,
$vectorPreview['vectorLibraryId'],
'dynamic_vector',
'Vector'
);
} else {
if (isset($vectorPreview['name']) && !empty($vectorPreview['name'])) {
$vectorName = $vectorPreview['name'];
} else if (isset($libraryName) && !empty($libraryName)) {
$vectorName = $libraryName;
} else {
$vectorName = "Vector {$vectorPreview['id']}";
}
$option = $this->createDynamicOption(
$vectorPreview['id'],
$vectorName,
$multiply,
$plus,
'dynamic_vector'
);
$elements = $this->generateOptionsFromLibrary(
'dynamic_vector',
$vectorPreview['vectorLibraryId'],
$positions
);
$option['values'] = $this->createDynamicValues(
$vectorPreview['id'],
$elements,
'dynamic_vector'
);
$this->options[] = $option;
}
$isDynamic = true;
}
} else if (count($vectorPreview['vectors']) > 1) {
$dynamicVectors = $vectorPreview['vectors'];
$plus = min(array_map(function ($el) {
return $el['position'];
}, $dynamicVectors)) > 0 ? 0 : 1;
$elements = [];
foreach ($dynamicVectors as $vector) {
$position = (int)$vector['position'] + $plus;
$elements[] = [
'name' => "Vector {$position}",
'position' => $position,
'path' => isset($vector['svgPath']) && !empty($vector['svgPath'])
? $vector['svgPath']
: $vector['ThumbnailPath']
];
}
$vectorName = isset($vectorPreview['name']) && !empty($vectorPreview['name'])
? $vectorPreview['name']
: "Vector {$vectorPreview['id']}";
$option = $this->createDynamicOption(
$vectorPreview['id'],
$vectorName,
$multiply,
$plus,
'dynamic_vector'
);
$option['values'] = $this->createDynamicValues($vectorPreview['id'], $elements, 'dynamic_vector');
$this->options[] = $option;
$isDynamic = true;
}
if (!$isDynamic && $vectorPreview['allowUserUpload']) {
$vectorName = isset($vectorPreview['name']) && !empty($vectorPreview['name'])
? $vectorPreview['name']
: "Vector {$vectorPreview['id']}";
$this->generateFileUploadOption('vector', $vectorPreview['id'], $vectorName);
}
if (
(isset($vectorPreview['colorLibraryId']) && !empty($vectorPreview['colorLibraryId'])) ||
count($vectorPreview['colors']) > 1
) {
$this->generateColorOption($vectorPreview, 'vector_color');
}
}
/**
* @param $type
* @param $elementId
* @param $title
*/
public function generateFileUploadOption($type, $elementId, $title = '')
{
$functions = [
'id' => 0,
'type' => $type,
'element_id' => "{$elementId}"
];
$title = isset($title) && !empty($title) ? $title : "File Upload {$elementId}";
$this->options [] = [
'title' => $title,
'price_type' => 'fixed',
'price' => '0.00',
'type' => 'file',
'file_extension' => $type == 'file' ? 'png, jpg, jpeg, gif' : 'eps, pdf, svg',
'sort_order' => $elementId * 1000,
'is_require' => 0,
'customily_functions' => '[' . json_encode($functions) . ']'
];
}
/**
* @param $type
* @param $elementId
* @param $values
* @param $title
* @param $multiply
* @param $plus
* @return array
*/
public function createCategoryOption($type, $elementId, $values, $title, $multiply, $plus)
{
$option = [
'title' => $title,
'price_type' => 'fixed',
'price' => '0.00',
'sort_order' => $elementId * $multiply + $plus,
'is_require' => 0
];
if ($type == 'dynamic_image' || $type == 'dynamic_vector') {
$option['type'] = 'radio';
$option['customily_is_swatch'] = 1;
$option['customily_swatch_settings'] = json_encode([
'width' => 45,
'height' => 45,
'align' => 'left',
'show_tooltip' => true,
'show_price' => false,
'border' => true,
'rounded' => false,
'paging' => false,
'rows' => 1,
'cols' => 5
]);
} else {
$option['type'] = 'drop_down';
}
$optionValues = [];
$index = 1;
$defaultMarked = false;
foreach ($values as $value) {
$optionValue = [
'title' => isset($value['Name']) && !empty($value['Name']) ? $value['Name'] : "Value {$index}",
'price' => "0.00",
'price_type' => 'fixed',
'sort_order' => $index,
'customily_is_default' => $defaultMarked ? '0' : '1'
];
if (!$defaultMarked) {
$defaultMarked = true;
}
if ($type == 'dynamic_image' || $type == 'dynamic_vector') {
$optionValue['customily_index_thumbnail'] = $this->getThumbnailAndInfo($type, $value['Path']);
}
$optionValues[] = $optionValue;
$index++;
}
$option['values'] = $optionValues;
$this->options [] = $option;
return $option;
}
/**
* @param $categories
* @param $categoryOption
* @param $previewElement
* @param $multiply
* @param $libraryId
* @param $libraryType
* @param $placeholderType
* @return bool
*/
public function populateCategories(
$categories,
$categoryOption,
$previewElement,
$multiply,
$libraryId,
$libraryType,
$placeholderType
) {
if (
$placeholderType == 'Text' &&
($libraryType == 'font' && !isset($previewElement['fontLibraryId'])) ||
($libraryType == 'color' && !isset($previewElement['colorLibraryId']))
) {
return false;
}
if ($libraryType == 'dynamic_image' && !isset($previewElement['imageLibraryId'])) {
return false;
}
if ($libraryType == 'dynamic_vector' && !isset($previewElement['vectorLibraryId'])) {
return false;
}
$index = 0;
foreach ($categories as $category) {
$conditions = [
'id' => 0,
'action' => 'show',
'watch_option' => $categoryOption['title'],
'expected_value' => $category['Name']
];
$elements = $this->generateOptionsFromLibraryCategory($libraryId, $category['CategoryId'], $libraryType);
$option = null;
$optionType = $libraryType;
$plus = 0;
switch ($libraryType) {
case 'font':
$plus = $index + 5002;
$optionType = 'font';
break;
case 'color':
if ($placeholderType == 'Text') {
$plus = 15002;
$optionType = 'color';
} else if ($placeholderType == 'Image') {
$plus = 35002;
$optionType = 'image_color';
} else {
$plus = 65002;
$optionType = 'vector_color';
}
break;
case 'dynamic_image':
$plus = $index + 30002;
break;
case 'dynamic_vector':
$plus = $index + 60002;
break;
}
$option = $this->createDynamicOption($previewElement['id'], $category['Name'], $multiply, $plus, $optionType);
$option['customily_conditions'] = '[' . json_encode($conditions) . ']';
$option['values'] = $this->createDynamicValues($previewElement['id'], $elements, $optionType, true);
$this->options[] = $option;
$index++;
}
return true;
}
/**
* @param $elementId
* @param $title
* @param $multiply
* @param $plus
* @param $type
* @return array
*/
public function createDynamicOption($elementId, $title, $multiply, $plus, $type)
{
$functions = [
'id' => 0,
'type' => $type,
'element_id' => "{$elementId}"
];
$swatchSettings = [
'width' => 45,
'height' => 45,
'align' => 'left',
'show_tooltip' => true,
'show_price' => false,
'border' => true,
'rounded' => false,
'paging' => false,
'rows' => 1,
'cols' => 5
];
return [
'title' => $title,
'price_type' => 'fixed',
'price' => '0.00',
'type' => 'radio',
'sort_order' => $elementId * $multiply + $plus,
'is_require' => 0,
'customily_functions' => '[' . json_encode($functions) . ']',
'customily_is_swatch' => 1,
'customily_swatch_settings' => json_encode($swatchSettings)
];
}
/**
* @param $elementId
* @param $values
* @param $optionType
* @param false $isCategory
* @return array
*/
public function createDynamicValues($elementId, $values, $optionType, $isCategory = false) {
$result = [];
$defaultMarked = !$isCategory;
foreach ($values as $value) {
$positions = [
'id' => 0,
'type' => $optionType,
'element_id' => "{$elementId}",
'position' => $value['position']
];
$optionValue = [
'price' => "0.00",
'price_type' => 'fixed',
'sort_order' => $value['position'],
'customily_index_positions' => '[' . json_encode($positions) . ']',
'customily_is_default' => $defaultMarked ? '0' : '1'
];
if (!$defaultMarked) {
$defaultMarked = true;
}
switch ($optionType) {
case 'font':
{
$optionValue['title'] = !empty($value['name']) ? $value['name'] : null;
if (isset($value['path']) && !empty($value['path'])) {
$info = $this->getThumbnailAndInfo($optionType, $value['path']);
$optionValue['title'] = isset($optionValue['title']) && !empty($optionValue['title'])
? $optionValue['title']
: $info['name'];
$optionValue['customily_index_thumbnail'] = $info['url'];
}
break;
}
case 'dynamic_image':
case 'dynamic_vector':
{
$optionValue['title'] = !empty($value['name']) ? $value['name'] : "Value {$value['position']}";
if (isset($value['path']) && !empty($value['path'])) {
$optionValue['customily_index_thumbnail'] = $this->getThumbnailAndInfo(
$optionType,
$value['path']
);
}
break;
}
case 'color':
case 'image_color':
case 'vector_color':
{
$optionValue['title'] = !empty($value['name']) ? $value['name'] : "Color {$value['position']}";
if (isset($value['hex'])) {
$optionValue['customily_index_color'] = $value['hex'];
}
break;
}
}
$result[] = $optionValue;
}
return $result;
}
/**
* @param $type
* @param $libraryId
* @param $positions
* @return array|mixed
*/
public function generateOptionsFromLibrary($type, $libraryId, $positions)
{
foreach ($this->generatedLibraries as $library) {
if (isset($library['id']) && $library['id'] === $libraryId) {
return $library['values'];
}
}
$values = [];
$positions = count($positions) > 1 ? $positions : $this->apiClient->getProductLibraryElementPositions($libraryId);
if (count($positions) > 1) {
foreach ($positions as $position) {
$libraryElement = $this->apiClient->getProductLibraryElementAtPosition($libraryId, $position);
if (isset($libraryElement)) {
$elementName = isset($libraryElement['Name']) && !empty($libraryElement['Name'])
? $libraryElement['Name']
: '';
switch ($type) {
case 'font':
{
$values[] = [
'type' => 'font',
'position' => $libraryElement['position'],
'path' => $libraryElement['Path'],
'libraryId' => $libraryId,
'name' => $elementName,
'id' => $libraryElement['FontId']
];
break;
}
case 'color':
{
$values[] = [
'type' => 'color',
'position' => $libraryElement['position'],
'hex' => $libraryElement['hex'],
'libraryId' => $libraryId,
'name' => $elementName,
'id' => $libraryElement['ColorId']
];
break;
}
case 'dynamic_image':
{
$values[] = [
'type' => 'image',
'position' => $libraryElement['position'],
'path' => isset($libraryElement['Path']) && !empty($libraryElement['Path'])
? $libraryElement['Path']
: $libraryElement['ThumbnailPath'],
'libraryId' => $libraryId,
'name' => $elementName,
'id' => $libraryElement['ImageId']
];
break;
}
case 'dynamic_vector':
{
$values[] = [
'type' => 'vector',
'position' => $libraryElement['position'],
'path' => isset($libraryElement['svgPath']) && !empty($libraryElement['svgPath'])
? $libraryElement['svgPath']
: $libraryElement['ThumbnailPath'],
'libraryId' => $libraryId,
'name' => $elementName,
'id' => $libraryElement['VectorId']
];
break;
}
}
}
}
}
$this->generatedLibraries[] = ['id' => $libraryId, 'type' => $type, 'values' => $values];
return $values;
}
/**
* @param $libraryId
* @param $categoryId
* @param $type
* @return array|mixed
*/
public function generateOptionsFromLibraryCategory($libraryId, $categoryId, $type) {
foreach ($this->generatedCategories as $category) {
if (isset($category['id']) && $category['id'] === $categoryId) {
return $category['values'];
}
}
$elements = $this->apiClient->getProductElementsByCategoryLibrary($libraryId, $categoryId);
$values = [];
foreach ($elements as $element) {
$value = [
'name' => isset($element['Name']) && !empty($element['Name']) ? $element['Name'] : '',
'position' => $element['position']
];
switch ($type) {
case 'font':
$value['path'] = $element['Path'];
break;
case 'color':
$value['hex'] = $element['hex'];
break;
case 'dynamic_image':
$value['path'] = isset($element['Path']) && !empty($element['Path'])
? $element['Path']
: $element['ThumbnailPath'];
break;
case 'dynamic_vector':
$value['path'] = isset($element['svgPath']) && !empty($element['svgPath'])
? $element['svgPath']
: $element['ThumbnailPath'];
break;
}
$values[] = $value;
}
$this->generatedCategories[] = ['id' => $categoryId, 'type' => $type, 'values' => $values];
return $values;
}
/**
* @param $type
* @param $path
* @return array|mixed|string|null
*/
public function getThumbnailAndInfo($type, $path)
{
$path = str_replace('/Content', '', $path);
$path = str_replace(' ', '%20', $path);
$result = null;
foreach ($this->generatedThumbnails as $thumbnail) {
if ($thumbnail[0] == $path) {
$result = $thumbnail[1];
break;
}
}
if (isset($result)) {
return $result;
} else {
switch ($type) {
case 'font':
{
$result = $this->fontToThumbnail($path);
break;
}
case 'dynamic_image':
{
$result = $this->createSwatchThumbnail($path);
break;
}
case 'dynamic_vector':
{
$result = $this->svgToThumbnail($path);
break;
}
}
if (isset($result)) {
$this->generatedThumbnails[] = [$path, $result];
}
}
return $result;
}
/**
* @param $url
* @return mixed|string|null
*/
public function createSwatchThumbnail($url)
{
try {
$file = $this->downloadFile("{$this->CDN_CUSTOMILY_ENDPOINT}{$url}");
if (isset($file) && $file !== false) {
$file = $this->resizeImage($file, (int)$this->swatchMaxSize);
if (isset($file) && $file !== false) {
return $this->uploadImage($file);
}
}
} catch (\Exception $ex) {
$this->logger->debug($ex->getTraceAsString());
}
return null;
}
/**
* @param $fontPath
* @return mixed|string|null
*/
public function fontToThumbnail($fontPath)
{
try {
$font = $this->downloadFile("{$this->CDN_CUSTOMILY_ENDPOINT}{$fontPath}");
$extension = pathinfo($font, PATHINFO_EXTENSION);
$text = 'Abc';
//create the image
$image = imagecreatetruecolor(100, 100);
//create some colors
$white = imagecolorallocate($image, 255, 255, 255);
$black = imagecolorallocate($image, 0, 0, 0);
imagefilledrectangle($image, 0, 0, 100 - 1, 100 - 1, $white);
//calculate text position
if ($extension == 'ttf') {
$textBox = imagettfbbox(30, 0, $font, $text);
} else {
$textBox = imageftbbox(30, 0, $font, $text);
}
$textWidth = abs(max($textBox[2], $textBox[4]));
$textHeight = abs(max($textBox[5], $textBox[7]));
$x = (imagesx($image) - $textWidth) / 2;
$y = (imagesy($image) + $textHeight) / 2;
//add the text
if ($extension == 'ttf') {
imagettftext($image, 30, 0, $x, $y, $black, $font, $text);
} else {
imagefttext($image, 30, 0, $x, $y, $black, $font, $text);
}
$file = str_replace(".{$extension}", '.png', $font);
if ($this->saveImage($image, $file)) {
$file = $this->uploadImage($file);
return ['name' => $this->getFontInfo($font), 'url' => $file];
}
} catch (\Exception $ex) {
$this->logger->debug($ex->getTraceAsString());
}
return null;
}
/**
* @param $svgPath
* @return mixed|string|null
*/
public function svgToThumbnail($svgPath)
{
try {
$svg = $this->downloadFile("{$this->CDN_CUSTOMILY_ENDPOINT}{$svgPath}");
if ($this->resizeSvg($svg, (int)$this->swatchMaxSize)) {
return $this->uploadImage($svg, 'svg');
}
} catch (\Exception $ex) {
$this->logger->debug($ex->getTraceAsString());
}
return null;
}
/**
* @param $dir
*/
private function removeDirectory($dir) {
try {
array_map('unlink', glob("$dir/*.*"));
rmdir($dir);
} catch (\Exception $ex) {
$this->logger->debug('Path: ' . $dir);
$this->logger->debug($ex->getTraceAsString());
}
}
/**
* @param $sku
* @param $storeId
* @return int
*/
public function deleteOptionsBySku($sku, $storeId) {
$options = $this->optionRepository->getList($sku);
$result = 0;
if (isset($options) && !empty($options)) {
foreach ($options as $option) {
$deleted = $this->deleteRecords('catalog_product_option_title', $storeId, $option->getOptionId());
$this->logger->debug(
"Deleting catalog_product_option_title <=> option: {$option->getTitle()}, rows affected: {$deleted}."
);
$deleted = $this->deleteRecords('catalog_product_option_price', $storeId, $option->getOptionId());
$this->logger->debug(
"Deleting catalog_product_option_price <=> option: {$option->getTitle()}, rows affected: {$deleted}."
);
$values = $option->getValues();
if (isset($values) && !empty($values)) {
foreach ($values as $value) {
$deleted = $this->deleteRecords(
'catalog_product_option_type_title',
$storeId,
$value->getOptionTypeId(),
'option_type_id'
);
$this->logger->debug(
"Deleting catalog_product_option_type_title <=> option: {$option->getTitle()}," .
" value: {$value->getTitle()}, rows affected: {$deleted}."
);
$deleted = $this->deleteRecords(
'catalog_product_option_type_price',
$storeId,
$value->getOptionTypeId(),
'option_type_id'
);
$this->logger->debug(
"Deleting catalog_product_option_type_price <=> option: {$option->getTitle()}," .
" price: {$value->getPrice()}, rows affected: {$deleted}."
);
}
}
$result++;
}
}
return $result;
}
/**
* @param $table
* @param $storeId
* @param $fieldValue
* @param string $fieldName
* @return int
*/
private function deleteRecords($table, $storeId, $fieldValue, $fieldName = 'option_id')
{
$tableName = $this->resourceConnection->getConnection()->getTableName($table);
$whereConditions = [
"{$fieldName} = ?" => $fieldValue,
'store_id > ?' => $storeId
];
return $this->resourceConnection->getConnection()->delete($tableName, $whereConditions);
}
/**
* @param \Magento\Catalog\Model\Product $product
* @param string $templateId
* @throws \Exception
*/
private function deleteExistingOptions($product, $templateId) {
try {
$options = $product->getOptions();
if (isset($options) && !empty($options)) {
/* @var \Magento\Catalog\Model\Product\Option $option */
foreach ($options as $option) {
if ($option['customily_imported_from_template_id'] == $templateId) {
$this->logger->debug(
"Deleting existing option before import from template <=> option: {$option->getTitle()}," .
" product: {$product->getName()}, templateId: {$templateId}."
);
$option->delete();
}
}
}
} catch (\Exception $ex) {
$this->logger->debug($ex->getTraceAsString());
}
}
/**
* @param $fontFile
* @return string|null
* @throws \Customily\Categories\Libraries\FontLib\Exception\FontNotFoundException
*/
private function getFontInfo($fontFile) {
try {
$font = Font::load($fontFile);
$font->parse();
$result = $font->getFontFullName();
$font->close();
return $result;
} catch (\Exception $e) {
return false;
}
}
}
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
* Date: 07/07/2020
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
<acl>
<resources>
<resource id="Magento_Backend::admin">
<resource id="Magento_Backend::stores">
<resource id="Magento_Backend::stores_settings">
<resource id="Magento_Config::config">
<!-- this resource id we can use in system.xml for section -->
<resource id="Customily_Categories::customily" title="Customily" sortOrder="80" />
</resource>
</resource>
</resource>
</resource>
</resources>
</acl>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
* Date: 09/12/2019
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- rewrite custom option provider CustomOptions.php -->
<preference for="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions" type="Customily\Categories\Ui\DataProvider\Product\Form\Modifier\CustomOptions" />
<!-- add customily fields to customizable options -->
<type name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions">
<plugin name="Customily_Categories_Custom_Options" type="Customily\Categories\Plugin\Catalog\Ui\DataProvider\Product\Form\Modifier\CustomOptions" sortOrder="999999999" />
</type>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
* Date: 07/07/2020
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<tab id="customily_settings" translate="label" sortOrder="10">
<label>Customily</label>
</tab>
<section id="customily" translate="label" sortOrder="130" showInDefault="1" showInWebsite="1" showInStore="1">
<class>separator-top</class>
<label>Configuration</label>
<tab>customily_settings</tab>
<resource>Customily_Categories::customily</resource>
<group id="general" translate="label" type="text" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>General Configuration</label>
<field id="enable" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Module Enable</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>
<model>Customily\Categories\Model\Config\ModuleEnableComment</model>
</comment>
</field>
<field id="save_files_in" translate="label" type="select" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="enable">1</field>
</depends>
<label>Save Files In</label>
<source_model>Customily\Categories\Model\Config\Source\ServerToSaveFile</source_model>
<comment>Where the swatches thumbnails and exported previews should be stored.</comment>
</field>
<field id="enable_swatches" translate="label" type="select" sortOrder="3" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="enable">1</field>
</depends>
<label>Enable Customily Swatches</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Enable or disable customily extension swatches.</comment>
</field>
<field id="swatches_max_size" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="enable">1</field>
<field id="enable_swatches">1</field>
</depends>
<label>Customily Swatches Max Size</label>
<comment>Customily swatches max size in px. For example: value 120 means 120x120 px</comment>
</field>
<field id="enable_logs" translate="label" type="select" sortOrder="5" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="enable">1</field>
</depends>
<label>Enable Logs</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Enable or disable customily extension logs.</comment>
</field>
<field id="apply_options_styles" translate="label" type="select" sortOrder="6" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="enable">1</field>
</depends>
<label>Apply Styles to Options</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Apply custom styles to options.</comment>
</field>
<field id="additional_frontend_styles" translate="label" type="textarea" sortOrder="7" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="enable">1</field>
</depends>
<label>Additional Frontend Styles</label>
<comment>Customily additional frontend styles (the "style" tag is not necessary).</comment>
</field>
<field id="additional_frontend_scripts" translate="label" type="textarea" sortOrder="8" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="enable">1</field>
</depends>
<label>Additional Frontend Scripts</label>
<comment>Customily additional frontend scripts (the "script" tag is not necessary).</comment>
</field>
</group>
<group id="personalization" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="customily/general/enable">1</field>
</depends>
<label>Personalization Settings</label>
<field id="type" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Type</label>
<source_model>Customily\Categories\Model\Config\Source\PersonalizationType</source_model>
<comment>Personalize products in product page or in modal window.</comment>
</field>
<field id="allow_optional" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Allow Optional</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Allow personalization to be optional</comment>
</field>
<field id="optional_behavior" translate="label" type="select" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="allow_optional">1</field>
</depends>
<label>Behavior</label>
<source_model>Customily\Categories\Model\Config\Source\PersonalizationBehavior</source_model>
<comment>Personalization optional behavior (visible/hidden by default).</comment>
</field>
<field id="optional_attach_to" translate="label" type="select" sortOrder="3" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="allow_optional">1</field>
</depends>
<label>Attach to</label>
<source_model>Customily\Categories\Model\Config\Source\PersonalizationAttachTo</source_model>
<comment>Personalization optional attach to parent (default) or child for configurable products.</comment>
</field>
<field id="optional_label" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="allow_optional">1</field>
</depends>
<label>Enable/Disable Label</label>
<comment>Enable/disable personalization field label.</comment>
</field>
<field id="handle_prices" translate="label" type="select" sortOrder="5" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Handle Prices</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Update product price by interacting with customily options in product page.</comment>
</field>
</group>
<group id="mail" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="customily/general/enable">1</field>
</depends>
<label>Mails</label>
<field id="show_uploaded_image_url" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Show Uploaded Image Url</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Show uploaded image url instead of full html.</comment>
</field>
</group>
<group id="preview" translate="label" type="text" sortOrder="4" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="customily/general/enable">1</field>
</depends>
<label>Preview Settings</label>
<field id="export_preview" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Export Preview</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Save preview image and add the link to order details.</comment>
</field>
<field id="hover_zoom" translate="label" type="select" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Zoom on Hover</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Zoom when mouse hovering on preview.</comment>
</field>
<field id="resize_preview" translate="label" type="select" sortOrder="3" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Resize Preview to Fit Image controls</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>We recommend having this enabled if your products don’t have photo upload.</comment>
</field>
<field id="save_placeholders_settings" translate="label" type="select" sortOrder="4" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Save Image Placeholder Settings</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Save the position, angle and scale of the image placeholders when template is changed.</comment>
</field>
<field id="sticky_left" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Sticky Left Container</label>
<comment>Image and thumbnails container (html element id or class).</comment>
</field>
<field id="sticky_right" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Sticky Right Container</label>
<comment>Product info container (html element id or class).</comment>
</field>
<field id="sticky_padding" translate="label" type="text" sortOrder="7" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Sticky Top Padding</label>
<comment>Sticky top padding.</comment>
</field>
</group>
<group id="production_file" translate="label" type="text" sortOrder="5" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="customily/general/enable">1</field>
</depends>
<label>Production File Settings</label>
<field id="export_file" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Export File</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Export production file and add the link in order details.</comment>
</field>
<field id="rename_file" translate="label" type="select" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="export_file">1</field>
</depends>
<label>Rename Production File</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Rename production file on checkout with a pattern.</comment>
</field>
<field id="rename_file_pattern" translate="label" type="text" sortOrder="3" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="export_file">1</field>
<field id="rename_file">1</field>
</depends>
<label>Rename Production File Pattern</label>
<comment>Pattern items: productid, sku, productname, customer, ordernumber and random. Example pattern: ordernumber_sku_random</comment>
</field>
</group>
<group id="extension_plugins" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="customily/general/enable">1</field>
</depends>
<label>Plugins Enabled Settings</label>
<field id="represent_product" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Add New Product To Cart</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Always add new product to cart when customily is enabled.</comment>
</field>
<field id="custom_cart_thumbnail" translate="label" type="select" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Custom Cart Thumbnails</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Custom thumbnail for cart items.</comment>
</field>
<field id="custom_minicart_thumbnail" translate="label" type="select" sortOrder="3" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Custom Minicart Thumbnails</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Custom thumbnail for minicart items.</comment>
</field>
<field id="selectable_default_value" translate="label" type="select" sortOrder="4" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Selectable Default Value</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment>Default value for selectable options.</comment>
</field>
</group>
<group id="api" translate="label" type="text" sortOrder="7" showInDefault="1" showInWebsite="0" showInStore="0">
<depends>
<field id="customily/general/enable">1</field>
</depends>
<label>Api Settings</label>
<field id="user_api_key" translate="label" type="textarea" sortOrder="1" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Customily Api Key</label>
<comment>Customily api key (you can find it in your customily account settings).</comment>
</field>
<field id="api_endpoint" translate="label" type="text" sortOrder="2" showInDefault="0" showInWebsite="0" showInStore="0">
<label>Customily Api Endpoint</label>
<comment>Customily api endpoint (default https://app.customily.com/api).</comment>
</field>
<field id="cdn_endpoint" translate="label" type="text" sortOrder="3" showInDefault="0" showInWebsite="0" showInStore="0">
<label>Customily Cdn Endpoint</label>
<comment>Customily cdn endpoint (default https://cdn.customily.com).</comment>
</field>
<field id="thumbnails_endpoint" translate="label" type="text" sortOrder="4" showInDefault="0" showInWebsite="0" showInStore="0">
<label>Customily Thumbnails Endpoint</label>
<comment>Customily thumbnails endpoint (default https://api.customily.com/magento).</comment>
</field>
<field id="api_secret_key" translate="label" type="textarea" sortOrder="5" showInDefault="0" showInWebsite="0" showInStore="0">
<label>Customily Api Secret Key</label>
<comment>Customily app.customily.com/api secret key.</comment>
</field>
<field id="x_api_key" translate="label" type="textarea" sortOrder="6" showInDefault="0" showInWebsite="0" showInStore="0">
<label>Customily Api Key</label>
<comment>Customily app.customily.com/api key.</comment>
</field>
<field id="m_api_key" translate="label" type="textarea" sortOrder="7" showInDefault="0" showInWebsite="0" showInStore="0">
<label>Internal Api Key</label>
<comment>Magento internal api key.</comment>
</field>
</group>
</section>
</system>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Catalog:etc/catalog_attributes.xsd">
<group name="quote_item">
<attribute name="additional_options"/>
</group>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
* Date: 09/07/2020
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<customily>
<general>
<enable>1</enable>
<save_files_in>magento</save_files_in>
<enable_swatches>1</enable_swatches>
<swatches_max_size>120</swatches_max_size>
<enable_logs>1</enable_logs>
<apply_options_styles>1</apply_options_styles>
<additional_fontend_styles></additional_fontend_styles>
<additional_frontend_scripts></additional_frontend_scripts>
</general>
<personalization>
<type>page-preview</type>
<allow_optional>0</allow_optional>
<optional_attach_to>child</optional_attach_to>
<optional_behavior>visible</optional_behavior>
<optional_label>I don't want to personalize, I want this item blank</optional_label>
<handle_prices>1</handle_prices>
</personalization>
<mail>
<show_uploaded_image_url>0</show_uploaded_image_url>
</mail>
<preview>
<export_preview>1</export_preview>
<hover_zoom>0</hover_zoom>
<resize_preview>0</resize_preview>
<save_placeholders_settings>1</save_placeholders_settings>
<sticky_left></sticky_left>
<sticky_right></sticky_right>
<sticky_padding>40</sticky_padding>
</preview>
<production_file>
<export_file>1</export_file>
<rename_file>0</rename_file>
<rename_file_pattern>ordernumber_sku</rename_file_pattern>
</production_file>
<extension_plugins>
<represent_product>0</represent_product>
<custom_cart_thumbnail>1</custom_cart_thumbnail>
<custom_minicart_thumbnail>1</custom_minicart_thumbnail>
<selectable_default_value>1</selectable_default_value>
</extension_plugins>
<api>
<user_api_key></user_api_key>
<api_endpoint>https://app.customily.com/api</api_endpoint>
<cdn_endpoint>https://cdn.customily.com</cdn_endpoint>
<thumbnails_endpoint>https://api.customily.com/magento</thumbnails_endpoint>
<api_secret_key></api_secret_key>
<x_api_key></x_api_key>
<m_api_key>VTBCdGVTb3hOVEEwTWpBeE9GOUVhVzl6YldGdWFTbzRNVEF6TXpCZlRHbHNZU280TWpFeE1UWQ==</m_api_key>
</api>
</customily>
</default>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
* Date: 07/07/2020
*/
-->
<csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp:etc/csp_whitelist.xsd">
<policies>
<policy id="img-src">
<values>
<value id="customily-img-src" type="host">https://*.customily.com</value>
<value id="customily-s3-img-src" type="host">https://*.amazonaws.com</value>
<value id="data-url-img-src" type="host">'self' data:</value>
</values>
</policy>
<policy id="font-src">
<values>
<value id="customily-font-src" type="host">https://*.customily.com</value>
<value id="customily-s3-font-src" type="host">https://*.amazonaws.com</value>
<value id="data-url-font-src" type="host">'self' data:</value>
</values>
</policy>
<policy id="script-src">
<values>
<value id="customily-script-src" type="host">https://*.customily.com</value>
<value id="customily-s3-script-src" type="host">https://*.amazonaws.com</value>
</values>
</policy>
<policy id="connect-src">
<values>
<value id="customily-connect-src" type="host">https://*.customily.com</value>
<value id="customily-s3-connect-src" type="host">https://*.amazonaws.com</value>
<value id="data-url-connect-src" type="host">'self' data:</value>
</values>
</policy>
</policies>
</csp_whitelist>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- implementing CustomilyRestInterface rest api -->
<preference for="Customily\Categories\Api\Server\ApiRestInterface" type="Customily\Categories\Api\Server\ApiRestImpl"/>
<!-- hide thumbnail and production file in order item (frontend) -->
<type name="Magento\Sales\Block\Order\Item\Renderer\DefaultRenderer">
<plugin name="Customily_Categories_Order_Item_Renderer_DefaultRenderer" type="Customily\Categories\Plugin\Sales\Block\Order\Item\Renderer\DefaultRenderer" sortOrder="999999" />
</type>
<!-- hide thumbnail and production file in order emails (frontend) -->
<type name="Magento\Sales\Block\Order\Email\Items\DefaultItems">
<plugin name="Customily_Categories_Order_Email_Items_DefaultItems" type="Customily\Categories\Plugin\Sales\Block\Order\Email\Items\DefaultItems" sortOrder="999999" />
</type>
<!-- hide thumbnail and production file in order emails (frontend) -->
<type name="Magento\Sales\Block\Order\Email\Items\Order\DefaultOrder">
<plugin name="Customily_Categories_Order_Email_Items_Order_DefaultOrder" type="Customily\Categories\Plugin\Sales\Block\Order\Email\Items\Order\DefaultOrder" sortOrder="999999" />
</type>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<!-- register order -->
<event name="sales_model_service_quote_submit_before">
<observer name="customily_sales_model_service_quote_submit_before" instance="Customily\Categories\Observer\Frontend\QuoteSubmitBeforeObserver" />
</event>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
* Date: 09/12/2019
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- default value for selectable options -->
<type name="Magento\Catalog\Block\Product\View\Options\Type\Select">
<plugin name="Customily_Categories_Option_Select_Values" type="Customily\Categories\Plugin\Catalog\Block\Product\View\Options\Type\Select" sortOrder="99" />
</type>
<!-- custom thumbnail for cart items -->
<type name="Magento\Checkout\Block\Cart\Item\Renderer">
<plugin name="Customily_Categories_Custom_Cart_Item_Image" type="Customily\Categories\Plugin\Checkout\Block\Cart\Item\Renderer" sortOrder="99" />
</type>
<!-- custom thumbnail for minicart items -->
<type name="Magento\Checkout\CustomerData\AbstractItem">
<plugin name="Customily_Categories_Custom_MiniCart_Item_Image" type="Customily\Categories\Plugin\Checkout\CustomerData\AbstractItem" sortOrder="99" />
</type>
<!-- always add new product to cart when customily is enabled -->
<type name="Magento\Quote\Model\Quote\Item">
<plugin name="Customily_Categories_Add_New_Product_To_Cart" type="Customily\Categories\Plugin\Quote\Model\Quote\Item" sortOrder="99" />
</type>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Customily_Categories" setup_version="2.7.3">
<sequence>
<module name="Magento_Backend"/>
<module name="Magento_Catalog"/>
<module name="Magento_Sales"/>
<module name="Magento_Quote"/>
<module name="Magento_Checkout"/>
<module name="Magento_ConfigurableProduct"/>
</sequence>
</module>
</config>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route method="GET" url="/V1/customily">
<service class="Customily\Categories\Api\Server\ApiRestInterface" method="testApi"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="GET" url="/V1/customily/status">
<service class="Customily\Categories\Api\Server\ApiRestInterface" method="status"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="POST" url="/V1/customily/uploadThumbnail">
<service class="Customily\Categories\Api\Server\ApiRestInterface" method="uploadThumbnail"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="POST" url="/V1/customily/deleteThumbnail">
<service class="Customily\Categories\Api\Server\ApiRestInterface" method="deleteThumbnail"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="POST" url="/V1/customily/uploadPreview">
<service class="Customily\Categories\Api\Server\ApiRestInterface" method="uploadPreview"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="POST" url="/V1/customily/optionsFromTemplate">
<service class="Customily\Categories\Api\Server\ApiRestInterface" method="optionsFromTemplate"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
<route method="POST" url="/V1/customily/createLog">
<service class="Customily\Categories\Api\Server\ApiRestInterface" method="createLog"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
</routes>
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Customily_Categories',
__DIR__
);
1.3.0: adding modal personalization
1.4.0: saving swatches thumbnails and exported preview on magento server
1.4.1: fixing collapsible options issue in modal personalization and csp issue when try to upload image to s3
1.4.2: fixing invalid conditions issue on frontend and hiding customily fields on backend when extension is disabled
1.4.3: fixing issue: product added 2 times to cart by custom ajax call
1.4.4: hiding preview when click on .fotorama__dot
1.4.5: fixing issue: save swatches images base64 as file on server
1.4.6: showing module version and customily products count in system config
1.5.0: adding exported preview size limit
1.6.0: adding default value to selectable options
1.6.1: adding customily required validation to options
1.6.2: adding migration for customily_is_required field
1.7.0: renaming production file, show/hide preview and production file link in orders emails
1.8.0: export production file in checkout
1.8.1: fixing issue: showing an option that is already visible according to the customily conditions
1.8.2: fixing issue: replace swatch image
1.9.0: adding api key to internal rest api
fixing the default value when there is more than one page of customizable options
fixing possible options to define conditions when options have more than one page
fixing that buttons and swatches images are not displayed when changing pages in customizable options
1.9.1: adding extension logs
2.0.0: generating customizable options from customily template
2.0.1: fixing add attributes to customizable product with exiting customily attributes configuration
2.0.2: fixing swatch size when image width is different from image height
2.0.4: generating customizable options from customily template for store with id 0 only
2.0.5: fixing categories elasticsearch issue on magento 2.4.x
2.0.6: adjusting fields positions and styles on backend
2.0.7: saving product_customization_id attribute when importing options from template
2.0.9: adding additional styles for backend product edit page
2.0.11: set option is_require false when customily_is_required value change
2.0.12: get font name from font file when generate options from template
2.0.13: set option is_require default value to cero
2.1.0: validating the size of the images, adding customization behavior and text transform
2.1.6: optimizing optional personalization
2.2.0: removing objectManager usage, adding swatches max size
2.2.1: fixing optional personalization issue for child products
2.2.2: optimizing images lazy loading
2.2.3: clear engraver selection when add to cart
2.2.4: fixing preview positioning error when $imagesContainer is null
2.3.0: adding default value for text fields
2.3.1: fixing possible error in function getSelectedProductId
2.3.2: fixing issue when evaluating conditions for options (adding all hidden options to optionsToHide array)
2.3.3: hide customily fields in mageworx edit options templates page and adding options['verify'] = false for avoid certificate issue in apiClient requests
2.3.4: save the position, angle and scale of the image placeholders when the template is changed
2.3.5: fixing issue when disable swatches (position field isn't displayed for dropdown values)
2.3.6: fixing the optional personalization field isn't hidden when set to "No" for child products of a configurable product
2.3.7: fixing attribute options not updating when product attributes are modified.
2.4.0: generating customizable options from font, color and vector library categories
generate production files using the customily user api key
allow quotes on options and options values title
the use of the SVG library is no longer necessary so it was removed from the extension
2.4.1: fixing issue preview is incorrectly positioned within '.gallery-placeholder' while the page is still loading
2.4.2: updating the total price when options are shown/hidden
fixing the index of the orders items for the rename
fixing the textarea value not shown in the cart in modal preview
2.4.3: fixing show/hide preview and production file link in orders emails
2.5.0: updating product price by interacting with customily options in product page
2.5.1: using relative path for swatches images
2.5.2: adding extension version and max_execution_time to status endpoint
2.5.3: fixing label for font/color options created by libraries
2.6.0: compatibility with magento 2.4.4 and php 8.1
2.6.1: more fixes for compatibility php 8.1
2.6.2: more fixes for compatibility with magento 2.4.4 and php 8.1
2.6.3: more fixes for compatibility with magento 2.4.4 and php 8.1
2.6.4: fixing cursor position when edit field/textarea with text-transform applied
2.7.0: improve show/hide customily fields in order items name column and emails
2.7.1: adding setting to display the user uploaded image url instead of the full html
2.7.2: compatibility with magento 2.4.5 (option values per page)
2.7.3: fixing show/hide loader when changing customizable option type
2.7.4: fixing show/hide loader when remove option value
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="Customily_Categories::css/fontawesome/fontawesome.css"/>
<css src="Customily_Categories::css/fontawesome/regular.css"/>
<css src="Customily_Categories::css/fontawesome/solid.css"/>
</head>
<referenceContainer name="content">
<block class="Magento\Framework\View\Element\Template" name="customily.customizable.options.modifier" template="Customily_Categories::product/edit/customily_options_modifier.phtml" />
</referenceContainer>
</page>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="column_name">
<action method="setTemplate">
<argument name="template" xsi:type="string">Customily_Categories::items/column/name.phtml</argument>
</action>
</referenceBlock>
</body>
</page>
/**
* Copyright © Customily, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
var config = {
config: {
mixins: {
'Magento_Catalog/js/custom-options-type': {
'Customily_Categories/js/custom-options-type': true
}
}
},
map: {
'*': {
'Vue': 'Customily_Categories/js/vue',
'spectrum': 'Customily_Categories/js/spectrum'
}
}
};
<?php
/**
* Copyright © Customily. All rights reserved.
*/
?>
<?php
/**
* @var $block \Magento\Sales\Block\Adminhtml\Items\Column\Name
*/
?>
<?php
/** @var \Magento\Catalog\Helper\Data $catalogHelper */
$catalogHelper = $this->helper('Magento\Catalog\Helper\Data');
/* @var \Customily\Categories\Helper\CustomilyHelper $customilyHelper */
$customilyHelper = $this->helper('Customily\Categories\Helper\CustomilyHelper');
$customilyOptionsFound = false;
if ($_item = $block->getItem()): ?>
<div id="order_item_<?= /* @escapeNotVerified */ $_item->getId() ?>_title" class="product-title customily">
<?= $block->escapeHtml($_item->getName()) ?>
</div>
<div class="product-sku-block">
<span><?= /* @escapeNotVerified */ __('SKU') ?>:</span> <?= implode('<br />', $catalogHelper->splitSku($block->escapeHtml($block->getSku()))) ?>
</div>
<?php if ($block->getOrderOptions()): ?>
<dl class="item-options">
<?php foreach ($block->getOrderOptions() as $_option): ?>
<?php
if ($_option['label'] == 'magento_product_id') {
continue;
}
?>
<dt class="op-label"><?= /* @escapeNotVerified */ $_option['label'] ?>:</dt>
<dd class="op-value">
<?php if (isset($_option['custom_view']) && $_option['custom_view']): ?>
<?= /* @escapeNotVerified */ $block->getCustomizedOptionValue($_option) ?>
<?php else: ?>
<?php
if (in_array(strtolower($_option['label']), array('preview', 'thumbnail', 'production file'))) {
$customilyOptionsFound = true;
echo '<a href="' . $_option['value'] . '" target="_blank">link</a>';
} else {
echo /* @escapeNotVerified */ $_option['value'];
}
?>
<?php if (isset($_option['remainder']) && $_option['remainder']): ?>
<span id="<?= /* @escapeNotVerified */ $_dots = 'dots' . uniqid() ?>"> ...</span>
<span id="<?= /* @escapeNotVerified */ $_id = 'id' . uniqid() ?>">
<?= /* @escapeNotVerified */ $_option['remainder'] ?>
</span>
<script>
require(['prototype'], function() {
$('<?= /* @escapeNotVerified */ $_id ?>').hide();
$('<?= /* @escapeNotVerified */ $_id ?>').up().observe('mouseover', function(){$('<?= /* @escapeNotVerified */ $_id ?>').show();});
$('<?= /* @escapeNotVerified */ $_id ?>').up().observe('mouseover', function(){$('<?= /* @escapeNotVerified */ $_dots ?>').hide();});
$('<?= /* @escapeNotVerified */ $_id ?>').up().observe('mouseout', function(){$('<?= /* @escapeNotVerified */ $_id ?>').hide();});
$('<?= /* @escapeNotVerified */ $_id ?>').up().observe('mouseout', function(){$('<?= /* @escapeNotVerified */ $_dots ?>').show();});
});
</script>
<?php endif; ?>
<?php endif; ?>
</dd>
<?php endforeach; ?>
<?php
if (!$customilyOptionsFound) {
$infoBuyRequest = $customilyHelper->getQuoteBuyRequest($_item->getQuoteItemId());
if (isset($infoBuyRequest)) {
if (isset($infoBuyRequest['customily'])) {
if (isset($infoBuyRequest['customily']['url_thumbnail']) && !empty($infoBuyRequest['customily']['url_thumbnail'])) {
?>
<dt class="op-label">Thumbnail:</dt>
<dd class="op-value"><a href="<?= $infoBuyRequest['customily']['url_thumbnail']; ?>" target="_blank">link</a></dd>
<?php
}
if (isset($infoBuyRequest['customily']['url_preview']) && !empty($infoBuyRequest['customily']['url_preview'])) {
?>
<dt class="op-label">Preview:</dt>
<dd class="op-value"><a href="<?= $infoBuyRequest['customily']['url_preview']; ?>" target="_blank">link</a></dd>
<?php
}
$productionFile = $infoBuyRequest['customily']['url_eps'] ?? $infoBuyRequest['customily']['url_production_file'];
if (isset($productionFile) && !empty($productionFile)) {
?>
<dt class="op-label">Production file:</dt>
<dd class="op-value"><a href="<?= $productionFile; ?>" target="_blank">link</a></dd>
<?php
}
if (isset($infoBuyRequest['customily']['personalization_id']) && !empty($infoBuyRequest['customily']['personalization_id'])) {
?>
<dt class="op-label">Personalization Id:</dt>
<dd class="op-value"><?= $infoBuyRequest['customily']['personalization_id']; ?></dd>
<?php
}
}
}
}
?>
</dl>
<?php endif; ?>
<?= $block->escapeHtml($_item->getDescription()) ?>
<?php endif; ?>
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
// Animated Icons
// --------------------------
.@{fa-css-prefix}-spin {
animation: fa-spin 2s infinite linear;
}
.@{fa-css-prefix}-pulse {
animation: fa-spin 1s infinite steps(8);
}
@keyframes fa-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
// Bordered & Pulled
// -------------------------
.@{fa-css-prefix}-border {
border-radius: .1em;
border: solid .08em @fa-border-color;
padding: .2em .25em .15em;
}
.@{fa-css-prefix}-pull-left { float: left; }
.@{fa-css-prefix}-pull-right { float: right; }
.@{fa-css-prefix}, .fas, .far, .fal, .fab {
&.@{fa-css-prefix}-pull-left { margin-right: .3em; }
&.@{fa-css-prefix}-pull-right { margin-left: .3em; }
}
// Base Class Definition
// -------------------------
.@{fa-css-prefix}, .fas, .far, .fal, .fad, .fab {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
}
// Fixed Width Icons
// -------------------------
.@{fa-css-prefix}-fw {
text-align: center;
width: (20em / 16);
}
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
readers do not read off random characters that represent icons */
.@{fa-css-prefix}-500px:before { content: @fa-var-500px; }
.@{fa-css-prefix}-accessible-icon:before { content: @fa-var-accessible-icon; }
.@{fa-css-prefix}-accusoft:before { content: @fa-var-accusoft; }
.@{fa-css-prefix}-acquisitions-incorporated:before { content: @fa-var-acquisitions-incorporated; }
.@{fa-css-prefix}-ad:before { content: @fa-var-ad; }
.@{fa-css-prefix}-address-book:before { content: @fa-var-address-book; }
.@{fa-css-prefix}-address-card:before { content: @fa-var-address-card; }
.@{fa-css-prefix}-adjust:before { content: @fa-var-adjust; }
.@{fa-css-prefix}-adn:before { content: @fa-var-adn; }
.@{fa-css-prefix}-adobe:before { content: @fa-var-adobe; }
.@{fa-css-prefix}-adversal:before { content: @fa-var-adversal; }
.@{fa-css-prefix}-affiliatetheme:before { content: @fa-var-affiliatetheme; }
.@{fa-css-prefix}-air-freshener:before { content: @fa-var-air-freshener; }
.@{fa-css-prefix}-airbnb:before { content: @fa-var-airbnb; }
.@{fa-css-prefix}-algolia:before { content: @fa-var-algolia; }
.@{fa-css-prefix}-align-center:before { content: @fa-var-align-center; }
.@{fa-css-prefix}-align-justify:before { content: @fa-var-align-justify; }
.@{fa-css-prefix}-align-left:before { content: @fa-var-align-left; }
.@{fa-css-prefix}-align-right:before { content: @fa-var-align-right; }
.@{fa-css-prefix}-alipay:before { content: @fa-var-alipay; }
.@{fa-css-prefix}-allergies:before { content: @fa-var-allergies; }
.@{fa-css-prefix}-amazon:before { content: @fa-var-amazon; }
.@{fa-css-prefix}-amazon-pay:before { content: @fa-var-amazon-pay; }
.@{fa-css-prefix}-ambulance:before { content: @fa-var-ambulance; }
.@{fa-css-prefix}-american-sign-language-interpreting:before { content: @fa-var-american-sign-language-interpreting; }
.@{fa-css-prefix}-amilia:before { content: @fa-var-amilia; }
.@{fa-css-prefix}-anchor:before { content: @fa-var-anchor; }
.@{fa-css-prefix}-android:before { content: @fa-var-android; }
.@{fa-css-prefix}-angellist:before { content: @fa-var-angellist; }
.@{fa-css-prefix}-angle-double-down:before { content: @fa-var-angle-double-down; }
.@{fa-css-prefix}-angle-double-left:before { content: @fa-var-angle-double-left; }
.@{fa-css-prefix}-angle-double-right:before { content: @fa-var-angle-double-right; }
.@{fa-css-prefix}-angle-double-up:before { content: @fa-var-angle-double-up; }
.@{fa-css-prefix}-angle-down:before { content: @fa-var-angle-down; }
.@{fa-css-prefix}-angle-left:before { content: @fa-var-angle-left; }
.@{fa-css-prefix}-angle-right:before { content: @fa-var-angle-right; }
.@{fa-css-prefix}-angle-up:before { content: @fa-var-angle-up; }
.@{fa-css-prefix}-angry:before { content: @fa-var-angry; }
.@{fa-css-prefix}-angrycreative:before { content: @fa-var-angrycreative; }
.@{fa-css-prefix}-angular:before { content: @fa-var-angular; }
.@{fa-css-prefix}-ankh:before { content: @fa-var-ankh; }
.@{fa-css-prefix}-app-store:before { content: @fa-var-app-store; }
.@{fa-css-prefix}-app-store-ios:before { content: @fa-var-app-store-ios; }
.@{fa-css-prefix}-apper:before { content: @fa-var-apper; }
.@{fa-css-prefix}-apple:before { content: @fa-var-apple; }
.@{fa-css-prefix}-apple-alt:before { content: @fa-var-apple-alt; }
.@{fa-css-prefix}-apple-pay:before { content: @fa-var-apple-pay; }
.@{fa-css-prefix}-archive:before { content: @fa-var-archive; }
.@{fa-css-prefix}-archway:before { content: @fa-var-archway; }
.@{fa-css-prefix}-arrow-alt-circle-down:before { content: @fa-var-arrow-alt-circle-down; }
.@{fa-css-prefix}-arrow-alt-circle-left:before { content: @fa-var-arrow-alt-circle-left; }
.@{fa-css-prefix}-arrow-alt-circle-right:before { content: @fa-var-arrow-alt-circle-right; }
.@{fa-css-prefix}-arrow-alt-circle-up:before { content: @fa-var-arrow-alt-circle-up; }
.@{fa-css-prefix}-arrow-circle-down:before { content: @fa-var-arrow-circle-down; }
.@{fa-css-prefix}-arrow-circle-left:before { content: @fa-var-arrow-circle-left; }
.@{fa-css-prefix}-arrow-circle-right:before { content: @fa-var-arrow-circle-right; }
.@{fa-css-prefix}-arrow-circle-up:before { content: @fa-var-arrow-circle-up; }
.@{fa-css-prefix}-arrow-down:before { content: @fa-var-arrow-down; }
.@{fa-css-prefix}-arrow-left:before { content: @fa-var-arrow-left; }
.@{fa-css-prefix}-arrow-right:before { content: @fa-var-arrow-right; }
.@{fa-css-prefix}-arrow-up:before { content: @fa-var-arrow-up; }
.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-arrows-alt; }
.@{fa-css-prefix}-arrows-alt-h:before { content: @fa-var-arrows-alt-h; }
.@{fa-css-prefix}-arrows-alt-v:before { content: @fa-var-arrows-alt-v; }
.@{fa-css-prefix}-artstation:before { content: @fa-var-artstation; }
.@{fa-css-prefix}-assistive-listening-systems:before { content: @fa-var-assistive-listening-systems; }
.@{fa-css-prefix}-asterisk:before { content: @fa-var-asterisk; }
.@{fa-css-prefix}-asymmetrik:before { content: @fa-var-asymmetrik; }
.@{fa-css-prefix}-at:before { content: @fa-var-at; }
.@{fa-css-prefix}-atlas:before { content: @fa-var-atlas; }
.@{fa-css-prefix}-atlassian:before { content: @fa-var-atlassian; }
.@{fa-css-prefix}-atom:before { content: @fa-var-atom; }
.@{fa-css-prefix}-audible:before { content: @fa-var-audible; }
.@{fa-css-prefix}-audio-description:before { content: @fa-var-audio-description; }
.@{fa-css-prefix}-autoprefixer:before { content: @fa-var-autoprefixer; }
.@{fa-css-prefix}-avianex:before { content: @fa-var-avianex; }
.@{fa-css-prefix}-aviato:before { content: @fa-var-aviato; }
.@{fa-css-prefix}-award:before { content: @fa-var-award; }
.@{fa-css-prefix}-aws:before { content: @fa-var-aws; }
.@{fa-css-prefix}-baby:before { content: @fa-var-baby; }
.@{fa-css-prefix}-baby-carriage:before { content: @fa-var-baby-carriage; }
.@{fa-css-prefix}-backspace:before { content: @fa-var-backspace; }
.@{fa-css-prefix}-backward:before { content: @fa-var-backward; }
.@{fa-css-prefix}-bacon:before { content: @fa-var-bacon; }
.@{fa-css-prefix}-bahai:before { content: @fa-var-bahai; }
.@{fa-css-prefix}-balance-scale:before { content: @fa-var-balance-scale; }
.@{fa-css-prefix}-balance-scale-left:before { content: @fa-var-balance-scale-left; }
.@{fa-css-prefix}-balance-scale-right:before { content: @fa-var-balance-scale-right; }
.@{fa-css-prefix}-ban:before { content: @fa-var-ban; }
.@{fa-css-prefix}-band-aid:before { content: @fa-var-band-aid; }
.@{fa-css-prefix}-bandcamp:before { content: @fa-var-bandcamp; }
.@{fa-css-prefix}-barcode:before { content: @fa-var-barcode; }
.@{fa-css-prefix}-bars:before { content: @fa-var-bars; }
.@{fa-css-prefix}-baseball-ball:before { content: @fa-var-baseball-ball; }
.@{fa-css-prefix}-basketball-ball:before { content: @fa-var-basketball-ball; }
.@{fa-css-prefix}-bath:before { content: @fa-var-bath; }
.@{fa-css-prefix}-battery-empty:before { content: @fa-var-battery-empty; }
.@{fa-css-prefix}-battery-full:before { content: @fa-var-battery-full; }
.@{fa-css-prefix}-battery-half:before { content: @fa-var-battery-half; }
.@{fa-css-prefix}-battery-quarter:before { content: @fa-var-battery-quarter; }
.@{fa-css-prefix}-battery-three-quarters:before { content: @fa-var-battery-three-quarters; }
.@{fa-css-prefix}-battle-net:before { content: @fa-var-battle-net; }
.@{fa-css-prefix}-bed:before { content: @fa-var-bed; }
.@{fa-css-prefix}-beer:before { content: @fa-var-beer; }
.@{fa-css-prefix}-behance:before { content: @fa-var-behance; }
.@{fa-css-prefix}-behance-square:before { content: @fa-var-behance-square; }
.@{fa-css-prefix}-bell:before { content: @fa-var-bell; }
.@{fa-css-prefix}-bell-slash:before { content: @fa-var-bell-slash; }
.@{fa-css-prefix}-bezier-curve:before { content: @fa-var-bezier-curve; }
.@{fa-css-prefix}-bible:before { content: @fa-var-bible; }
.@{fa-css-prefix}-bicycle:before { content: @fa-var-bicycle; }
.@{fa-css-prefix}-biking:before { content: @fa-var-biking; }
.@{fa-css-prefix}-bimobject:before { content: @fa-var-bimobject; }
.@{fa-css-prefix}-binoculars:before { content: @fa-var-binoculars; }
.@{fa-css-prefix}-biohazard:before { content: @fa-var-biohazard; }
.@{fa-css-prefix}-birthday-cake:before { content: @fa-var-birthday-cake; }
.@{fa-css-prefix}-bitbucket:before { content: @fa-var-bitbucket; }
.@{fa-css-prefix}-bitcoin:before { content: @fa-var-bitcoin; }
.@{fa-css-prefix}-bity:before { content: @fa-var-bity; }
.@{fa-css-prefix}-black-tie:before { content: @fa-var-black-tie; }
.@{fa-css-prefix}-blackberry:before { content: @fa-var-blackberry; }
.@{fa-css-prefix}-blender:before { content: @fa-var-blender; }
.@{fa-css-prefix}-blender-phone:before { content: @fa-var-blender-phone; }
.@{fa-css-prefix}-blind:before { content: @fa-var-blind; }
.@{fa-css-prefix}-blog:before { content: @fa-var-blog; }
.@{fa-css-prefix}-blogger:before { content: @fa-var-blogger; }
.@{fa-css-prefix}-blogger-b:before { content: @fa-var-blogger-b; }
.@{fa-css-prefix}-bluetooth:before { content: @fa-var-bluetooth; }
.@{fa-css-prefix}-bluetooth-b:before { content: @fa-var-bluetooth-b; }
.@{fa-css-prefix}-bold:before { content: @fa-var-bold; }
.@{fa-css-prefix}-bolt:before { content: @fa-var-bolt; }
.@{fa-css-prefix}-bomb:before { content: @fa-var-bomb; }
.@{fa-css-prefix}-bone:before { content: @fa-var-bone; }
.@{fa-css-prefix}-bong:before { content: @fa-var-bong; }
.@{fa-css-prefix}-book:before { content: @fa-var-book; }
.@{fa-css-prefix}-book-dead:before { content: @fa-var-book-dead; }
.@{fa-css-prefix}-book-medical:before { content: @fa-var-book-medical; }
.@{fa-css-prefix}-book-open:before { content: @fa-var-book-open; }
.@{fa-css-prefix}-book-reader:before { content: @fa-var-book-reader; }
.@{fa-css-prefix}-bookmark:before { content: @fa-var-bookmark; }
.@{fa-css-prefix}-bootstrap:before { content: @fa-var-bootstrap; }
.@{fa-css-prefix}-border-all:before { content: @fa-var-border-all; }
.@{fa-css-prefix}-border-none:before { content: @fa-var-border-none; }
.@{fa-css-prefix}-border-style:before { content: @fa-var-border-style; }
.@{fa-css-prefix}-bowling-ball:before { content: @fa-var-bowling-ball; }
.@{fa-css-prefix}-box:before { content: @fa-var-box; }
.@{fa-css-prefix}-box-open:before { content: @fa-var-box-open; }
.@{fa-css-prefix}-box-tissue:before { content: @fa-var-box-tissue; }
.@{fa-css-prefix}-boxes:before { content: @fa-var-boxes; }
.@{fa-css-prefix}-braille:before { content: @fa-var-braille; }
.@{fa-css-prefix}-brain:before { content: @fa-var-brain; }
.@{fa-css-prefix}-bread-slice:before { content: @fa-var-bread-slice; }
.@{fa-css-prefix}-briefcase:before { content: @fa-var-briefcase; }
.@{fa-css-prefix}-briefcase-medical:before { content: @fa-var-briefcase-medical; }
.@{fa-css-prefix}-broadcast-tower:before { content: @fa-var-broadcast-tower; }
.@{fa-css-prefix}-broom:before { content: @fa-var-broom; }
.@{fa-css-prefix}-brush:before { content: @fa-var-brush; }
.@{fa-css-prefix}-btc:before { content: @fa-var-btc; }
.@{fa-css-prefix}-buffer:before { content: @fa-var-buffer; }
.@{fa-css-prefix}-bug:before { content: @fa-var-bug; }
.@{fa-css-prefix}-building:before { content: @fa-var-building; }
.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; }
.@{fa-css-prefix}-bullseye:before { content: @fa-var-bullseye; }
.@{fa-css-prefix}-burn:before { content: @fa-var-burn; }
.@{fa-css-prefix}-buromobelexperte:before { content: @fa-var-buromobelexperte; }
.@{fa-css-prefix}-bus:before { content: @fa-var-bus; }
.@{fa-css-prefix}-bus-alt:before { content: @fa-var-bus-alt; }
.@{fa-css-prefix}-business-time:before { content: @fa-var-business-time; }
.@{fa-css-prefix}-buy-n-large:before { content: @fa-var-buy-n-large; }
.@{fa-css-prefix}-buysellads:before { content: @fa-var-buysellads; }
.@{fa-css-prefix}-calculator:before { content: @fa-var-calculator; }
.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar; }
.@{fa-css-prefix}-calendar-alt:before { content: @fa-var-calendar-alt; }
.@{fa-css-prefix}-calendar-check:before { content: @fa-var-calendar-check; }
.@{fa-css-prefix}-calendar-day:before { content: @fa-var-calendar-day; }
.@{fa-css-prefix}-calendar-minus:before { content: @fa-var-calendar-minus; }
.@{fa-css-prefix}-calendar-plus:before { content: @fa-var-calendar-plus; }
.@{fa-css-prefix}-calendar-times:before { content: @fa-var-calendar-times; }
.@{fa-css-prefix}-calendar-week:before { content: @fa-var-calendar-week; }
.@{fa-css-prefix}-camera:before { content: @fa-var-camera; }
.@{fa-css-prefix}-camera-retro:before { content: @fa-var-camera-retro; }
.@{fa-css-prefix}-campground:before { content: @fa-var-campground; }
.@{fa-css-prefix}-canadian-maple-leaf:before { content: @fa-var-canadian-maple-leaf; }
.@{fa-css-prefix}-candy-cane:before { content: @fa-var-candy-cane; }
.@{fa-css-prefix}-cannabis:before { content: @fa-var-cannabis; }
.@{fa-css-prefix}-capsules:before { content: @fa-var-capsules; }
.@{fa-css-prefix}-car:before { content: @fa-var-car; }
.@{fa-css-prefix}-car-alt:before { content: @fa-var-car-alt; }
.@{fa-css-prefix}-car-battery:before { content: @fa-var-car-battery; }
.@{fa-css-prefix}-car-crash:before { content: @fa-var-car-crash; }
.@{fa-css-prefix}-car-side:before { content: @fa-var-car-side; }
.@{fa-css-prefix}-caravan:before { content: @fa-var-caravan; }
.@{fa-css-prefix}-caret-down:before { content: @fa-var-caret-down; }
.@{fa-css-prefix}-caret-left:before { content: @fa-var-caret-left; }
.@{fa-css-prefix}-caret-right:before { content: @fa-var-caret-right; }
.@{fa-css-prefix}-caret-square-down:before { content: @fa-var-caret-square-down; }
.@{fa-css-prefix}-caret-square-left:before { content: @fa-var-caret-square-left; }
.@{fa-css-prefix}-caret-square-right:before { content: @fa-var-caret-square-right; }
.@{fa-css-prefix}-caret-square-up:before { content: @fa-var-caret-square-up; }
.@{fa-css-prefix}-caret-up:before { content: @fa-var-caret-up; }
.@{fa-css-prefix}-carrot:before { content: @fa-var-carrot; }
.@{fa-css-prefix}-cart-arrow-down:before { content: @fa-var-cart-arrow-down; }
.@{fa-css-prefix}-cart-plus:before { content: @fa-var-cart-plus; }
.@{fa-css-prefix}-cash-register:before { content: @fa-var-cash-register; }
.@{fa-css-prefix}-cat:before { content: @fa-var-cat; }
.@{fa-css-prefix}-cc-amazon-pay:before { content: @fa-var-cc-amazon-pay; }
.@{fa-css-prefix}-cc-amex:before { content: @fa-var-cc-amex; }
.@{fa-css-prefix}-cc-apple-pay:before { content: @fa-var-cc-apple-pay; }
.@{fa-css-prefix}-cc-diners-club:before { content: @fa-var-cc-diners-club; }
.@{fa-css-prefix}-cc-discover:before { content: @fa-var-cc-discover; }
.@{fa-css-prefix}-cc-jcb:before { content: @fa-var-cc-jcb; }
.@{fa-css-prefix}-cc-mastercard:before { content: @fa-var-cc-mastercard; }
.@{fa-css-prefix}-cc-paypal:before { content: @fa-var-cc-paypal; }
.@{fa-css-prefix}-cc-stripe:before { content: @fa-var-cc-stripe; }
.@{fa-css-prefix}-cc-visa:before { content: @fa-var-cc-visa; }
.@{fa-css-prefix}-centercode:before { content: @fa-var-centercode; }
.@{fa-css-prefix}-centos:before { content: @fa-var-centos; }
.@{fa-css-prefix}-certificate:before { content: @fa-var-certificate; }
.@{fa-css-prefix}-chair:before { content: @fa-var-chair; }
.@{fa-css-prefix}-chalkboard:before { content: @fa-var-chalkboard; }
.@{fa-css-prefix}-chalkboard-teacher:before { content: @fa-var-chalkboard-teacher; }
.@{fa-css-prefix}-charging-station:before { content: @fa-var-charging-station; }
.@{fa-css-prefix}-chart-area:before { content: @fa-var-chart-area; }
.@{fa-css-prefix}-chart-bar:before { content: @fa-var-chart-bar; }
.@{fa-css-prefix}-chart-line:before { content: @fa-var-chart-line; }
.@{fa-css-prefix}-chart-pie:before { content: @fa-var-chart-pie; }
.@{fa-css-prefix}-check:before { content: @fa-var-check; }
.@{fa-css-prefix}-check-circle:before { content: @fa-var-check-circle; }
.@{fa-css-prefix}-check-double:before { content: @fa-var-check-double; }
.@{fa-css-prefix}-check-square:before { content: @fa-var-check-square; }
.@{fa-css-prefix}-cheese:before { content: @fa-var-cheese; }
.@{fa-css-prefix}-chess:before { content: @fa-var-chess; }
.@{fa-css-prefix}-chess-bishop:before { content: @fa-var-chess-bishop; }
.@{fa-css-prefix}-chess-board:before { content: @fa-var-chess-board; }
.@{fa-css-prefix}-chess-king:before { content: @fa-var-chess-king; }
.@{fa-css-prefix}-chess-knight:before { content: @fa-var-chess-knight; }
.@{fa-css-prefix}-chess-pawn:before { content: @fa-var-chess-pawn; }
.@{fa-css-prefix}-chess-queen:before { content: @fa-var-chess-queen; }
.@{fa-css-prefix}-chess-rook:before { content: @fa-var-chess-rook; }
.@{fa-css-prefix}-chevron-circle-down:before { content: @fa-var-chevron-circle-down; }
.@{fa-css-prefix}-chevron-circle-left:before { content: @fa-var-chevron-circle-left; }
.@{fa-css-prefix}-chevron-circle-right:before { content: @fa-var-chevron-circle-right; }
.@{fa-css-prefix}-chevron-circle-up:before { content: @fa-var-chevron-circle-up; }
.@{fa-css-prefix}-chevron-down:before { content: @fa-var-chevron-down; }
.@{fa-css-prefix}-chevron-left:before { content: @fa-var-chevron-left; }
.@{fa-css-prefix}-chevron-right:before { content: @fa-var-chevron-right; }
.@{fa-css-prefix}-chevron-up:before { content: @fa-var-chevron-up; }
.@{fa-css-prefix}-child:before { content: @fa-var-child; }
.@{fa-css-prefix}-chrome:before { content: @fa-var-chrome; }
.@{fa-css-prefix}-chromecast:before { content: @fa-var-chromecast; }
.@{fa-css-prefix}-church:before { content: @fa-var-church; }
.@{fa-css-prefix}-circle:before { content: @fa-var-circle; }
.@{fa-css-prefix}-circle-notch:before { content: @fa-var-circle-notch; }
.@{fa-css-prefix}-city:before { content: @fa-var-city; }
.@{fa-css-prefix}-clinic-medical:before { content: @fa-var-clinic-medical; }
.@{fa-css-prefix}-clipboard:before { content: @fa-var-clipboard; }
.@{fa-css-prefix}-clipboard-check:before { content: @fa-var-clipboard-check; }
.@{fa-css-prefix}-clipboard-list:before { content: @fa-var-clipboard-list; }
.@{fa-css-prefix}-clock:before { content: @fa-var-clock; }
.@{fa-css-prefix}-clone:before { content: @fa-var-clone; }
.@{fa-css-prefix}-closed-captioning:before { content: @fa-var-closed-captioning; }
.@{fa-css-prefix}-cloud:before { content: @fa-var-cloud; }
.@{fa-css-prefix}-cloud-download-alt:before { content: @fa-var-cloud-download-alt; }
.@{fa-css-prefix}-cloud-meatball:before { content: @fa-var-cloud-meatball; }
.@{fa-css-prefix}-cloud-moon:before { content: @fa-var-cloud-moon; }
.@{fa-css-prefix}-cloud-moon-rain:before { content: @fa-var-cloud-moon-rain; }
.@{fa-css-prefix}-cloud-rain:before { content: @fa-var-cloud-rain; }
.@{fa-css-prefix}-cloud-showers-heavy:before { content: @fa-var-cloud-showers-heavy; }
.@{fa-css-prefix}-cloud-sun:before { content: @fa-var-cloud-sun; }
.@{fa-css-prefix}-cloud-sun-rain:before { content: @fa-var-cloud-sun-rain; }
.@{fa-css-prefix}-cloud-upload-alt:before { content: @fa-var-cloud-upload-alt; }
.@{fa-css-prefix}-cloudscale:before { content: @fa-var-cloudscale; }
.@{fa-css-prefix}-cloudsmith:before { content: @fa-var-cloudsmith; }
.@{fa-css-prefix}-cloudversify:before { content: @fa-var-cloudversify; }
.@{fa-css-prefix}-cocktail:before { content: @fa-var-cocktail; }
.@{fa-css-prefix}-code:before { content: @fa-var-code; }
.@{fa-css-prefix}-code-branch:before { content: @fa-var-code-branch; }
.@{fa-css-prefix}-codepen:before { content: @fa-var-codepen; }
.@{fa-css-prefix}-codiepie:before { content: @fa-var-codiepie; }
.@{fa-css-prefix}-coffee:before { content: @fa-var-coffee; }
.@{fa-css-prefix}-cog:before { content: @fa-var-cog; }
.@{fa-css-prefix}-cogs:before { content: @fa-var-cogs; }
.@{fa-css-prefix}-coins:before { content: @fa-var-coins; }
.@{fa-css-prefix}-columns:before { content: @fa-var-columns; }
.@{fa-css-prefix}-comment:before { content: @fa-var-comment; }
.@{fa-css-prefix}-comment-alt:before { content: @fa-var-comment-alt; }
.@{fa-css-prefix}-comment-dollar:before { content: @fa-var-comment-dollar; }
.@{fa-css-prefix}-comment-dots:before { content: @fa-var-comment-dots; }
.@{fa-css-prefix}-comment-medical:before { content: @fa-var-comment-medical; }
.@{fa-css-prefix}-comment-slash:before { content: @fa-var-comment-slash; }
.@{fa-css-prefix}-comments:before { content: @fa-var-comments; }
.@{fa-css-prefix}-comments-dollar:before { content: @fa-var-comments-dollar; }
.@{fa-css-prefix}-compact-disc:before { content: @fa-var-compact-disc; }
.@{fa-css-prefix}-compass:before { content: @fa-var-compass; }
.@{fa-css-prefix}-compress:before { content: @fa-var-compress; }
.@{fa-css-prefix}-compress-alt:before { content: @fa-var-compress-alt; }
.@{fa-css-prefix}-compress-arrows-alt:before { content: @fa-var-compress-arrows-alt; }
.@{fa-css-prefix}-concierge-bell:before { content: @fa-var-concierge-bell; }
.@{fa-css-prefix}-confluence:before { content: @fa-var-confluence; }
.@{fa-css-prefix}-connectdevelop:before { content: @fa-var-connectdevelop; }
.@{fa-css-prefix}-contao:before { content: @fa-var-contao; }
.@{fa-css-prefix}-cookie:before { content: @fa-var-cookie; }
.@{fa-css-prefix}-cookie-bite:before { content: @fa-var-cookie-bite; }
.@{fa-css-prefix}-copy:before { content: @fa-var-copy; }
.@{fa-css-prefix}-copyright:before { content: @fa-var-copyright; }
.@{fa-css-prefix}-cotton-bureau:before { content: @fa-var-cotton-bureau; }
.@{fa-css-prefix}-couch:before { content: @fa-var-couch; }
.@{fa-css-prefix}-cpanel:before { content: @fa-var-cpanel; }
.@{fa-css-prefix}-creative-commons:before { content: @fa-var-creative-commons; }
.@{fa-css-prefix}-creative-commons-by:before { content: @fa-var-creative-commons-by; }
.@{fa-css-prefix}-creative-commons-nc:before { content: @fa-var-creative-commons-nc; }
.@{fa-css-prefix}-creative-commons-nc-eu:before { content: @fa-var-creative-commons-nc-eu; }
.@{fa-css-prefix}-creative-commons-nc-jp:before { content: @fa-var-creative-commons-nc-jp; }
.@{fa-css-prefix}-creative-commons-nd:before { content: @fa-var-creative-commons-nd; }
.@{fa-css-prefix}-creative-commons-pd:before { content: @fa-var-creative-commons-pd; }
.@{fa-css-prefix}-creative-commons-pd-alt:before { content: @fa-var-creative-commons-pd-alt; }
.@{fa-css-prefix}-creative-commons-remix:before { content: @fa-var-creative-commons-remix; }
.@{fa-css-prefix}-creative-commons-sa:before { content: @fa-var-creative-commons-sa; }
.@{fa-css-prefix}-creative-commons-sampling:before { content: @fa-var-creative-commons-sampling; }
.@{fa-css-prefix}-creative-commons-sampling-plus:before { content: @fa-var-creative-commons-sampling-plus; }
.@{fa-css-prefix}-creative-commons-share:before { content: @fa-var-creative-commons-share; }
.@{fa-css-prefix}-creative-commons-zero:before { content: @fa-var-creative-commons-zero; }
.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; }
.@{fa-css-prefix}-critical-role:before { content: @fa-var-critical-role; }
.@{fa-css-prefix}-crop:before { content: @fa-var-crop; }
.@{fa-css-prefix}-crop-alt:before { content: @fa-var-crop-alt; }
.@{fa-css-prefix}-cross:before { content: @fa-var-cross; }
.@{fa-css-prefix}-crosshairs:before { content: @fa-var-crosshairs; }
.@{fa-css-prefix}-crow:before { content: @fa-var-crow; }
.@{fa-css-prefix}-crown:before { content: @fa-var-crown; }
.@{fa-css-prefix}-crutch:before { content: @fa-var-crutch; }
.@{fa-css-prefix}-css3:before { content: @fa-var-css3; }
.@{fa-css-prefix}-css3-alt:before { content: @fa-var-css3-alt; }
.@{fa-css-prefix}-cube:before { content: @fa-var-cube; }
.@{fa-css-prefix}-cubes:before { content: @fa-var-cubes; }
.@{fa-css-prefix}-cut:before { content: @fa-var-cut; }
.@{fa-css-prefix}-cuttlefish:before { content: @fa-var-cuttlefish; }
.@{fa-css-prefix}-d-and-d:before { content: @fa-var-d-and-d; }
.@{fa-css-prefix}-d-and-d-beyond:before { content: @fa-var-d-and-d-beyond; }
.@{fa-css-prefix}-dailymotion:before { content: @fa-var-dailymotion; }
.@{fa-css-prefix}-dashcube:before { content: @fa-var-dashcube; }
.@{fa-css-prefix}-database:before { content: @fa-var-database; }
.@{fa-css-prefix}-deaf:before { content: @fa-var-deaf; }
.@{fa-css-prefix}-delicious:before { content: @fa-var-delicious; }
.@{fa-css-prefix}-democrat:before { content: @fa-var-democrat; }
.@{fa-css-prefix}-deploydog:before { content: @fa-var-deploydog; }
.@{fa-css-prefix}-deskpro:before { content: @fa-var-deskpro; }
.@{fa-css-prefix}-desktop:before { content: @fa-var-desktop; }
.@{fa-css-prefix}-dev:before { content: @fa-var-dev; }
.@{fa-css-prefix}-deviantart:before { content: @fa-var-deviantart; }
.@{fa-css-prefix}-dharmachakra:before { content: @fa-var-dharmachakra; }
.@{fa-css-prefix}-dhl:before { content: @fa-var-dhl; }
.@{fa-css-prefix}-diagnoses:before { content: @fa-var-diagnoses; }
.@{fa-css-prefix}-diaspora:before { content: @fa-var-diaspora; }
.@{fa-css-prefix}-dice:before { content: @fa-var-dice; }
.@{fa-css-prefix}-dice-d20:before { content: @fa-var-dice-d20; }
.@{fa-css-prefix}-dice-d6:before { content: @fa-var-dice-d6; }
.@{fa-css-prefix}-dice-five:before { content: @fa-var-dice-five; }
.@{fa-css-prefix}-dice-four:before { content: @fa-var-dice-four; }
.@{fa-css-prefix}-dice-one:before { content: @fa-var-dice-one; }
.@{fa-css-prefix}-dice-six:before { content: @fa-var-dice-six; }
.@{fa-css-prefix}-dice-three:before { content: @fa-var-dice-three; }
.@{fa-css-prefix}-dice-two:before { content: @fa-var-dice-two; }
.@{fa-css-prefix}-digg:before { content: @fa-var-digg; }
.@{fa-css-prefix}-digital-ocean:before { content: @fa-var-digital-ocean; }
.@{fa-css-prefix}-digital-tachograph:before { content: @fa-var-digital-tachograph; }
.@{fa-css-prefix}-directions:before { content: @fa-var-directions; }
.@{fa-css-prefix}-discord:before { content: @fa-var-discord; }
.@{fa-css-prefix}-discourse:before { content: @fa-var-discourse; }
.@{fa-css-prefix}-disease:before { content: @fa-var-disease; }
.@{fa-css-prefix}-divide:before { content: @fa-var-divide; }
.@{fa-css-prefix}-dizzy:before { content: @fa-var-dizzy; }
.@{fa-css-prefix}-dna:before { content: @fa-var-dna; }
.@{fa-css-prefix}-dochub:before { content: @fa-var-dochub; }
.@{fa-css-prefix}-docker:before { content: @fa-var-docker; }
.@{fa-css-prefix}-dog:before { content: @fa-var-dog; }
.@{fa-css-prefix}-dollar-sign:before { content: @fa-var-dollar-sign; }
.@{fa-css-prefix}-dolly:before { content: @fa-var-dolly; }
.@{fa-css-prefix}-dolly-flatbed:before { content: @fa-var-dolly-flatbed; }
.@{fa-css-prefix}-donate:before { content: @fa-var-donate; }
.@{fa-css-prefix}-door-closed:before { content: @fa-var-door-closed; }
.@{fa-css-prefix}-door-open:before { content: @fa-var-door-open; }
.@{fa-css-prefix}-dot-circle:before { content: @fa-var-dot-circle; }
.@{fa-css-prefix}-dove:before { content: @fa-var-dove; }
.@{fa-css-prefix}-download:before { content: @fa-var-download; }
.@{fa-css-prefix}-draft2digital:before { content: @fa-var-draft2digital; }
.@{fa-css-prefix}-drafting-compass:before { content: @fa-var-drafting-compass; }
.@{fa-css-prefix}-dragon:before { content: @fa-var-dragon; }
.@{fa-css-prefix}-draw-polygon:before { content: @fa-var-draw-polygon; }
.@{fa-css-prefix}-dribbble:before { content: @fa-var-dribbble; }
.@{fa-css-prefix}-dribbble-square:before { content: @fa-var-dribbble-square; }
.@{fa-css-prefix}-dropbox:before { content: @fa-var-dropbox; }
.@{fa-css-prefix}-drum:before { content: @fa-var-drum; }
.@{fa-css-prefix}-drum-steelpan:before { content: @fa-var-drum-steelpan; }
.@{fa-css-prefix}-drumstick-bite:before { content: @fa-var-drumstick-bite; }
.@{fa-css-prefix}-drupal:before { content: @fa-var-drupal; }
.@{fa-css-prefix}-dumbbell:before { content: @fa-var-dumbbell; }
.@{fa-css-prefix}-dumpster:before { content: @fa-var-dumpster; }
.@{fa-css-prefix}-dumpster-fire:before { content: @fa-var-dumpster-fire; }
.@{fa-css-prefix}-dungeon:before { content: @fa-var-dungeon; }
.@{fa-css-prefix}-dyalog:before { content: @fa-var-dyalog; }
.@{fa-css-prefix}-earlybirds:before { content: @fa-var-earlybirds; }
.@{fa-css-prefix}-ebay:before { content: @fa-var-ebay; }
.@{fa-css-prefix}-edge:before { content: @fa-var-edge; }
.@{fa-css-prefix}-edit:before { content: @fa-var-edit; }
.@{fa-css-prefix}-egg:before { content: @fa-var-egg; }
.@{fa-css-prefix}-eject:before { content: @fa-var-eject; }
.@{fa-css-prefix}-elementor:before { content: @fa-var-elementor; }
.@{fa-css-prefix}-ellipsis-h:before { content: @fa-var-ellipsis-h; }
.@{fa-css-prefix}-ellipsis-v:before { content: @fa-var-ellipsis-v; }
.@{fa-css-prefix}-ello:before { content: @fa-var-ello; }
.@{fa-css-prefix}-ember:before { content: @fa-var-ember; }
.@{fa-css-prefix}-empire:before { content: @fa-var-empire; }
.@{fa-css-prefix}-envelope:before { content: @fa-var-envelope; }
.@{fa-css-prefix}-envelope-open:before { content: @fa-var-envelope-open; }
.@{fa-css-prefix}-envelope-open-text:before { content: @fa-var-envelope-open-text; }
.@{fa-css-prefix}-envelope-square:before { content: @fa-var-envelope-square; }
.@{fa-css-prefix}-envira:before { content: @fa-var-envira; }
.@{fa-css-prefix}-equals:before { content: @fa-var-equals; }
.@{fa-css-prefix}-eraser:before { content: @fa-var-eraser; }
.@{fa-css-prefix}-erlang:before { content: @fa-var-erlang; }
.@{fa-css-prefix}-ethereum:before { content: @fa-var-ethereum; }
.@{fa-css-prefix}-ethernet:before { content: @fa-var-ethernet; }
.@{fa-css-prefix}-etsy:before { content: @fa-var-etsy; }
.@{fa-css-prefix}-euro-sign:before { content: @fa-var-euro-sign; }
.@{fa-css-prefix}-evernote:before { content: @fa-var-evernote; }
.@{fa-css-prefix}-exchange-alt:before { content: @fa-var-exchange-alt; }
.@{fa-css-prefix}-exclamation:before { content: @fa-var-exclamation; }
.@{fa-css-prefix}-exclamation-circle:before { content: @fa-var-exclamation-circle; }
.@{fa-css-prefix}-exclamation-triangle:before { content: @fa-var-exclamation-triangle; }
.@{fa-css-prefix}-expand:before { content: @fa-var-expand; }
.@{fa-css-prefix}-expand-alt:before { content: @fa-var-expand-alt; }
.@{fa-css-prefix}-expand-arrows-alt:before { content: @fa-var-expand-arrows-alt; }
.@{fa-css-prefix}-expeditedssl:before { content: @fa-var-expeditedssl; }
.@{fa-css-prefix}-external-link-alt:before { content: @fa-var-external-link-alt; }
.@{fa-css-prefix}-external-link-square-alt:before { content: @fa-var-external-link-square-alt; }
.@{fa-css-prefix}-eye:before { content: @fa-var-eye; }
.@{fa-css-prefix}-eye-dropper:before { content: @fa-var-eye-dropper; }
.@{fa-css-prefix}-eye-slash:before { content: @fa-var-eye-slash; }
.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; }
.@{fa-css-prefix}-facebook-f:before { content: @fa-var-facebook-f; }
.@{fa-css-prefix}-facebook-messenger:before { content: @fa-var-facebook-messenger; }
.@{fa-css-prefix}-facebook-square:before { content: @fa-var-facebook-square; }
.@{fa-css-prefix}-fan:before { content: @fa-var-fan; }
.@{fa-css-prefix}-fantasy-flight-games:before { content: @fa-var-fantasy-flight-games; }
.@{fa-css-prefix}-fast-backward:before { content: @fa-var-fast-backward; }
.@{fa-css-prefix}-fast-forward:before { content: @fa-var-fast-forward; }
.@{fa-css-prefix}-faucet:before { content: @fa-var-faucet; }
.@{fa-css-prefix}-fax:before { content: @fa-var-fax; }
.@{fa-css-prefix}-feather:before { content: @fa-var-feather; }
.@{fa-css-prefix}-feather-alt:before { content: @fa-var-feather-alt; }
.@{fa-css-prefix}-fedex:before { content: @fa-var-fedex; }
.@{fa-css-prefix}-fedora:before { content: @fa-var-fedora; }
.@{fa-css-prefix}-female:before { content: @fa-var-female; }
.@{fa-css-prefix}-fighter-jet:before { content: @fa-var-fighter-jet; }
.@{fa-css-prefix}-figma:before { content: @fa-var-figma; }
.@{fa-css-prefix}-file:before { content: @fa-var-file; }
.@{fa-css-prefix}-file-alt:before { content: @fa-var-file-alt; }
.@{fa-css-prefix}-file-archive:before { content: @fa-var-file-archive; }
.@{fa-css-prefix}-file-audio:before { content: @fa-var-file-audio; }
.@{fa-css-prefix}-file-code:before { content: @fa-var-file-code; }
.@{fa-css-prefix}-file-contract:before { content: @fa-var-file-contract; }
.@{fa-css-prefix}-file-csv:before { content: @fa-var-file-csv; }
.@{fa-css-prefix}-file-download:before { content: @fa-var-file-download; }
.@{fa-css-prefix}-file-excel:before { content: @fa-var-file-excel; }
.@{fa-css-prefix}-file-export:before { content: @fa-var-file-export; }
.@{fa-css-prefix}-file-image:before { content: @fa-var-file-image; }
.@{fa-css-prefix}-file-import:before { content: @fa-var-file-import; }
.@{fa-css-prefix}-file-invoice:before { content: @fa-var-file-invoice; }
.@{fa-css-prefix}-file-invoice-dollar:before { content: @fa-var-file-invoice-dollar; }
.@{fa-css-prefix}-file-medical:before { content: @fa-var-file-medical; }
.@{fa-css-prefix}-file-medical-alt:before { content: @fa-var-file-medical-alt; }
.@{fa-css-prefix}-file-pdf:before { content: @fa-var-file-pdf; }
.@{fa-css-prefix}-file-powerpoint:before { content: @fa-var-file-powerpoint; }
.@{fa-css-prefix}-file-prescription:before { content: @fa-var-file-prescription; }
.@{fa-css-prefix}-file-signature:before { content: @fa-var-file-signature; }
.@{fa-css-prefix}-file-upload:before { content: @fa-var-file-upload; }
.@{fa-css-prefix}-file-video:before { content: @fa-var-file-video; }
.@{fa-css-prefix}-file-word:before { content: @fa-var-file-word; }
.@{fa-css-prefix}-fill:before { content: @fa-var-fill; }
.@{fa-css-prefix}-fill-drip:before { content: @fa-var-fill-drip; }
.@{fa-css-prefix}-film:before { content: @fa-var-film; }
.@{fa-css-prefix}-filter:before { content: @fa-var-filter; }
.@{fa-css-prefix}-fingerprint:before { content: @fa-var-fingerprint; }
.@{fa-css-prefix}-fire:before { content: @fa-var-fire; }
.@{fa-css-prefix}-fire-alt:before { content: @fa-var-fire-alt; }
.@{fa-css-prefix}-fire-extinguisher:before { content: @fa-var-fire-extinguisher; }
.@{fa-css-prefix}-firefox:before { content: @fa-var-firefox; }
.@{fa-css-prefix}-firefox-browser:before { content: @fa-var-firefox-browser; }
.@{fa-css-prefix}-first-aid:before { content: @fa-var-first-aid; }
.@{fa-css-prefix}-first-order:before { content: @fa-var-first-order; }
.@{fa-css-prefix}-first-order-alt:before { content: @fa-var-first-order-alt; }
.@{fa-css-prefix}-firstdraft:before { content: @fa-var-firstdraft; }
.@{fa-css-prefix}-fish:before { content: @fa-var-fish; }
.@{fa-css-prefix}-fist-raised:before { content: @fa-var-fist-raised; }
.@{fa-css-prefix}-flag:before { content: @fa-var-flag; }
.@{fa-css-prefix}-flag-checkered:before { content: @fa-var-flag-checkered; }
.@{fa-css-prefix}-flag-usa:before { content: @fa-var-flag-usa; }
.@{fa-css-prefix}-flask:before { content: @fa-var-flask; }
.@{fa-css-prefix}-flickr:before { content: @fa-var-flickr; }
.@{fa-css-prefix}-flipboard:before { content: @fa-var-flipboard; }
.@{fa-css-prefix}-flushed:before { content: @fa-var-flushed; }
.@{fa-css-prefix}-fly:before { content: @fa-var-fly; }
.@{fa-css-prefix}-folder:before { content: @fa-var-folder; }
.@{fa-css-prefix}-folder-minus:before { content: @fa-var-folder-minus; }
.@{fa-css-prefix}-folder-open:before { content: @fa-var-folder-open; }
.@{fa-css-prefix}-folder-plus:before { content: @fa-var-folder-plus; }
.@{fa-css-prefix}-font:before { content: @fa-var-font; }
.@{fa-css-prefix}-font-awesome:before { content: @fa-var-font-awesome; }
.@{fa-css-prefix}-font-awesome-alt:before { content: @fa-var-font-awesome-alt; }
.@{fa-css-prefix}-font-awesome-flag:before { content: @fa-var-font-awesome-flag; }
.@{fa-css-prefix}-font-awesome-logo-full:before { content: @fa-var-font-awesome-logo-full; }
.@{fa-css-prefix}-fonticons:before { content: @fa-var-fonticons; }
.@{fa-css-prefix}-fonticons-fi:before { content: @fa-var-fonticons-fi; }
.@{fa-css-prefix}-football-ball:before { content: @fa-var-football-ball; }
.@{fa-css-prefix}-fort-awesome:before { content: @fa-var-fort-awesome; }
.@{fa-css-prefix}-fort-awesome-alt:before { content: @fa-var-fort-awesome-alt; }
.@{fa-css-prefix}-forumbee:before { content: @fa-var-forumbee; }
.@{fa-css-prefix}-forward:before { content: @fa-var-forward; }
.@{fa-css-prefix}-foursquare:before { content: @fa-var-foursquare; }
.@{fa-css-prefix}-free-code-camp:before { content: @fa-var-free-code-camp; }
.@{fa-css-prefix}-freebsd:before { content: @fa-var-freebsd; }
.@{fa-css-prefix}-frog:before { content: @fa-var-frog; }
.@{fa-css-prefix}-frown:before { content: @fa-var-frown; }
.@{fa-css-prefix}-frown-open:before { content: @fa-var-frown-open; }
.@{fa-css-prefix}-fulcrum:before { content: @fa-var-fulcrum; }
.@{fa-css-prefix}-funnel-dollar:before { content: @fa-var-funnel-dollar; }
.@{fa-css-prefix}-futbol:before { content: @fa-var-futbol; }
.@{fa-css-prefix}-galactic-republic:before { content: @fa-var-galactic-republic; }
.@{fa-css-prefix}-galactic-senate:before { content: @fa-var-galactic-senate; }
.@{fa-css-prefix}-gamepad:before { content: @fa-var-gamepad; }
.@{fa-css-prefix}-gas-pump:before { content: @fa-var-gas-pump; }
.@{fa-css-prefix}-gavel:before { content: @fa-var-gavel; }
.@{fa-css-prefix}-gem:before { content: @fa-var-gem; }
.@{fa-css-prefix}-genderless:before { content: @fa-var-genderless; }
.@{fa-css-prefix}-get-pocket:before { content: @fa-var-get-pocket; }
.@{fa-css-prefix}-gg:before { content: @fa-var-gg; }
.@{fa-css-prefix}-gg-circle:before { content: @fa-var-gg-circle; }
.@{fa-css-prefix}-ghost:before { content: @fa-var-ghost; }
.@{fa-css-prefix}-gift:before { content: @fa-var-gift; }
.@{fa-css-prefix}-gifts:before { content: @fa-var-gifts; }
.@{fa-css-prefix}-git:before { content: @fa-var-git; }
.@{fa-css-prefix}-git-alt:before { content: @fa-var-git-alt; }
.@{fa-css-prefix}-git-square:before { content: @fa-var-git-square; }
.@{fa-css-prefix}-github:before { content: @fa-var-github; }
.@{fa-css-prefix}-github-alt:before { content: @fa-var-github-alt; }
.@{fa-css-prefix}-github-square:before { content: @fa-var-github-square; }
.@{fa-css-prefix}-gitkraken:before { content: @fa-var-gitkraken; }
.@{fa-css-prefix}-gitlab:before { content: @fa-var-gitlab; }
.@{fa-css-prefix}-gitter:before { content: @fa-var-gitter; }
.@{fa-css-prefix}-glass-cheers:before { content: @fa-var-glass-cheers; }
.@{fa-css-prefix}-glass-martini:before { content: @fa-var-glass-martini; }
.@{fa-css-prefix}-glass-martini-alt:before { content: @fa-var-glass-martini-alt; }
.@{fa-css-prefix}-glass-whiskey:before { content: @fa-var-glass-whiskey; }
.@{fa-css-prefix}-glasses:before { content: @fa-var-glasses; }
.@{fa-css-prefix}-glide:before { content: @fa-var-glide; }
.@{fa-css-prefix}-glide-g:before { content: @fa-var-glide-g; }
.@{fa-css-prefix}-globe:before { content: @fa-var-globe; }
.@{fa-css-prefix}-globe-africa:before { content: @fa-var-globe-africa; }
.@{fa-css-prefix}-globe-americas:before { content: @fa-var-globe-americas; }
.@{fa-css-prefix}-globe-asia:before { content: @fa-var-globe-asia; }
.@{fa-css-prefix}-globe-europe:before { content: @fa-var-globe-europe; }
.@{fa-css-prefix}-gofore:before { content: @fa-var-gofore; }
.@{fa-css-prefix}-golf-ball:before { content: @fa-var-golf-ball; }
.@{fa-css-prefix}-goodreads:before { content: @fa-var-goodreads; }
.@{fa-css-prefix}-goodreads-g:before { content: @fa-var-goodreads-g; }
.@{fa-css-prefix}-google:before { content: @fa-var-google; }
.@{fa-css-prefix}-google-drive:before { content: @fa-var-google-drive; }
.@{fa-css-prefix}-google-play:before { content: @fa-var-google-play; }
.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus; }
.@{fa-css-prefix}-google-plus-g:before { content: @fa-var-google-plus-g; }
.@{fa-css-prefix}-google-plus-square:before { content: @fa-var-google-plus-square; }
.@{fa-css-prefix}-google-wallet:before { content: @fa-var-google-wallet; }
.@{fa-css-prefix}-gopuram:before { content: @fa-var-gopuram; }
.@{fa-css-prefix}-graduation-cap:before { content: @fa-var-graduation-cap; }
.@{fa-css-prefix}-gratipay:before { content: @fa-var-gratipay; }
.@{fa-css-prefix}-grav:before { content: @fa-var-grav; }
.@{fa-css-prefix}-greater-than:before { content: @fa-var-greater-than; }
.@{fa-css-prefix}-greater-than-equal:before { content: @fa-var-greater-than-equal; }
.@{fa-css-prefix}-grimace:before { content: @fa-var-grimace; }
.@{fa-css-prefix}-grin:before { content: @fa-var-grin; }
.@{fa-css-prefix}-grin-alt:before { content: @fa-var-grin-alt; }
.@{fa-css-prefix}-grin-beam:before { content: @fa-var-grin-beam; }
.@{fa-css-prefix}-grin-beam-sweat:before { content: @fa-var-grin-beam-sweat; }
.@{fa-css-prefix}-grin-hearts:before { content: @fa-var-grin-hearts; }
.@{fa-css-prefix}-grin-squint:before { content: @fa-var-grin-squint; }
.@{fa-css-prefix}-grin-squint-tears:before { content: @fa-var-grin-squint-tears; }
.@{fa-css-prefix}-grin-stars:before { content: @fa-var-grin-stars; }
.@{fa-css-prefix}-grin-tears:before { content: @fa-var-grin-tears; }
.@{fa-css-prefix}-grin-tongue:before { content: @fa-var-grin-tongue; }
.@{fa-css-prefix}-grin-tongue-squint:before { content: @fa-var-grin-tongue-squint; }
.@{fa-css-prefix}-grin-tongue-wink:before { content: @fa-var-grin-tongue-wink; }
.@{fa-css-prefix}-grin-wink:before { content: @fa-var-grin-wink; }
.@{fa-css-prefix}-grip-horizontal:before { content: @fa-var-grip-horizontal; }
.@{fa-css-prefix}-grip-lines:before { content: @fa-var-grip-lines; }
.@{fa-css-prefix}-grip-lines-vertical:before { content: @fa-var-grip-lines-vertical; }
.@{fa-css-prefix}-grip-vertical:before { content: @fa-var-grip-vertical; }
.@{fa-css-prefix}-gripfire:before { content: @fa-var-gripfire; }
.@{fa-css-prefix}-grunt:before { content: @fa-var-grunt; }
.@{fa-css-prefix}-guitar:before { content: @fa-var-guitar; }
.@{fa-css-prefix}-gulp:before { content: @fa-var-gulp; }
.@{fa-css-prefix}-h-square:before { content: @fa-var-h-square; }
.@{fa-css-prefix}-hacker-news:before { content: @fa-var-hacker-news; }
.@{fa-css-prefix}-hacker-news-square:before { content: @fa-var-hacker-news-square; }
.@{fa-css-prefix}-hackerrank:before { content: @fa-var-hackerrank; }
.@{fa-css-prefix}-hamburger:before { content: @fa-var-hamburger; }
.@{fa-css-prefix}-hammer:before { content: @fa-var-hammer; }
.@{fa-css-prefix}-hamsa:before { content: @fa-var-hamsa; }
.@{fa-css-prefix}-hand-holding:before { content: @fa-var-hand-holding; }
.@{fa-css-prefix}-hand-holding-heart:before { content: @fa-var-hand-holding-heart; }
.@{fa-css-prefix}-hand-holding-medical:before { content: @fa-var-hand-holding-medical; }
.@{fa-css-prefix}-hand-holding-usd:before { content: @fa-var-hand-holding-usd; }
.@{fa-css-prefix}-hand-holding-water:before { content: @fa-var-hand-holding-water; }
.@{fa-css-prefix}-hand-lizard:before { content: @fa-var-hand-lizard; }
.@{fa-css-prefix}-hand-middle-finger:before { content: @fa-var-hand-middle-finger; }
.@{fa-css-prefix}-hand-paper:before { content: @fa-var-hand-paper; }
.@{fa-css-prefix}-hand-peace:before { content: @fa-var-hand-peace; }
.@{fa-css-prefix}-hand-point-down:before { content: @fa-var-hand-point-down; }
.@{fa-css-prefix}-hand-point-left:before { content: @fa-var-hand-point-left; }
.@{fa-css-prefix}-hand-point-right:before { content: @fa-var-hand-point-right; }
.@{fa-css-prefix}-hand-point-up:before { content: @fa-var-hand-point-up; }
.@{fa-css-prefix}-hand-pointer:before { content: @fa-var-hand-pointer; }
.@{fa-css-prefix}-hand-rock:before { content: @fa-var-hand-rock; }
.@{fa-css-prefix}-hand-scissors:before { content: @fa-var-hand-scissors; }
.@{fa-css-prefix}-hand-sparkles:before { content: @fa-var-hand-sparkles; }
.@{fa-css-prefix}-hand-spock:before { content: @fa-var-hand-spock; }
.@{fa-css-prefix}-hands:before { content: @fa-var-hands; }
.@{fa-css-prefix}-hands-helping:before { content: @fa-var-hands-helping; }
.@{fa-css-prefix}-hands-wash:before { content: @fa-var-hands-wash; }
.@{fa-css-prefix}-handshake:before { content: @fa-var-handshake; }
.@{fa-css-prefix}-handshake-alt-slash:before { content: @fa-var-handshake-alt-slash; }
.@{fa-css-prefix}-handshake-slash:before { content: @fa-var-handshake-slash; }
.@{fa-css-prefix}-hanukiah:before { content: @fa-var-hanukiah; }
.@{fa-css-prefix}-hard-hat:before { content: @fa-var-hard-hat; }
.@{fa-css-prefix}-hashtag:before { content: @fa-var-hashtag; }
.@{fa-css-prefix}-hat-cowboy:before { content: @fa-var-hat-cowboy; }
.@{fa-css-prefix}-hat-cowboy-side:before { content: @fa-var-hat-cowboy-side; }
.@{fa-css-prefix}-hat-wizard:before { content: @fa-var-hat-wizard; }
.@{fa-css-prefix}-hdd:before { content: @fa-var-hdd; }
.@{fa-css-prefix}-head-side-cough:before { content: @fa-var-head-side-cough; }
.@{fa-css-prefix}-head-side-cough-slash:before { content: @fa-var-head-side-cough-slash; }
.@{fa-css-prefix}-head-side-mask:before { content: @fa-var-head-side-mask; }
.@{fa-css-prefix}-head-side-virus:before { content: @fa-var-head-side-virus; }
.@{fa-css-prefix}-heading:before { content: @fa-var-heading; }
.@{fa-css-prefix}-headphones:before { content: @fa-var-headphones; }
.@{fa-css-prefix}-headphones-alt:before { content: @fa-var-headphones-alt; }
.@{fa-css-prefix}-headset:before { content: @fa-var-headset; }
.@{fa-css-prefix}-heart:before { content: @fa-var-heart; }
.@{fa-css-prefix}-heart-broken:before { content: @fa-var-heart-broken; }
.@{fa-css-prefix}-heartbeat:before { content: @fa-var-heartbeat; }
.@{fa-css-prefix}-helicopter:before { content: @fa-var-helicopter; }
.@{fa-css-prefix}-highlighter:before { content: @fa-var-highlighter; }
.@{fa-css-prefix}-hiking:before { content: @fa-var-hiking; }
.@{fa-css-prefix}-hippo:before { content: @fa-var-hippo; }
.@{fa-css-prefix}-hips:before { content: @fa-var-hips; }
.@{fa-css-prefix}-hire-a-helper:before { content: @fa-var-hire-a-helper; }
.@{fa-css-prefix}-history:before { content: @fa-var-history; }
.@{fa-css-prefix}-hockey-puck:before { content: @fa-var-hockey-puck; }
.@{fa-css-prefix}-holly-berry:before { content: @fa-var-holly-berry; }
.@{fa-css-prefix}-home:before { content: @fa-var-home; }
.@{fa-css-prefix}-hooli:before { content: @fa-var-hooli; }
.@{fa-css-prefix}-hornbill:before { content: @fa-var-hornbill; }
.@{fa-css-prefix}-horse:before { content: @fa-var-horse; }
.@{fa-css-prefix}-horse-head:before { content: @fa-var-horse-head; }
.@{fa-css-prefix}-hospital:before { content: @fa-var-hospital; }
.@{fa-css-prefix}-hospital-alt:before { content: @fa-var-hospital-alt; }
.@{fa-css-prefix}-hospital-symbol:before { content: @fa-var-hospital-symbol; }
.@{fa-css-prefix}-hospital-user:before { content: @fa-var-hospital-user; }
.@{fa-css-prefix}-hot-tub:before { content: @fa-var-hot-tub; }
.@{fa-css-prefix}-hotdog:before { content: @fa-var-hotdog; }
.@{fa-css-prefix}-hotel:before { content: @fa-var-hotel; }
.@{fa-css-prefix}-hotjar:before { content: @fa-var-hotjar; }
.@{fa-css-prefix}-hourglass:before { content: @fa-var-hourglass; }
.@{fa-css-prefix}-hourglass-end:before { content: @fa-var-hourglass-end; }
.@{fa-css-prefix}-hourglass-half:before { content: @fa-var-hourglass-half; }
.@{fa-css-prefix}-hourglass-start:before { content: @fa-var-hourglass-start; }
.@{fa-css-prefix}-house-damage:before { content: @fa-var-house-damage; }
.@{fa-css-prefix}-house-user:before { content: @fa-var-house-user; }
.@{fa-css-prefix}-houzz:before { content: @fa-var-houzz; }
.@{fa-css-prefix}-hryvnia:before { content: @fa-var-hryvnia; }
.@{fa-css-prefix}-html5:before { content: @fa-var-html5; }
.@{fa-css-prefix}-hubspot:before { content: @fa-var-hubspot; }
.@{fa-css-prefix}-i-cursor:before { content: @fa-var-i-cursor; }
.@{fa-css-prefix}-ice-cream:before { content: @fa-var-ice-cream; }
.@{fa-css-prefix}-icicles:before { content: @fa-var-icicles; }
.@{fa-css-prefix}-icons:before { content: @fa-var-icons; }
.@{fa-css-prefix}-id-badge:before { content: @fa-var-id-badge; }
.@{fa-css-prefix}-id-card:before { content: @fa-var-id-card; }
.@{fa-css-prefix}-id-card-alt:before { content: @fa-var-id-card-alt; }
.@{fa-css-prefix}-ideal:before { content: @fa-var-ideal; }
.@{fa-css-prefix}-igloo:before { content: @fa-var-igloo; }
.@{fa-css-prefix}-image:before { content: @fa-var-image; }
.@{fa-css-prefix}-images:before { content: @fa-var-images; }
.@{fa-css-prefix}-imdb:before { content: @fa-var-imdb; }
.@{fa-css-prefix}-inbox:before { content: @fa-var-inbox; }
.@{fa-css-prefix}-indent:before { content: @fa-var-indent; }
.@{fa-css-prefix}-industry:before { content: @fa-var-industry; }
.@{fa-css-prefix}-infinity:before { content: @fa-var-infinity; }
.@{fa-css-prefix}-info:before { content: @fa-var-info; }
.@{fa-css-prefix}-info-circle:before { content: @fa-var-info-circle; }
.@{fa-css-prefix}-instagram:before { content: @fa-var-instagram; }
.@{fa-css-prefix}-instagram-square:before { content: @fa-var-instagram-square; }
.@{fa-css-prefix}-intercom:before { content: @fa-var-intercom; }
.@{fa-css-prefix}-internet-explorer:before { content: @fa-var-internet-explorer; }
.@{fa-css-prefix}-invision:before { content: @fa-var-invision; }
.@{fa-css-prefix}-ioxhost:before { content: @fa-var-ioxhost; }
.@{fa-css-prefix}-italic:before { content: @fa-var-italic; }
.@{fa-css-prefix}-itch-io:before { content: @fa-var-itch-io; }
.@{fa-css-prefix}-itunes:before { content: @fa-var-itunes; }
.@{fa-css-prefix}-itunes-note:before { content: @fa-var-itunes-note; }
.@{fa-css-prefix}-java:before { content: @fa-var-java; }
.@{fa-css-prefix}-jedi:before { content: @fa-var-jedi; }
.@{fa-css-prefix}-jedi-order:before { content: @fa-var-jedi-order; }
.@{fa-css-prefix}-jenkins:before { content: @fa-var-jenkins; }
.@{fa-css-prefix}-jira:before { content: @fa-var-jira; }
.@{fa-css-prefix}-joget:before { content: @fa-var-joget; }
.@{fa-css-prefix}-joint:before { content: @fa-var-joint; }
.@{fa-css-prefix}-joomla:before { content: @fa-var-joomla; }
.@{fa-css-prefix}-journal-whills:before { content: @fa-var-journal-whills; }
.@{fa-css-prefix}-js:before { content: @fa-var-js; }
.@{fa-css-prefix}-js-square:before { content: @fa-var-js-square; }
.@{fa-css-prefix}-jsfiddle:before { content: @fa-var-jsfiddle; }
.@{fa-css-prefix}-kaaba:before { content: @fa-var-kaaba; }
.@{fa-css-prefix}-kaggle:before { content: @fa-var-kaggle; }
.@{fa-css-prefix}-key:before { content: @fa-var-key; }
.@{fa-css-prefix}-keybase:before { content: @fa-var-keybase; }
.@{fa-css-prefix}-keyboard:before { content: @fa-var-keyboard; }
.@{fa-css-prefix}-keycdn:before { content: @fa-var-keycdn; }
.@{fa-css-prefix}-khanda:before { content: @fa-var-khanda; }
.@{fa-css-prefix}-kickstarter:before { content: @fa-var-kickstarter; }
.@{fa-css-prefix}-kickstarter-k:before { content: @fa-var-kickstarter-k; }
.@{fa-css-prefix}-kiss:before { content: @fa-var-kiss; }
.@{fa-css-prefix}-kiss-beam:before { content: @fa-var-kiss-beam; }
.@{fa-css-prefix}-kiss-wink-heart:before { content: @fa-var-kiss-wink-heart; }
.@{fa-css-prefix}-kiwi-bird:before { content: @fa-var-kiwi-bird; }
.@{fa-css-prefix}-korvue:before { content: @fa-var-korvue; }
.@{fa-css-prefix}-landmark:before { content: @fa-var-landmark; }
.@{fa-css-prefix}-language:before { content: @fa-var-language; }
.@{fa-css-prefix}-laptop:before { content: @fa-var-laptop; }
.@{fa-css-prefix}-laptop-code:before { content: @fa-var-laptop-code; }
.@{fa-css-prefix}-laptop-house:before { content: @fa-var-laptop-house; }
.@{fa-css-prefix}-laptop-medical:before { content: @fa-var-laptop-medical; }
.@{fa-css-prefix}-laravel:before { content: @fa-var-laravel; }
.@{fa-css-prefix}-lastfm:before { content: @fa-var-lastfm; }
.@{fa-css-prefix}-lastfm-square:before { content: @fa-var-lastfm-square; }
.@{fa-css-prefix}-laugh:before { content: @fa-var-laugh; }
.@{fa-css-prefix}-laugh-beam:before { content: @fa-var-laugh-beam; }
.@{fa-css-prefix}-laugh-squint:before { content: @fa-var-laugh-squint; }
.@{fa-css-prefix}-laugh-wink:before { content: @fa-var-laugh-wink; }
.@{fa-css-prefix}-layer-group:before { content: @fa-var-layer-group; }
.@{fa-css-prefix}-leaf:before { content: @fa-var-leaf; }
.@{fa-css-prefix}-leanpub:before { content: @fa-var-leanpub; }
.@{fa-css-prefix}-lemon:before { content: @fa-var-lemon; }
.@{fa-css-prefix}-less:before { content: @fa-var-less; }
.@{fa-css-prefix}-less-than:before { content: @fa-var-less-than; }
.@{fa-css-prefix}-less-than-equal:before { content: @fa-var-less-than-equal; }
.@{fa-css-prefix}-level-down-alt:before { content: @fa-var-level-down-alt; }
.@{fa-css-prefix}-level-up-alt:before { content: @fa-var-level-up-alt; }
.@{fa-css-prefix}-life-ring:before { content: @fa-var-life-ring; }
.@{fa-css-prefix}-lightbulb:before { content: @fa-var-lightbulb; }
.@{fa-css-prefix}-line:before { content: @fa-var-line; }
.@{fa-css-prefix}-link:before { content: @fa-var-link; }
.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin; }
.@{fa-css-prefix}-linkedin-in:before { content: @fa-var-linkedin-in; }
.@{fa-css-prefix}-linode:before { content: @fa-var-linode; }
.@{fa-css-prefix}-linux:before { content: @fa-var-linux; }
.@{fa-css-prefix}-lira-sign:before { content: @fa-var-lira-sign; }
.@{fa-css-prefix}-list:before { content: @fa-var-list; }
.@{fa-css-prefix}-list-alt:before { content: @fa-var-list-alt; }
.@{fa-css-prefix}-list-ol:before { content: @fa-var-list-ol; }
.@{fa-css-prefix}-list-ul:before { content: @fa-var-list-ul; }
.@{fa-css-prefix}-location-arrow:before { content: @fa-var-location-arrow; }
.@{fa-css-prefix}-lock:before { content: @fa-var-lock; }
.@{fa-css-prefix}-lock-open:before { content: @fa-var-lock-open; }
.@{fa-css-prefix}-long-arrow-alt-down:before { content: @fa-var-long-arrow-alt-down; }
.@{fa-css-prefix}-long-arrow-alt-left:before { content: @fa-var-long-arrow-alt-left; }
.@{fa-css-prefix}-long-arrow-alt-right:before { content: @fa-var-long-arrow-alt-right; }
.@{fa-css-prefix}-long-arrow-alt-up:before { content: @fa-var-long-arrow-alt-up; }
.@{fa-css-prefix}-low-vision:before { content: @fa-var-low-vision; }
.@{fa-css-prefix}-luggage-cart:before { content: @fa-var-luggage-cart; }
.@{fa-css-prefix}-lungs:before { content: @fa-var-lungs; }
.@{fa-css-prefix}-lungs-virus:before { content: @fa-var-lungs-virus; }
.@{fa-css-prefix}-lyft:before { content: @fa-var-lyft; }
.@{fa-css-prefix}-magento:before { content: @fa-var-magento; }
.@{fa-css-prefix}-magic:before { content: @fa-var-magic; }
.@{fa-css-prefix}-magnet:before { content: @fa-var-magnet; }
.@{fa-css-prefix}-mail-bulk:before { content: @fa-var-mail-bulk; }
.@{fa-css-prefix}-mailchimp:before { content: @fa-var-mailchimp; }
.@{fa-css-prefix}-male:before { content: @fa-var-male; }
.@{fa-css-prefix}-mandalorian:before { content: @fa-var-mandalorian; }
.@{fa-css-prefix}-map:before { content: @fa-var-map; }
.@{fa-css-prefix}-map-marked:before { content: @fa-var-map-marked; }
.@{fa-css-prefix}-map-marked-alt:before { content: @fa-var-map-marked-alt; }
.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker; }
.@{fa-css-prefix}-map-marker-alt:before { content: @fa-var-map-marker-alt; }
.@{fa-css-prefix}-map-pin:before { content: @fa-var-map-pin; }
.@{fa-css-prefix}-map-signs:before { content: @fa-var-map-signs; }
.@{fa-css-prefix}-markdown:before { content: @fa-var-markdown; }
.@{fa-css-prefix}-marker:before { content: @fa-var-marker; }
.@{fa-css-prefix}-mars:before { content: @fa-var-mars; }
.@{fa-css-prefix}-mars-double:before { content: @fa-var-mars-double; }
.@{fa-css-prefix}-mars-stroke:before { content: @fa-var-mars-stroke; }
.@{fa-css-prefix}-mars-stroke-h:before { content: @fa-var-mars-stroke-h; }
.@{fa-css-prefix}-mars-stroke-v:before { content: @fa-var-mars-stroke-v; }
.@{fa-css-prefix}-mask:before { content: @fa-var-mask; }
.@{fa-css-prefix}-mastodon:before { content: @fa-var-mastodon; }
.@{fa-css-prefix}-maxcdn:before { content: @fa-var-maxcdn; }
.@{fa-css-prefix}-mdb:before { content: @fa-var-mdb; }
.@{fa-css-prefix}-medal:before { content: @fa-var-medal; }
.@{fa-css-prefix}-medapps:before { content: @fa-var-medapps; }
.@{fa-css-prefix}-medium:before { content: @fa-var-medium; }
.@{fa-css-prefix}-medium-m:before { content: @fa-var-medium-m; }
.@{fa-css-prefix}-medkit:before { content: @fa-var-medkit; }
.@{fa-css-prefix}-medrt:before { content: @fa-var-medrt; }
.@{fa-css-prefix}-meetup:before { content: @fa-var-meetup; }
.@{fa-css-prefix}-megaport:before { content: @fa-var-megaport; }
.@{fa-css-prefix}-meh:before { content: @fa-var-meh; }
.@{fa-css-prefix}-meh-blank:before { content: @fa-var-meh-blank; }
.@{fa-css-prefix}-meh-rolling-eyes:before { content: @fa-var-meh-rolling-eyes; }
.@{fa-css-prefix}-memory:before { content: @fa-var-memory; }
.@{fa-css-prefix}-mendeley:before { content: @fa-var-mendeley; }
.@{fa-css-prefix}-menorah:before { content: @fa-var-menorah; }
.@{fa-css-prefix}-mercury:before { content: @fa-var-mercury; }
.@{fa-css-prefix}-meteor:before { content: @fa-var-meteor; }
.@{fa-css-prefix}-microblog:before { content: @fa-var-microblog; }
.@{fa-css-prefix}-microchip:before { content: @fa-var-microchip; }
.@{fa-css-prefix}-microphone:before { content: @fa-var-microphone; }
.@{fa-css-prefix}-microphone-alt:before { content: @fa-var-microphone-alt; }
.@{fa-css-prefix}-microphone-alt-slash:before { content: @fa-var-microphone-alt-slash; }
.@{fa-css-prefix}-microphone-slash:before { content: @fa-var-microphone-slash; }
.@{fa-css-prefix}-microscope:before { content: @fa-var-microscope; }
.@{fa-css-prefix}-microsoft:before { content: @fa-var-microsoft; }
.@{fa-css-prefix}-minus:before { content: @fa-var-minus; }
.@{fa-css-prefix}-minus-circle:before { content: @fa-var-minus-circle; }
.@{fa-css-prefix}-minus-square:before { content: @fa-var-minus-square; }
.@{fa-css-prefix}-mitten:before { content: @fa-var-mitten; }
.@{fa-css-prefix}-mix:before { content: @fa-var-mix; }
.@{fa-css-prefix}-mixcloud:before { content: @fa-var-mixcloud; }
.@{fa-css-prefix}-mixer:before { content: @fa-var-mixer; }
.@{fa-css-prefix}-mizuni:before { content: @fa-var-mizuni; }
.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile; }
.@{fa-css-prefix}-mobile-alt:before { content: @fa-var-mobile-alt; }
.@{fa-css-prefix}-modx:before { content: @fa-var-modx; }
.@{fa-css-prefix}-monero:before { content: @fa-var-monero; }
.@{fa-css-prefix}-money-bill:before { content: @fa-var-money-bill; }
.@{fa-css-prefix}-money-bill-alt:before { content: @fa-var-money-bill-alt; }
.@{fa-css-prefix}-money-bill-wave:before { content: @fa-var-money-bill-wave; }
.@{fa-css-prefix}-money-bill-wave-alt:before { content: @fa-var-money-bill-wave-alt; }
.@{fa-css-prefix}-money-check:before { content: @fa-var-money-check; }
.@{fa-css-prefix}-money-check-alt:before { content: @fa-var-money-check-alt; }
.@{fa-css-prefix}-monument:before { content: @fa-var-monument; }
.@{fa-css-prefix}-moon:before { content: @fa-var-moon; }
.@{fa-css-prefix}-mortar-pestle:before { content: @fa-var-mortar-pestle; }
.@{fa-css-prefix}-mosque:before { content: @fa-var-mosque; }
.@{fa-css-prefix}-motorcycle:before { content: @fa-var-motorcycle; }
.@{fa-css-prefix}-mountain:before { content: @fa-var-mountain; }
.@{fa-css-prefix}-mouse:before { content: @fa-var-mouse; }
.@{fa-css-prefix}-mouse-pointer:before { content: @fa-var-mouse-pointer; }
.@{fa-css-prefix}-mug-hot:before { content: @fa-var-mug-hot; }
.@{fa-css-prefix}-music:before { content: @fa-var-music; }
.@{fa-css-prefix}-napster:before { content: @fa-var-napster; }
.@{fa-css-prefix}-neos:before { content: @fa-var-neos; }
.@{fa-css-prefix}-network-wired:before { content: @fa-var-network-wired; }
.@{fa-css-prefix}-neuter:before { content: @fa-var-neuter; }
.@{fa-css-prefix}-newspaper:before { content: @fa-var-newspaper; }
.@{fa-css-prefix}-nimblr:before { content: @fa-var-nimblr; }
.@{fa-css-prefix}-node:before { content: @fa-var-node; }
.@{fa-css-prefix}-node-js:before { content: @fa-var-node-js; }
.@{fa-css-prefix}-not-equal:before { content: @fa-var-not-equal; }
.@{fa-css-prefix}-notes-medical:before { content: @fa-var-notes-medical; }
.@{fa-css-prefix}-npm:before { content: @fa-var-npm; }
.@{fa-css-prefix}-ns8:before { content: @fa-var-ns8; }
.@{fa-css-prefix}-nutritionix:before { content: @fa-var-nutritionix; }
.@{fa-css-prefix}-object-group:before { content: @fa-var-object-group; }
.@{fa-css-prefix}-object-ungroup:before { content: @fa-var-object-ungroup; }
.@{fa-css-prefix}-odnoklassniki:before { content: @fa-var-odnoklassniki; }
.@{fa-css-prefix}-odnoklassniki-square:before { content: @fa-var-odnoklassniki-square; }
.@{fa-css-prefix}-oil-can:before { content: @fa-var-oil-can; }
.@{fa-css-prefix}-old-republic:before { content: @fa-var-old-republic; }
.@{fa-css-prefix}-om:before { content: @fa-var-om; }
.@{fa-css-prefix}-opencart:before { content: @fa-var-opencart; }
.@{fa-css-prefix}-openid:before { content: @fa-var-openid; }
.@{fa-css-prefix}-opera:before { content: @fa-var-opera; }
.@{fa-css-prefix}-optin-monster:before { content: @fa-var-optin-monster; }
.@{fa-css-prefix}-orcid:before { content: @fa-var-orcid; }
.@{fa-css-prefix}-osi:before { content: @fa-var-osi; }
.@{fa-css-prefix}-otter:before { content: @fa-var-otter; }
.@{fa-css-prefix}-outdent:before { content: @fa-var-outdent; }
.@{fa-css-prefix}-page4:before { content: @fa-var-page4; }
.@{fa-css-prefix}-pagelines:before { content: @fa-var-pagelines; }
.@{fa-css-prefix}-pager:before { content: @fa-var-pager; }
.@{fa-css-prefix}-paint-brush:before { content: @fa-var-paint-brush; }
.@{fa-css-prefix}-paint-roller:before { content: @fa-var-paint-roller; }
.@{fa-css-prefix}-palette:before { content: @fa-var-palette; }
.@{fa-css-prefix}-palfed:before { content: @fa-var-palfed; }
.@{fa-css-prefix}-pallet:before { content: @fa-var-pallet; }
.@{fa-css-prefix}-paper-plane:before { content: @fa-var-paper-plane; }
.@{fa-css-prefix}-paperclip:before { content: @fa-var-paperclip; }
.@{fa-css-prefix}-parachute-box:before { content: @fa-var-parachute-box; }
.@{fa-css-prefix}-paragraph:before { content: @fa-var-paragraph; }
.@{fa-css-prefix}-parking:before { content: @fa-var-parking; }
.@{fa-css-prefix}-passport:before { content: @fa-var-passport; }
.@{fa-css-prefix}-pastafarianism:before { content: @fa-var-pastafarianism; }
.@{fa-css-prefix}-paste:before { content: @fa-var-paste; }
.@{fa-css-prefix}-patreon:before { content: @fa-var-patreon; }
.@{fa-css-prefix}-pause:before { content: @fa-var-pause; }
.@{fa-css-prefix}-pause-circle:before { content: @fa-var-pause-circle; }
.@{fa-css-prefix}-paw:before { content: @fa-var-paw; }
.@{fa-css-prefix}-paypal:before { content: @fa-var-paypal; }
.@{fa-css-prefix}-peace:before { content: @fa-var-peace; }
.@{fa-css-prefix}-pen:before { content: @fa-var-pen; }
.@{fa-css-prefix}-pen-alt:before { content: @fa-var-pen-alt; }
.@{fa-css-prefix}-pen-fancy:before { content: @fa-var-pen-fancy; }
.@{fa-css-prefix}-pen-nib:before { content: @fa-var-pen-nib; }
.@{fa-css-prefix}-pen-square:before { content: @fa-var-pen-square; }
.@{fa-css-prefix}-pencil-alt:before { content: @fa-var-pencil-alt; }
.@{fa-css-prefix}-pencil-ruler:before { content: @fa-var-pencil-ruler; }
.@{fa-css-prefix}-penny-arcade:before { content: @fa-var-penny-arcade; }
.@{fa-css-prefix}-people-arrows:before { content: @fa-var-people-arrows; }
.@{fa-css-prefix}-people-carry:before { content: @fa-var-people-carry; }
.@{fa-css-prefix}-pepper-hot:before { content: @fa-var-pepper-hot; }
.@{fa-css-prefix}-percent:before { content: @fa-var-percent; }
.@{fa-css-prefix}-percentage:before { content: @fa-var-percentage; }
.@{fa-css-prefix}-periscope:before { content: @fa-var-periscope; }
.@{fa-css-prefix}-person-booth:before { content: @fa-var-person-booth; }
.@{fa-css-prefix}-phabricator:before { content: @fa-var-phabricator; }
.@{fa-css-prefix}-phoenix-framework:before { content: @fa-var-phoenix-framework; }
.@{fa-css-prefix}-phoenix-squadron:before { content: @fa-var-phoenix-squadron; }
.@{fa-css-prefix}-phone:before { content: @fa-var-phone; }
.@{fa-css-prefix}-phone-alt:before { content: @fa-var-phone-alt; }
.@{fa-css-prefix}-phone-slash:before { content: @fa-var-phone-slash; }
.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; }
.@{fa-css-prefix}-phone-square-alt:before { content: @fa-var-phone-square-alt; }
.@{fa-css-prefix}-phone-volume:before { content: @fa-var-phone-volume; }
.@{fa-css-prefix}-photo-video:before { content: @fa-var-photo-video; }
.@{fa-css-prefix}-php:before { content: @fa-var-php; }
.@{fa-css-prefix}-pied-piper:before { content: @fa-var-pied-piper; }
.@{fa-css-prefix}-pied-piper-alt:before { content: @fa-var-pied-piper-alt; }
.@{fa-css-prefix}-pied-piper-hat:before { content: @fa-var-pied-piper-hat; }
.@{fa-css-prefix}-pied-piper-pp:before { content: @fa-var-pied-piper-pp; }
.@{fa-css-prefix}-pied-piper-square:before { content: @fa-var-pied-piper-square; }
.@{fa-css-prefix}-piggy-bank:before { content: @fa-var-piggy-bank; }
.@{fa-css-prefix}-pills:before { content: @fa-var-pills; }
.@{fa-css-prefix}-pinterest:before { content: @fa-var-pinterest; }
.@{fa-css-prefix}-pinterest-p:before { content: @fa-var-pinterest-p; }
.@{fa-css-prefix}-pinterest-square:before { content: @fa-var-pinterest-square; }
.@{fa-css-prefix}-pizza-slice:before { content: @fa-var-pizza-slice; }
.@{fa-css-prefix}-place-of-worship:before { content: @fa-var-place-of-worship; }
.@{fa-css-prefix}-plane:before { content: @fa-var-plane; }
.@{fa-css-prefix}-plane-arrival:before { content: @fa-var-plane-arrival; }
.@{fa-css-prefix}-plane-departure:before { content: @fa-var-plane-departure; }
.@{fa-css-prefix}-plane-slash:before { content: @fa-var-plane-slash; }
.@{fa-css-prefix}-play:before { content: @fa-var-play; }
.@{fa-css-prefix}-play-circle:before { content: @fa-var-play-circle; }
.@{fa-css-prefix}-playstation:before { content: @fa-var-playstation; }
.@{fa-css-prefix}-plug:before { content: @fa-var-plug; }
.@{fa-css-prefix}-plus:before { content: @fa-var-plus; }
.@{fa-css-prefix}-plus-circle:before { content: @fa-var-plus-circle; }
.@{fa-css-prefix}-plus-square:before { content: @fa-var-plus-square; }
.@{fa-css-prefix}-podcast:before { content: @fa-var-podcast; }
.@{fa-css-prefix}-poll:before { content: @fa-var-poll; }
.@{fa-css-prefix}-poll-h:before { content: @fa-var-poll-h; }
.@{fa-css-prefix}-poo:before { content: @fa-var-poo; }
.@{fa-css-prefix}-poo-storm:before { content: @fa-var-poo-storm; }
.@{fa-css-prefix}-poop:before { content: @fa-var-poop; }
.@{fa-css-prefix}-portrait:before { content: @fa-var-portrait; }
.@{fa-css-prefix}-pound-sign:before { content: @fa-var-pound-sign; }
.@{fa-css-prefix}-power-off:before { content: @fa-var-power-off; }
.@{fa-css-prefix}-pray:before { content: @fa-var-pray; }
.@{fa-css-prefix}-praying-hands:before { content: @fa-var-praying-hands; }
.@{fa-css-prefix}-prescription:before { content: @fa-var-prescription; }
.@{fa-css-prefix}-prescription-bottle:before { content: @fa-var-prescription-bottle; }
.@{fa-css-prefix}-prescription-bottle-alt:before { content: @fa-var-prescription-bottle-alt; }
.@{fa-css-prefix}-print:before { content: @fa-var-print; }
.@{fa-css-prefix}-procedures:before { content: @fa-var-procedures; }
.@{fa-css-prefix}-product-hunt:before { content: @fa-var-product-hunt; }
.@{fa-css-prefix}-project-diagram:before { content: @fa-var-project-diagram; }
.@{fa-css-prefix}-pump-medical:before { content: @fa-var-pump-medical; }
.@{fa-css-prefix}-pump-soap:before { content: @fa-var-pump-soap; }
.@{fa-css-prefix}-pushed:before { content: @fa-var-pushed; }
.@{fa-css-prefix}-puzzle-piece:before { content: @fa-var-puzzle-piece; }
.@{fa-css-prefix}-python:before { content: @fa-var-python; }
.@{fa-css-prefix}-qq:before { content: @fa-var-qq; }
.@{fa-css-prefix}-qrcode:before { content: @fa-var-qrcode; }
.@{fa-css-prefix}-question:before { content: @fa-var-question; }
.@{fa-css-prefix}-question-circle:before { content: @fa-var-question-circle; }
.@{fa-css-prefix}-quidditch:before { content: @fa-var-quidditch; }
.@{fa-css-prefix}-quinscape:before { content: @fa-var-quinscape; }
.@{fa-css-prefix}-quora:before { content: @fa-var-quora; }
.@{fa-css-prefix}-quote-left:before { content: @fa-var-quote-left; }
.@{fa-css-prefix}-quote-right:before { content: @fa-var-quote-right; }
.@{fa-css-prefix}-quran:before { content: @fa-var-quran; }
.@{fa-css-prefix}-r-project:before { content: @fa-var-r-project; }
.@{fa-css-prefix}-radiation:before { content: @fa-var-radiation; }
.@{fa-css-prefix}-radiation-alt:before { content: @fa-var-radiation-alt; }
.@{fa-css-prefix}-rainbow:before { content: @fa-var-rainbow; }
.@{fa-css-prefix}-random:before { content: @fa-var-random; }
.@{fa-css-prefix}-raspberry-pi:before { content: @fa-var-raspberry-pi; }
.@{fa-css-prefix}-ravelry:before { content: @fa-var-ravelry; }
.@{fa-css-prefix}-react:before { content: @fa-var-react; }
.@{fa-css-prefix}-reacteurope:before { content: @fa-var-reacteurope; }
.@{fa-css-prefix}-readme:before { content: @fa-var-readme; }
.@{fa-css-prefix}-rebel:before { content: @fa-var-rebel; }
.@{fa-css-prefix}-receipt:before { content: @fa-var-receipt; }
.@{fa-css-prefix}-record-vinyl:before { content: @fa-var-record-vinyl; }
.@{fa-css-prefix}-recycle:before { content: @fa-var-recycle; }
.@{fa-css-prefix}-red-river:before { content: @fa-var-red-river; }
.@{fa-css-prefix}-reddit:before { content: @fa-var-reddit; }
.@{fa-css-prefix}-reddit-alien:before { content: @fa-var-reddit-alien; }
.@{fa-css-prefix}-reddit-square:before { content: @fa-var-reddit-square; }
.@{fa-css-prefix}-redhat:before { content: @fa-var-redhat; }
.@{fa-css-prefix}-redo:before { content: @fa-var-redo; }
.@{fa-css-prefix}-redo-alt:before { content: @fa-var-redo-alt; }
.@{fa-css-prefix}-registered:before { content: @fa-var-registered; }
.@{fa-css-prefix}-remove-format:before { content: @fa-var-remove-format; }
.@{fa-css-prefix}-renren:before { content: @fa-var-renren; }
.@{fa-css-prefix}-reply:before { content: @fa-var-reply; }
.@{fa-css-prefix}-reply-all:before { content: @fa-var-reply-all; }
.@{fa-css-prefix}-replyd:before { content: @fa-var-replyd; }
.@{fa-css-prefix}-republican:before { content: @fa-var-republican; }
.@{fa-css-prefix}-researchgate:before { content: @fa-var-researchgate; }
.@{fa-css-prefix}-resolving:before { content: @fa-var-resolving; }
.@{fa-css-prefix}-restroom:before { content: @fa-var-restroom; }
.@{fa-css-prefix}-retweet:before { content: @fa-var-retweet; }
.@{fa-css-prefix}-rev:before { content: @fa-var-rev; }
.@{fa-css-prefix}-ribbon:before { content: @fa-var-ribbon; }
.@{fa-css-prefix}-ring:before { content: @fa-var-ring; }
.@{fa-css-prefix}-road:before { content: @fa-var-road; }
.@{fa-css-prefix}-robot:before { content: @fa-var-robot; }
.@{fa-css-prefix}-rocket:before { content: @fa-var-rocket; }
.@{fa-css-prefix}-rocketchat:before { content: @fa-var-rocketchat; }
.@{fa-css-prefix}-rockrms:before { content: @fa-var-rockrms; }
.@{fa-css-prefix}-route:before { content: @fa-var-route; }
.@{fa-css-prefix}-rss:before { content: @fa-var-rss; }
.@{fa-css-prefix}-rss-square:before { content: @fa-var-rss-square; }
.@{fa-css-prefix}-ruble-sign:before { content: @fa-var-ruble-sign; }
.@{fa-css-prefix}-ruler:before { content: @fa-var-ruler; }
.@{fa-css-prefix}-ruler-combined:before { content: @fa-var-ruler-combined; }
.@{fa-css-prefix}-ruler-horizontal:before { content: @fa-var-ruler-horizontal; }
.@{fa-css-prefix}-ruler-vertical:before { content: @fa-var-ruler-vertical; }
.@{fa-css-prefix}-running:before { content: @fa-var-running; }
.@{fa-css-prefix}-rupee-sign:before { content: @fa-var-rupee-sign; }
.@{fa-css-prefix}-sad-cry:before { content: @fa-var-sad-cry; }
.@{fa-css-prefix}-sad-tear:before { content: @fa-var-sad-tear; }
.@{fa-css-prefix}-safari:before { content: @fa-var-safari; }
.@{fa-css-prefix}-salesforce:before { content: @fa-var-salesforce; }
.@{fa-css-prefix}-sass:before { content: @fa-var-sass; }
.@{fa-css-prefix}-satellite:before { content: @fa-var-satellite; }
.@{fa-css-prefix}-satellite-dish:before { content: @fa-var-satellite-dish; }
.@{fa-css-prefix}-save:before { content: @fa-var-save; }
.@{fa-css-prefix}-schlix:before { content: @fa-var-schlix; }
.@{fa-css-prefix}-school:before { content: @fa-var-school; }
.@{fa-css-prefix}-screwdriver:before { content: @fa-var-screwdriver; }
.@{fa-css-prefix}-scribd:before { content: @fa-var-scribd; }
.@{fa-css-prefix}-scroll:before { content: @fa-var-scroll; }
.@{fa-css-prefix}-sd-card:before { content: @fa-var-sd-card; }
.@{fa-css-prefix}-search:before { content: @fa-var-search; }
.@{fa-css-prefix}-search-dollar:before { content: @fa-var-search-dollar; }
.@{fa-css-prefix}-search-location:before { content: @fa-var-search-location; }
.@{fa-css-prefix}-search-minus:before { content: @fa-var-search-minus; }
.@{fa-css-prefix}-search-plus:before { content: @fa-var-search-plus; }
.@{fa-css-prefix}-searchengin:before { content: @fa-var-searchengin; }
.@{fa-css-prefix}-seedling:before { content: @fa-var-seedling; }
.@{fa-css-prefix}-sellcast:before { content: @fa-var-sellcast; }
.@{fa-css-prefix}-sellsy:before { content: @fa-var-sellsy; }
.@{fa-css-prefix}-server:before { content: @fa-var-server; }
.@{fa-css-prefix}-servicestack:before { content: @fa-var-servicestack; }
.@{fa-css-prefix}-shapes:before { content: @fa-var-shapes; }
.@{fa-css-prefix}-share:before { content: @fa-var-share; }
.@{fa-css-prefix}-share-alt:before { content: @fa-var-share-alt; }
.@{fa-css-prefix}-share-alt-square:before { content: @fa-var-share-alt-square; }
.@{fa-css-prefix}-share-square:before { content: @fa-var-share-square; }
.@{fa-css-prefix}-shekel-sign:before { content: @fa-var-shekel-sign; }
.@{fa-css-prefix}-shield-alt:before { content: @fa-var-shield-alt; }
.@{fa-css-prefix}-shield-virus:before { content: @fa-var-shield-virus; }
.@{fa-css-prefix}-ship:before { content: @fa-var-ship; }
.@{fa-css-prefix}-shipping-fast:before { content: @fa-var-shipping-fast; }
.@{fa-css-prefix}-shirtsinbulk:before { content: @fa-var-shirtsinbulk; }
.@{fa-css-prefix}-shoe-prints:before { content: @fa-var-shoe-prints; }
.@{fa-css-prefix}-shopify:before { content: @fa-var-shopify; }
.@{fa-css-prefix}-shopping-bag:before { content: @fa-var-shopping-bag; }
.@{fa-css-prefix}-shopping-basket:before { content: @fa-var-shopping-basket; }
.@{fa-css-prefix}-shopping-cart:before { content: @fa-var-shopping-cart; }
.@{fa-css-prefix}-shopware:before { content: @fa-var-shopware; }
.@{fa-css-prefix}-shower:before { content: @fa-var-shower; }
.@{fa-css-prefix}-shuttle-van:before { content: @fa-var-shuttle-van; }
.@{fa-css-prefix}-sign:before { content: @fa-var-sign; }
.@{fa-css-prefix}-sign-in-alt:before { content: @fa-var-sign-in-alt; }
.@{fa-css-prefix}-sign-language:before { content: @fa-var-sign-language; }
.@{fa-css-prefix}-sign-out-alt:before { content: @fa-var-sign-out-alt; }
.@{fa-css-prefix}-signal:before { content: @fa-var-signal; }
.@{fa-css-prefix}-signature:before { content: @fa-var-signature; }
.@{fa-css-prefix}-sim-card:before { content: @fa-var-sim-card; }
.@{fa-css-prefix}-simplybuilt:before { content: @fa-var-simplybuilt; }
.@{fa-css-prefix}-sistrix:before { content: @fa-var-sistrix; }
.@{fa-css-prefix}-sitemap:before { content: @fa-var-sitemap; }
.@{fa-css-prefix}-sith:before { content: @fa-var-sith; }
.@{fa-css-prefix}-skating:before { content: @fa-var-skating; }
.@{fa-css-prefix}-sketch:before { content: @fa-var-sketch; }
.@{fa-css-prefix}-skiing:before { content: @fa-var-skiing; }
.@{fa-css-prefix}-skiing-nordic:before { content: @fa-var-skiing-nordic; }
.@{fa-css-prefix}-skull:before { content: @fa-var-skull; }
.@{fa-css-prefix}-skull-crossbones:before { content: @fa-var-skull-crossbones; }
.@{fa-css-prefix}-skyatlas:before { content: @fa-var-skyatlas; }
.@{fa-css-prefix}-skype:before { content: @fa-var-skype; }
.@{fa-css-prefix}-slack:before { content: @fa-var-slack; }
.@{fa-css-prefix}-slack-hash:before { content: @fa-var-slack-hash; }
.@{fa-css-prefix}-slash:before { content: @fa-var-slash; }
.@{fa-css-prefix}-sleigh:before { content: @fa-var-sleigh; }
.@{fa-css-prefix}-sliders-h:before { content: @fa-var-sliders-h; }
.@{fa-css-prefix}-slideshare:before { content: @fa-var-slideshare; }
.@{fa-css-prefix}-smile:before { content: @fa-var-smile; }
.@{fa-css-prefix}-smile-beam:before { content: @fa-var-smile-beam; }
.@{fa-css-prefix}-smile-wink:before { content: @fa-var-smile-wink; }
.@{fa-css-prefix}-smog:before { content: @fa-var-smog; }
.@{fa-css-prefix}-smoking:before { content: @fa-var-smoking; }
.@{fa-css-prefix}-smoking-ban:before { content: @fa-var-smoking-ban; }
.@{fa-css-prefix}-sms:before { content: @fa-var-sms; }
.@{fa-css-prefix}-snapchat:before { content: @fa-var-snapchat; }
.@{fa-css-prefix}-snapchat-ghost:before { content: @fa-var-snapchat-ghost; }
.@{fa-css-prefix}-snapchat-square:before { content: @fa-var-snapchat-square; }
.@{fa-css-prefix}-snowboarding:before { content: @fa-var-snowboarding; }
.@{fa-css-prefix}-snowflake:before { content: @fa-var-snowflake; }
.@{fa-css-prefix}-snowman:before { content: @fa-var-snowman; }
.@{fa-css-prefix}-snowplow:before { content: @fa-var-snowplow; }
.@{fa-css-prefix}-soap:before { content: @fa-var-soap; }
.@{fa-css-prefix}-socks:before { content: @fa-var-socks; }
.@{fa-css-prefix}-solar-panel:before { content: @fa-var-solar-panel; }
.@{fa-css-prefix}-sort:before { content: @fa-var-sort; }
.@{fa-css-prefix}-sort-alpha-down:before { content: @fa-var-sort-alpha-down; }
.@{fa-css-prefix}-sort-alpha-down-alt:before { content: @fa-var-sort-alpha-down-alt; }
.@{fa-css-prefix}-sort-alpha-up:before { content: @fa-var-sort-alpha-up; }
.@{fa-css-prefix}-sort-alpha-up-alt:before { content: @fa-var-sort-alpha-up-alt; }
.@{fa-css-prefix}-sort-amount-down:before { content: @fa-var-sort-amount-down; }
.@{fa-css-prefix}-sort-amount-down-alt:before { content: @fa-var-sort-amount-down-alt; }
.@{fa-css-prefix}-sort-amount-up:before { content: @fa-var-sort-amount-up; }
.@{fa-css-prefix}-sort-amount-up-alt:before { content: @fa-var-sort-amount-up-alt; }
.@{fa-css-prefix}-sort-down:before { content: @fa-var-sort-down; }
.@{fa-css-prefix}-sort-numeric-down:before { content: @fa-var-sort-numeric-down; }
.@{fa-css-prefix}-sort-numeric-down-alt:before { content: @fa-var-sort-numeric-down-alt; }
.@{fa-css-prefix}-sort-numeric-up:before { content: @fa-var-sort-numeric-up; }
.@{fa-css-prefix}-sort-numeric-up-alt:before { content: @fa-var-sort-numeric-up-alt; }
.@{fa-css-prefix}-sort-up:before { content: @fa-var-sort-up; }
.@{fa-css-prefix}-soundcloud:before { content: @fa-var-soundcloud; }
.@{fa-css-prefix}-sourcetree:before { content: @fa-var-sourcetree; }
.@{fa-css-prefix}-spa:before { content: @fa-var-spa; }
.@{fa-css-prefix}-space-shuttle:before { content: @fa-var-space-shuttle; }
.@{fa-css-prefix}-speakap:before { content: @fa-var-speakap; }
.@{fa-css-prefix}-speaker-deck:before { content: @fa-var-speaker-deck; }
.@{fa-css-prefix}-spell-check:before { content: @fa-var-spell-check; }
.@{fa-css-prefix}-spider:before { content: @fa-var-spider; }
.@{fa-css-prefix}-spinner:before { content: @fa-var-spinner; }
.@{fa-css-prefix}-splotch:before { content: @fa-var-splotch; }
.@{fa-css-prefix}-spotify:before { content: @fa-var-spotify; }
.@{fa-css-prefix}-spray-can:before { content: @fa-var-spray-can; }
.@{fa-css-prefix}-square:before { content: @fa-var-square; }
.@{fa-css-prefix}-square-full:before { content: @fa-var-square-full; }
.@{fa-css-prefix}-square-root-alt:before { content: @fa-var-square-root-alt; }
.@{fa-css-prefix}-squarespace:before { content: @fa-var-squarespace; }
.@{fa-css-prefix}-stack-exchange:before { content: @fa-var-stack-exchange; }
.@{fa-css-prefix}-stack-overflow:before { content: @fa-var-stack-overflow; }
.@{fa-css-prefix}-stackpath:before { content: @fa-var-stackpath; }
.@{fa-css-prefix}-stamp:before { content: @fa-var-stamp; }
.@{fa-css-prefix}-star:before { content: @fa-var-star; }
.@{fa-css-prefix}-star-and-crescent:before { content: @fa-var-star-and-crescent; }
.@{fa-css-prefix}-star-half:before { content: @fa-var-star-half; }
.@{fa-css-prefix}-star-half-alt:before { content: @fa-var-star-half-alt; }
.@{fa-css-prefix}-star-of-david:before { content: @fa-var-star-of-david; }
.@{fa-css-prefix}-star-of-life:before { content: @fa-var-star-of-life; }
.@{fa-css-prefix}-staylinked:before { content: @fa-var-staylinked; }
.@{fa-css-prefix}-steam:before { content: @fa-var-steam; }
.@{fa-css-prefix}-steam-square:before { content: @fa-var-steam-square; }
.@{fa-css-prefix}-steam-symbol:before { content: @fa-var-steam-symbol; }
.@{fa-css-prefix}-step-backward:before { content: @fa-var-step-backward; }
.@{fa-css-prefix}-step-forward:before { content: @fa-var-step-forward; }
.@{fa-css-prefix}-stethoscope:before { content: @fa-var-stethoscope; }
.@{fa-css-prefix}-sticker-mule:before { content: @fa-var-sticker-mule; }
.@{fa-css-prefix}-sticky-note:before { content: @fa-var-sticky-note; }
.@{fa-css-prefix}-stop:before { content: @fa-var-stop; }
.@{fa-css-prefix}-stop-circle:before { content: @fa-var-stop-circle; }
.@{fa-css-prefix}-stopwatch:before { content: @fa-var-stopwatch; }
.@{fa-css-prefix}-stopwatch-20:before { content: @fa-var-stopwatch-20; }
.@{fa-css-prefix}-store:before { content: @fa-var-store; }
.@{fa-css-prefix}-store-alt:before { content: @fa-var-store-alt; }
.@{fa-css-prefix}-store-alt-slash:before { content: @fa-var-store-alt-slash; }
.@{fa-css-prefix}-store-slash:before { content: @fa-var-store-slash; }
.@{fa-css-prefix}-strava:before { content: @fa-var-strava; }
.@{fa-css-prefix}-stream:before { content: @fa-var-stream; }
.@{fa-css-prefix}-street-view:before { content: @fa-var-street-view; }
.@{fa-css-prefix}-strikethrough:before { content: @fa-var-strikethrough; }
.@{fa-css-prefix}-stripe:before { content: @fa-var-stripe; }
.@{fa-css-prefix}-stripe-s:before { content: @fa-var-stripe-s; }
.@{fa-css-prefix}-stroopwafel:before { content: @fa-var-stroopwafel; }
.@{fa-css-prefix}-studiovinari:before { content: @fa-var-studiovinari; }
.@{fa-css-prefix}-stumbleupon:before { content: @fa-var-stumbleupon; }
.@{fa-css-prefix}-stumbleupon-circle:before { content: @fa-var-stumbleupon-circle; }
.@{fa-css-prefix}-subscript:before { content: @fa-var-subscript; }
.@{fa-css-prefix}-subway:before { content: @fa-var-subway; }
.@{fa-css-prefix}-suitcase:before { content: @fa-var-suitcase; }
.@{fa-css-prefix}-suitcase-rolling:before { content: @fa-var-suitcase-rolling; }
.@{fa-css-prefix}-sun:before { content: @fa-var-sun; }
.@{fa-css-prefix}-superpowers:before { content: @fa-var-superpowers; }
.@{fa-css-prefix}-superscript:before { content: @fa-var-superscript; }
.@{fa-css-prefix}-supple:before { content: @fa-var-supple; }
.@{fa-css-prefix}-surprise:before { content: @fa-var-surprise; }
.@{fa-css-prefix}-suse:before { content: @fa-var-suse; }
.@{fa-css-prefix}-swatchbook:before { content: @fa-var-swatchbook; }
.@{fa-css-prefix}-swift:before { content: @fa-var-swift; }
.@{fa-css-prefix}-swimmer:before { content: @fa-var-swimmer; }
.@{fa-css-prefix}-swimming-pool:before { content: @fa-var-swimming-pool; }
.@{fa-css-prefix}-symfony:before { content: @fa-var-symfony; }
.@{fa-css-prefix}-synagogue:before { content: @fa-var-synagogue; }
.@{fa-css-prefix}-sync:before { content: @fa-var-sync; }
.@{fa-css-prefix}-sync-alt:before { content: @fa-var-sync-alt; }
.@{fa-css-prefix}-syringe:before { content: @fa-var-syringe; }
.@{fa-css-prefix}-table:before { content: @fa-var-table; }
.@{fa-css-prefix}-table-tennis:before { content: @fa-var-table-tennis; }
.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet; }
.@{fa-css-prefix}-tablet-alt:before { content: @fa-var-tablet-alt; }
.@{fa-css-prefix}-tablets:before { content: @fa-var-tablets; }
.@{fa-css-prefix}-tachometer-alt:before { content: @fa-var-tachometer-alt; }
.@{fa-css-prefix}-tag:before { content: @fa-var-tag; }
.@{fa-css-prefix}-tags:before { content: @fa-var-tags; }
.@{fa-css-prefix}-tape:before { content: @fa-var-tape; }
.@{fa-css-prefix}-tasks:before { content: @fa-var-tasks; }
.@{fa-css-prefix}-taxi:before { content: @fa-var-taxi; }
.@{fa-css-prefix}-teamspeak:before { content: @fa-var-teamspeak; }
.@{fa-css-prefix}-teeth:before { content: @fa-var-teeth; }
.@{fa-css-prefix}-teeth-open:before { content: @fa-var-teeth-open; }
.@{fa-css-prefix}-telegram:before { content: @fa-var-telegram; }
.@{fa-css-prefix}-telegram-plane:before { content: @fa-var-telegram-plane; }
.@{fa-css-prefix}-temperature-high:before { content: @fa-var-temperature-high; }
.@{fa-css-prefix}-temperature-low:before { content: @fa-var-temperature-low; }
.@{fa-css-prefix}-tencent-weibo:before { content: @fa-var-tencent-weibo; }
.@{fa-css-prefix}-tenge:before { content: @fa-var-tenge; }
.@{fa-css-prefix}-terminal:before { content: @fa-var-terminal; }
.@{fa-css-prefix}-text-height:before { content: @fa-var-text-height; }
.@{fa-css-prefix}-text-width:before { content: @fa-var-text-width; }
.@{fa-css-prefix}-th:before { content: @fa-var-th; }
.@{fa-css-prefix}-th-large:before { content: @fa-var-th-large; }
.@{fa-css-prefix}-th-list:before { content: @fa-var-th-list; }
.@{fa-css-prefix}-the-red-yeti:before { content: @fa-var-the-red-yeti; }
.@{fa-css-prefix}-theater-masks:before { content: @fa-var-theater-masks; }
.@{fa-css-prefix}-themeco:before { content: @fa-var-themeco; }
.@{fa-css-prefix}-themeisle:before { content: @fa-var-themeisle; }
.@{fa-css-prefix}-thermometer:before { content: @fa-var-thermometer; }
.@{fa-css-prefix}-thermometer-empty:before { content: @fa-var-thermometer-empty; }
.@{fa-css-prefix}-thermometer-full:before { content: @fa-var-thermometer-full; }
.@{fa-css-prefix}-thermometer-half:before { content: @fa-var-thermometer-half; }
.@{fa-css-prefix}-thermometer-quarter:before { content: @fa-var-thermometer-quarter; }
.@{fa-css-prefix}-thermometer-three-quarters:before { content: @fa-var-thermometer-three-quarters; }
.@{fa-css-prefix}-think-peaks:before { content: @fa-var-think-peaks; }
.@{fa-css-prefix}-thumbs-down:before { content: @fa-var-thumbs-down; }
.@{fa-css-prefix}-thumbs-up:before { content: @fa-var-thumbs-up; }
.@{fa-css-prefix}-thumbtack:before { content: @fa-var-thumbtack; }
.@{fa-css-prefix}-ticket-alt:before { content: @fa-var-ticket-alt; }
.@{fa-css-prefix}-times:before { content: @fa-var-times; }
.@{fa-css-prefix}-times-circle:before { content: @fa-var-times-circle; }
.@{fa-css-prefix}-tint:before { content: @fa-var-tint; }
.@{fa-css-prefix}-tint-slash:before { content: @fa-var-tint-slash; }
.@{fa-css-prefix}-tired:before { content: @fa-var-tired; }
.@{fa-css-prefix}-toggle-off:before { content: @fa-var-toggle-off; }
.@{fa-css-prefix}-toggle-on:before { content: @fa-var-toggle-on; }
.@{fa-css-prefix}-toilet:before { content: @fa-var-toilet; }
.@{fa-css-prefix}-toilet-paper:before { content: @fa-var-toilet-paper; }
.@{fa-css-prefix}-toilet-paper-slash:before { content: @fa-var-toilet-paper-slash; }
.@{fa-css-prefix}-toolbox:before { content: @fa-var-toolbox; }
.@{fa-css-prefix}-tools:before { content: @fa-var-tools; }
.@{fa-css-prefix}-tooth:before { content: @fa-var-tooth; }
.@{fa-css-prefix}-torah:before { content: @fa-var-torah; }
.@{fa-css-prefix}-torii-gate:before { content: @fa-var-torii-gate; }
.@{fa-css-prefix}-tractor:before { content: @fa-var-tractor; }
.@{fa-css-prefix}-trade-federation:before { content: @fa-var-trade-federation; }
.@{fa-css-prefix}-trademark:before { content: @fa-var-trademark; }
.@{fa-css-prefix}-traffic-light:before { content: @fa-var-traffic-light; }
.@{fa-css-prefix}-trailer:before { content: @fa-var-trailer; }
.@{fa-css-prefix}-train:before { content: @fa-var-train; }
.@{fa-css-prefix}-tram:before { content: @fa-var-tram; }
.@{fa-css-prefix}-transgender:before { content: @fa-var-transgender; }
.@{fa-css-prefix}-transgender-alt:before { content: @fa-var-transgender-alt; }
.@{fa-css-prefix}-trash:before { content: @fa-var-trash; }
.@{fa-css-prefix}-trash-alt:before { content: @fa-var-trash-alt; }
.@{fa-css-prefix}-trash-restore:before { content: @fa-var-trash-restore; }
.@{fa-css-prefix}-trash-restore-alt:before { content: @fa-var-trash-restore-alt; }
.@{fa-css-prefix}-tree:before { content: @fa-var-tree; }
.@{fa-css-prefix}-trello:before { content: @fa-var-trello; }
.@{fa-css-prefix}-tripadvisor:before { content: @fa-var-tripadvisor; }
.@{fa-css-prefix}-trophy:before { content: @fa-var-trophy; }
.@{fa-css-prefix}-truck:before { content: @fa-var-truck; }
.@{fa-css-prefix}-truck-loading:before { content: @fa-var-truck-loading; }
.@{fa-css-prefix}-truck-monster:before { content: @fa-var-truck-monster; }
.@{fa-css-prefix}-truck-moving:before { content: @fa-var-truck-moving; }
.@{fa-css-prefix}-truck-pickup:before { content: @fa-var-truck-pickup; }
.@{fa-css-prefix}-tshirt:before { content: @fa-var-tshirt; }
.@{fa-css-prefix}-tty:before { content: @fa-var-tty; }
.@{fa-css-prefix}-tumblr:before { content: @fa-var-tumblr; }
.@{fa-css-prefix}-tumblr-square:before { content: @fa-var-tumblr-square; }
.@{fa-css-prefix}-tv:before { content: @fa-var-tv; }
.@{fa-css-prefix}-twitch:before { content: @fa-var-twitch; }
.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; }
.@{fa-css-prefix}-twitter-square:before { content: @fa-var-twitter-square; }
.@{fa-css-prefix}-typo3:before { content: @fa-var-typo3; }
.@{fa-css-prefix}-uber:before { content: @fa-var-uber; }
.@{fa-css-prefix}-ubuntu:before { content: @fa-var-ubuntu; }
.@{fa-css-prefix}-uikit:before { content: @fa-var-uikit; }
.@{fa-css-prefix}-umbraco:before { content: @fa-var-umbraco; }
.@{fa-css-prefix}-umbrella:before { content: @fa-var-umbrella; }
.@{fa-css-prefix}-umbrella-beach:before { content: @fa-var-umbrella-beach; }
.@{fa-css-prefix}-underline:before { content: @fa-var-underline; }
.@{fa-css-prefix}-undo:before { content: @fa-var-undo; }
.@{fa-css-prefix}-undo-alt:before { content: @fa-var-undo-alt; }
.@{fa-css-prefix}-uniregistry:before { content: @fa-var-uniregistry; }
.@{fa-css-prefix}-unity:before { content: @fa-var-unity; }
.@{fa-css-prefix}-universal-access:before { content: @fa-var-universal-access; }
.@{fa-css-prefix}-university:before { content: @fa-var-university; }
.@{fa-css-prefix}-unlink:before { content: @fa-var-unlink; }
.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; }
.@{fa-css-prefix}-unlock-alt:before { content: @fa-var-unlock-alt; }
.@{fa-css-prefix}-untappd:before { content: @fa-var-untappd; }
.@{fa-css-prefix}-upload:before { content: @fa-var-upload; }
.@{fa-css-prefix}-ups:before { content: @fa-var-ups; }
.@{fa-css-prefix}-usb:before { content: @fa-var-usb; }
.@{fa-css-prefix}-user:before { content: @fa-var-user; }
.@{fa-css-prefix}-user-alt:before { content: @fa-var-user-alt; }
.@{fa-css-prefix}-user-alt-slash:before { content: @fa-var-user-alt-slash; }
.@{fa-css-prefix}-user-astronaut:before { content: @fa-var-user-astronaut; }
.@{fa-css-prefix}-user-check:before { content: @fa-var-user-check; }
.@{fa-css-prefix}-user-circle:before { content: @fa-var-user-circle; }
.@{fa-css-prefix}-user-clock:before { content: @fa-var-user-clock; }
.@{fa-css-prefix}-user-cog:before { content: @fa-var-user-cog; }
.@{fa-css-prefix}-user-edit:before { content: @fa-var-user-edit; }
.@{fa-css-prefix}-user-friends:before { content: @fa-var-user-friends; }
.@{fa-css-prefix}-user-graduate:before { content: @fa-var-user-graduate; }
.@{fa-css-prefix}-user-injured:before { content: @fa-var-user-injured; }
.@{fa-css-prefix}-user-lock:before { content: @fa-var-user-lock; }
.@{fa-css-prefix}-user-md:before { content: @fa-var-user-md; }
.@{fa-css-prefix}-user-minus:before { content: @fa-var-user-minus; }
.@{fa-css-prefix}-user-ninja:before { content: @fa-var-user-ninja; }
.@{fa-css-prefix}-user-nurse:before { content: @fa-var-user-nurse; }
.@{fa-css-prefix}-user-plus:before { content: @fa-var-user-plus; }
.@{fa-css-prefix}-user-secret:before { content: @fa-var-user-secret; }
.@{fa-css-prefix}-user-shield:before { content: @fa-var-user-shield; }
.@{fa-css-prefix}-user-slash:before { content: @fa-var-user-slash; }
.@{fa-css-prefix}-user-tag:before { content: @fa-var-user-tag; }
.@{fa-css-prefix}-user-tie:before { content: @fa-var-user-tie; }
.@{fa-css-prefix}-user-times:before { content: @fa-var-user-times; }
.@{fa-css-prefix}-users:before { content: @fa-var-users; }
.@{fa-css-prefix}-users-cog:before { content: @fa-var-users-cog; }
.@{fa-css-prefix}-usps:before { content: @fa-var-usps; }
.@{fa-css-prefix}-ussunnah:before { content: @fa-var-ussunnah; }
.@{fa-css-prefix}-utensil-spoon:before { content: @fa-var-utensil-spoon; }
.@{fa-css-prefix}-utensils:before { content: @fa-var-utensils; }
.@{fa-css-prefix}-vaadin:before { content: @fa-var-vaadin; }
.@{fa-css-prefix}-vector-square:before { content: @fa-var-vector-square; }
.@{fa-css-prefix}-venus:before { content: @fa-var-venus; }
.@{fa-css-prefix}-venus-double:before { content: @fa-var-venus-double; }
.@{fa-css-prefix}-venus-mars:before { content: @fa-var-venus-mars; }
.@{fa-css-prefix}-viacoin:before { content: @fa-var-viacoin; }
.@{fa-css-prefix}-viadeo:before { content: @fa-var-viadeo; }
.@{fa-css-prefix}-viadeo-square:before { content: @fa-var-viadeo-square; }
.@{fa-css-prefix}-vial:before { content: @fa-var-vial; }
.@{fa-css-prefix}-vials:before { content: @fa-var-vials; }
.@{fa-css-prefix}-viber:before { content: @fa-var-viber; }
.@{fa-css-prefix}-video:before { content: @fa-var-video; }
.@{fa-css-prefix}-video-slash:before { content: @fa-var-video-slash; }
.@{fa-css-prefix}-vihara:before { content: @fa-var-vihara; }
.@{fa-css-prefix}-vimeo:before { content: @fa-var-vimeo; }
.@{fa-css-prefix}-vimeo-square:before { content: @fa-var-vimeo-square; }
.@{fa-css-prefix}-vimeo-v:before { content: @fa-var-vimeo-v; }
.@{fa-css-prefix}-vine:before { content: @fa-var-vine; }
.@{fa-css-prefix}-virus:before { content: @fa-var-virus; }
.@{fa-css-prefix}-virus-slash:before { content: @fa-var-virus-slash; }
.@{fa-css-prefix}-viruses:before { content: @fa-var-viruses; }
.@{fa-css-prefix}-vk:before { content: @fa-var-vk; }
.@{fa-css-prefix}-vnv:before { content: @fa-var-vnv; }
.@{fa-css-prefix}-voicemail:before { content: @fa-var-voicemail; }
.@{fa-css-prefix}-volleyball-ball:before { content: @fa-var-volleyball-ball; }
.@{fa-css-prefix}-volume-down:before { content: @fa-var-volume-down; }
.@{fa-css-prefix}-volume-mute:before { content: @fa-var-volume-mute; }
.@{fa-css-prefix}-volume-off:before { content: @fa-var-volume-off; }
.@{fa-css-prefix}-volume-up:before { content: @fa-var-volume-up; }
.@{fa-css-prefix}-vote-yea:before { content: @fa-var-vote-yea; }
.@{fa-css-prefix}-vr-cardboard:before { content: @fa-var-vr-cardboard; }
.@{fa-css-prefix}-vuejs:before { content: @fa-var-vuejs; }
.@{fa-css-prefix}-walking:before { content: @fa-var-walking; }
.@{fa-css-prefix}-wallet:before { content: @fa-var-wallet; }
.@{fa-css-prefix}-warehouse:before { content: @fa-var-warehouse; }
.@{fa-css-prefix}-water:before { content: @fa-var-water; }
.@{fa-css-prefix}-wave-square:before { content: @fa-var-wave-square; }
.@{fa-css-prefix}-waze:before { content: @fa-var-waze; }
.@{fa-css-prefix}-weebly:before { content: @fa-var-weebly; }
.@{fa-css-prefix}-weibo:before { content: @fa-var-weibo; }
.@{fa-css-prefix}-weight:before { content: @fa-var-weight; }
.@{fa-css-prefix}-weight-hanging:before { content: @fa-var-weight-hanging; }
.@{fa-css-prefix}-weixin:before { content: @fa-var-weixin; }
.@{fa-css-prefix}-whatsapp:before { content: @fa-var-whatsapp; }
.@{fa-css-prefix}-whatsapp-square:before { content: @fa-var-whatsapp-square; }
.@{fa-css-prefix}-wheelchair:before { content: @fa-var-wheelchair; }
.@{fa-css-prefix}-whmcs:before { content: @fa-var-whmcs; }
.@{fa-css-prefix}-wifi:before { content: @fa-var-wifi; }
.@{fa-css-prefix}-wikipedia-w:before { content: @fa-var-wikipedia-w; }
.@{fa-css-prefix}-wind:before { content: @fa-var-wind; }
.@{fa-css-prefix}-window-close:before { content: @fa-var-window-close; }
.@{fa-css-prefix}-window-maximize:before { content: @fa-var-window-maximize; }
.@{fa-css-prefix}-window-minimize:before { content: @fa-var-window-minimize; }
.@{fa-css-prefix}-window-restore:before { content: @fa-var-window-restore; }
.@{fa-css-prefix}-windows:before { content: @fa-var-windows; }
.@{fa-css-prefix}-wine-bottle:before { content: @fa-var-wine-bottle; }
.@{fa-css-prefix}-wine-glass:before { content: @fa-var-wine-glass; }
.@{fa-css-prefix}-wine-glass-alt:before { content: @fa-var-wine-glass-alt; }
.@{fa-css-prefix}-wix:before { content: @fa-var-wix; }
.@{fa-css-prefix}-wizards-of-the-coast:before { content: @fa-var-wizards-of-the-coast; }
.@{fa-css-prefix}-wolf-pack-battalion:before { content: @fa-var-wolf-pack-battalion; }
.@{fa-css-prefix}-won-sign:before { content: @fa-var-won-sign; }
.@{fa-css-prefix}-wordpress:before { content: @fa-var-wordpress; }
.@{fa-css-prefix}-wordpress-simple:before { content: @fa-var-wordpress-simple; }
.@{fa-css-prefix}-wpbeginner:before { content: @fa-var-wpbeginner; }
.@{fa-css-prefix}-wpexplorer:before { content: @fa-var-wpexplorer; }
.@{fa-css-prefix}-wpforms:before { content: @fa-var-wpforms; }
.@{fa-css-prefix}-wpressr:before { content: @fa-var-wpressr; }
.@{fa-css-prefix}-wrench:before { content: @fa-var-wrench; }
.@{fa-css-prefix}-x-ray:before { content: @fa-var-x-ray; }
.@{fa-css-prefix}-xbox:before { content: @fa-var-xbox; }
.@{fa-css-prefix}-xing:before { content: @fa-var-xing; }
.@{fa-css-prefix}-xing-square:before { content: @fa-var-xing-square; }
.@{fa-css-prefix}-y-combinator:before { content: @fa-var-y-combinator; }
.@{fa-css-prefix}-yahoo:before { content: @fa-var-yahoo; }
.@{fa-css-prefix}-yammer:before { content: @fa-var-yammer; }
.@{fa-css-prefix}-yandex:before { content: @fa-var-yandex; }
.@{fa-css-prefix}-yandex-international:before { content: @fa-var-yandex-international; }
.@{fa-css-prefix}-yarn:before { content: @fa-var-yarn; }
.@{fa-css-prefix}-yelp:before { content: @fa-var-yelp; }
.@{fa-css-prefix}-yen-sign:before { content: @fa-var-yen-sign; }
.@{fa-css-prefix}-yin-yang:before { content: @fa-var-yin-yang; }
.@{fa-css-prefix}-yoast:before { content: @fa-var-yoast; }
.@{fa-css-prefix}-youtube:before { content: @fa-var-youtube; }
.@{fa-css-prefix}-youtube-square:before { content: @fa-var-youtube-square; }
.@{fa-css-prefix}-zhihu:before { content: @fa-var-zhihu; }
// Icon Sizes
// -------------------------
.larger(@factor) when (@factor > 0) {
.larger((@factor - 1));
.@{fa-css-prefix}-@{factor}x {
font-size: (@factor * 1em);
}
}
/* makes the font 33% larger relative to the icon container */
.@{fa-css-prefix}-lg {
font-size: (4em / 3);
line-height: (3em / 4);
vertical-align: -.0667em;
}
.@{fa-css-prefix}-xs {
font-size: .75em;
}
.@{fa-css-prefix}-sm {
font-size: .875em;
}
.larger(10);
// List Icons
// -------------------------
.@{fa-css-prefix}-ul {
list-style-type: none;
margin-left: (@fa-li-width * 5/4);
padding-left: 0;
> li { position: relative; }
}
.@{fa-css-prefix}-li {
left: -@fa-li-width;
position: absolute;
text-align: center;
width: @fa-li-width;
line-height: inherit;
}
// Mixins
// --------------------------
.fa-icon() {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
font-weight: normal;
line-height: 1;
}
.fa-icon-rotate(@degrees, @rotation) {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})";
transform: rotate(@degrees);
}
.fa-icon-flip(@horiz, @vert, @rotation) {
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)";
transform: scale(@horiz, @vert);
}
// Only display content to screen readers. A la Bootstrap 4.
//
// See: http://a11yproject.com/posts/how-to-hide-content/
.sr-only() {
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
// Use in conjunction with .sr-only to only display content when it's focused.
//
// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
//
// Credit: HTML5 Boilerplate
.sr-only-focusable() {
&:active,
&:focus {
clip: auto;
height: auto;
margin: 0;
overflow: visible;
position: static;
width: auto;
}
}
// Rotated & Flipped Icons
// -------------------------
.@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); }
.@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); }
.@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); }
.@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); }
.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); }
.@{fa-css-prefix}-flip-both, .@{fa-css-prefix}-flip-horizontal.@{fa-css-prefix}-flip-vertical { .fa-icon-flip(-1, -1, 2); }
// Hook for IE8-9
// -------------------------
:root {
.@{fa-css-prefix}-rotate-90,
.@{fa-css-prefix}-rotate-180,
.@{fa-css-prefix}-rotate-270,
.@{fa-css-prefix}-flip-horizontal,
.@{fa-css-prefix}-flip-vertical,
.@{fa-css-prefix}-flip-both {
filter: none;
}
}
// Screen Readers
// -------------------------
.sr-only { .sr-only(); }
.sr-only-focusable { .sr-only-focusable(); }
.@{fa-css-prefix}.@{fa-css-prefix}-glass:before { content: @fa-var-glass-martini; }
.@{fa-css-prefix}.@{fa-css-prefix}-meetup {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-star-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-star-o:before { content: @fa-var-star; }
.@{fa-css-prefix}.@{fa-css-prefix}-remove:before { content: @fa-var-times; }
.@{fa-css-prefix}.@{fa-css-prefix}-close:before { content: @fa-var-times; }
.@{fa-css-prefix}.@{fa-css-prefix}-gear:before { content: @fa-var-cog; }
.@{fa-css-prefix}.@{fa-css-prefix}-trash-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-trash-o:before { content: @fa-var-trash-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-o:before { content: @fa-var-file; }
.@{fa-css-prefix}.@{fa-css-prefix}-clock-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-clock-o:before { content: @fa-var-clock; }
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-down {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-down:before { content: @fa-var-arrow-alt-circle-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-up {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-up:before { content: @fa-var-arrow-alt-circle-up; }
.@{fa-css-prefix}.@{fa-css-prefix}-play-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-play-circle-o:before { content: @fa-var-play-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-repeat:before { content: @fa-var-redo; }
.@{fa-css-prefix}.@{fa-css-prefix}-rotate-right:before { content: @fa-var-redo; }
.@{fa-css-prefix}.@{fa-css-prefix}-refresh:before { content: @fa-var-sync; }
.@{fa-css-prefix}.@{fa-css-prefix}-list-alt {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-dedent:before { content: @fa-var-outdent; }
.@{fa-css-prefix}.@{fa-css-prefix}-video-camera:before { content: @fa-var-video; }
.@{fa-css-prefix}.@{fa-css-prefix}-picture-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-picture-o:before { content: @fa-var-image; }
.@{fa-css-prefix}.@{fa-css-prefix}-photo {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-photo:before { content: @fa-var-image; }
.@{fa-css-prefix}.@{fa-css-prefix}-image {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-image:before { content: @fa-var-image; }
.@{fa-css-prefix}.@{fa-css-prefix}-pencil:before { content: @fa-var-pencil-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-map-marker:before { content: @fa-var-map-marker-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-pencil-square-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pencil-square-o:before { content: @fa-var-edit; }
.@{fa-css-prefix}.@{fa-css-prefix}-share-square-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-share-square-o:before { content: @fa-var-share-square; }
.@{fa-css-prefix}.@{fa-css-prefix}-check-square-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-check-square-o:before { content: @fa-var-check-square; }
.@{fa-css-prefix}.@{fa-css-prefix}-arrows:before { content: @fa-var-arrows-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-times-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-times-circle-o:before { content: @fa-var-times-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-check-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-check-circle-o:before { content: @fa-var-check-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-mail-forward:before { content: @fa-var-share; }
.@{fa-css-prefix}.@{fa-css-prefix}-expand:before { content: @fa-var-expand-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-compress:before { content: @fa-var-compress-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-eye {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-eye-slash {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-warning:before { content: @fa-var-exclamation-triangle; }
.@{fa-css-prefix}.@{fa-css-prefix}-calendar:before { content: @fa-var-calendar-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-arrows-v:before { content: @fa-var-arrows-alt-v; }
.@{fa-css-prefix}.@{fa-css-prefix}-arrows-h:before { content: @fa-var-arrows-alt-h; }
.@{fa-css-prefix}.@{fa-css-prefix}-bar-chart {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bar-chart:before { content: @fa-var-chart-bar; }
.@{fa-css-prefix}.@{fa-css-prefix}-bar-chart-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bar-chart-o:before { content: @fa-var-chart-bar; }
.@{fa-css-prefix}.@{fa-css-prefix}-twitter-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-facebook-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-gears:before { content: @fa-var-cogs; }
.@{fa-css-prefix}.@{fa-css-prefix}-thumbs-o-up {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-thumbs-o-up:before { content: @fa-var-thumbs-up; }
.@{fa-css-prefix}.@{fa-css-prefix}-thumbs-o-down {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-thumbs-o-down:before { content: @fa-var-thumbs-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-heart-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-heart-o:before { content: @fa-var-heart; }
.@{fa-css-prefix}.@{fa-css-prefix}-sign-out:before { content: @fa-var-sign-out-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-linkedin-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-linkedin-square:before { content: @fa-var-linkedin; }
.@{fa-css-prefix}.@{fa-css-prefix}-thumb-tack:before { content: @fa-var-thumbtack; }
.@{fa-css-prefix}.@{fa-css-prefix}-external-link:before { content: @fa-var-external-link-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-sign-in:before { content: @fa-var-sign-in-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-github-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-lemon-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-lemon-o:before { content: @fa-var-lemon; }
.@{fa-css-prefix}.@{fa-css-prefix}-square-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-square-o:before { content: @fa-var-square; }
.@{fa-css-prefix}.@{fa-css-prefix}-bookmark-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark; }
.@{fa-css-prefix}.@{fa-css-prefix}-twitter {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-facebook {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook-f; }
.@{fa-css-prefix}.@{fa-css-prefix}-facebook-f {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-facebook-f:before { content: @fa-var-facebook-f; }
.@{fa-css-prefix}.@{fa-css-prefix}-github {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-credit-card {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-feed:before { content: @fa-var-rss; }
.@{fa-css-prefix}.@{fa-css-prefix}-hdd-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-right {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-right:before { content: @fa-var-hand-point-right; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-left {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-left:before { content: @fa-var-hand-point-left; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-up {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-up:before { content: @fa-var-hand-point-up; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-down {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-o-down:before { content: @fa-var-hand-point-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-arrows-alt:before { content: @fa-var-expand-arrows-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-group:before { content: @fa-var-users; }
.@{fa-css-prefix}.@{fa-css-prefix}-chain:before { content: @fa-var-link; }
.@{fa-css-prefix}.@{fa-css-prefix}-scissors:before { content: @fa-var-cut; }
.@{fa-css-prefix}.@{fa-css-prefix}-files-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-files-o:before { content: @fa-var-copy; }
.@{fa-css-prefix}.@{fa-css-prefix}-floppy-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-floppy-o:before { content: @fa-var-save; }
.@{fa-css-prefix}.@{fa-css-prefix}-navicon:before { content: @fa-var-bars; }
.@{fa-css-prefix}.@{fa-css-prefix}-reorder:before { content: @fa-var-bars; }
.@{fa-css-prefix}.@{fa-css-prefix}-pinterest {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pinterest-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google-plus-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google-plus {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google-plus:before { content: @fa-var-google-plus-g; }
.@{fa-css-prefix}.@{fa-css-prefix}-money {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-money:before { content: @fa-var-money-bill-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-unsorted:before { content: @fa-var-sort; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-desc:before { content: @fa-var-sort-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-asc:before { content: @fa-var-sort-up; }
.@{fa-css-prefix}.@{fa-css-prefix}-linkedin {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-linkedin:before { content: @fa-var-linkedin-in; }
.@{fa-css-prefix}.@{fa-css-prefix}-rotate-left:before { content: @fa-var-undo; }
.@{fa-css-prefix}.@{fa-css-prefix}-legal:before { content: @fa-var-gavel; }
.@{fa-css-prefix}.@{fa-css-prefix}-tachometer:before { content: @fa-var-tachometer-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-dashboard:before { content: @fa-var-tachometer-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-comment-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-comment-o:before { content: @fa-var-comment; }
.@{fa-css-prefix}.@{fa-css-prefix}-comments-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-comments-o:before { content: @fa-var-comments; }
.@{fa-css-prefix}.@{fa-css-prefix}-flash:before { content: @fa-var-bolt; }
.@{fa-css-prefix}.@{fa-css-prefix}-clipboard {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-paste {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-paste:before { content: @fa-var-clipboard; }
.@{fa-css-prefix}.@{fa-css-prefix}-lightbulb-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-lightbulb-o:before { content: @fa-var-lightbulb; }
.@{fa-css-prefix}.@{fa-css-prefix}-exchange:before { content: @fa-var-exchange-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-cloud-download:before { content: @fa-var-cloud-download-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-cloud-upload:before { content: @fa-var-cloud-upload-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-bell-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bell-o:before { content: @fa-var-bell; }
.@{fa-css-prefix}.@{fa-css-prefix}-cutlery:before { content: @fa-var-utensils; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-text-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-text-o:before { content: @fa-var-file-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-building-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-building-o:before { content: @fa-var-building; }
.@{fa-css-prefix}.@{fa-css-prefix}-hospital-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hospital-o:before { content: @fa-var-hospital; }
.@{fa-css-prefix}.@{fa-css-prefix}-tablet:before { content: @fa-var-tablet-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-mobile:before { content: @fa-var-mobile-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-mobile-phone:before { content: @fa-var-mobile-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-circle-o:before { content: @fa-var-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-mail-reply:before { content: @fa-var-reply; }
.@{fa-css-prefix}.@{fa-css-prefix}-github-alt {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-folder-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-folder-o:before { content: @fa-var-folder; }
.@{fa-css-prefix}.@{fa-css-prefix}-folder-open-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-folder-open-o:before { content: @fa-var-folder-open; }
.@{fa-css-prefix}.@{fa-css-prefix}-smile-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-smile-o:before { content: @fa-var-smile; }
.@{fa-css-prefix}.@{fa-css-prefix}-frown-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-frown-o:before { content: @fa-var-frown; }
.@{fa-css-prefix}.@{fa-css-prefix}-meh-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-meh-o:before { content: @fa-var-meh; }
.@{fa-css-prefix}.@{fa-css-prefix}-keyboard-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-keyboard-o:before { content: @fa-var-keyboard; }
.@{fa-css-prefix}.@{fa-css-prefix}-flag-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-flag-o:before { content: @fa-var-flag; }
.@{fa-css-prefix}.@{fa-css-prefix}-mail-reply-all:before { content: @fa-var-reply-all; }
.@{fa-css-prefix}.@{fa-css-prefix}-star-half-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-star-half-o:before { content: @fa-var-star-half; }
.@{fa-css-prefix}.@{fa-css-prefix}-star-half-empty {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-star-half-empty:before { content: @fa-var-star-half; }
.@{fa-css-prefix}.@{fa-css-prefix}-star-half-full {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-star-half-full:before { content: @fa-var-star-half; }
.@{fa-css-prefix}.@{fa-css-prefix}-code-fork:before { content: @fa-var-code-branch; }
.@{fa-css-prefix}.@{fa-css-prefix}-chain-broken:before { content: @fa-var-unlink; }
.@{fa-css-prefix}.@{fa-css-prefix}-shield:before { content: @fa-var-shield-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-o:before { content: @fa-var-calendar; }
.@{fa-css-prefix}.@{fa-css-prefix}-maxcdn {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-html5 {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-css3 {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-ticket:before { content: @fa-var-ticket-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-minus-square-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-minus-square-o:before { content: @fa-var-minus-square; }
.@{fa-css-prefix}.@{fa-css-prefix}-level-up:before { content: @fa-var-level-up-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-level-down:before { content: @fa-var-level-down-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-pencil-square:before { content: @fa-var-pen-square; }
.@{fa-css-prefix}.@{fa-css-prefix}-external-link-square:before { content: @fa-var-external-link-square-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-compass {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-down {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-down:before { content: @fa-var-caret-square-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-down {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-down:before { content: @fa-var-caret-square-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-up {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-up:before { content: @fa-var-caret-square-up; }
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-up {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-up:before { content: @fa-var-caret-square-up; }
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-right {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-right:before { content: @fa-var-caret-square-right; }
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-right {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-right:before { content: @fa-var-caret-square-right; }
.@{fa-css-prefix}.@{fa-css-prefix}-eur:before { content: @fa-var-euro-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-euro:before { content: @fa-var-euro-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-gbp:before { content: @fa-var-pound-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-usd:before { content: @fa-var-dollar-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-dollar:before { content: @fa-var-dollar-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-inr:before { content: @fa-var-rupee-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-rupee:before { content: @fa-var-rupee-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-jpy:before { content: @fa-var-yen-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-cny:before { content: @fa-var-yen-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-rmb:before { content: @fa-var-yen-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-yen:before { content: @fa-var-yen-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-rub:before { content: @fa-var-ruble-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-ruble:before { content: @fa-var-ruble-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-rouble:before { content: @fa-var-ruble-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-krw:before { content: @fa-var-won-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-won:before { content: @fa-var-won-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-btc {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bitcoin {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bitcoin:before { content: @fa-var-btc; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-text:before { content: @fa-var-file-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-alpha-asc:before { content: @fa-var-sort-alpha-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-alpha-desc:before { content: @fa-var-sort-alpha-down-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-amount-asc:before { content: @fa-var-sort-amount-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-amount-desc:before { content: @fa-var-sort-amount-down-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-numeric-asc:before { content: @fa-var-sort-numeric-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-sort-numeric-desc:before { content: @fa-var-sort-numeric-down-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-youtube-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-youtube {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-xing {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-xing-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-youtube-play {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-youtube-play:before { content: @fa-var-youtube; }
.@{fa-css-prefix}.@{fa-css-prefix}-dropbox {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-stack-overflow {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-instagram {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-flickr {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-adn {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bitbucket {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bitbucket-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bitbucket-square:before { content: @fa-var-bitbucket; }
.@{fa-css-prefix}.@{fa-css-prefix}-tumblr {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-tumblr-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-long-arrow-down:before { content: @fa-var-long-arrow-alt-down; }
.@{fa-css-prefix}.@{fa-css-prefix}-long-arrow-up:before { content: @fa-var-long-arrow-alt-up; }
.@{fa-css-prefix}.@{fa-css-prefix}-long-arrow-left:before { content: @fa-var-long-arrow-alt-left; }
.@{fa-css-prefix}.@{fa-css-prefix}-long-arrow-right:before { content: @fa-var-long-arrow-alt-right; }
.@{fa-css-prefix}.@{fa-css-prefix}-apple {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-windows {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-android {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-linux {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-dribbble {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-skype {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-foursquare {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-trello {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-gratipay {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-gittip {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-gittip:before { content: @fa-var-gratipay; }
.@{fa-css-prefix}.@{fa-css-prefix}-sun-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun; }
.@{fa-css-prefix}.@{fa-css-prefix}-moon-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon; }
.@{fa-css-prefix}.@{fa-css-prefix}-vk {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-weibo {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-renren {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pagelines {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-stack-exchange {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-right {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-right:before { content: @fa-var-arrow-alt-circle-right; }
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-left {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-arrow-circle-o-left:before { content: @fa-var-arrow-alt-circle-left; }
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-left {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-caret-square-o-left:before { content: @fa-var-caret-square-left; }
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-left {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-toggle-left:before { content: @fa-var-caret-square-left; }
.@{fa-css-prefix}.@{fa-css-prefix}-dot-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-dot-circle-o:before { content: @fa-var-dot-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-vimeo-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-try:before { content: @fa-var-lira-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-turkish-lira:before { content: @fa-var-lira-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-plus-square-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-plus-square-o:before { content: @fa-var-plus-square; }
.@{fa-css-prefix}.@{fa-css-prefix}-slack {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wordpress {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-openid {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-institution:before { content: @fa-var-university; }
.@{fa-css-prefix}.@{fa-css-prefix}-bank:before { content: @fa-var-university; }
.@{fa-css-prefix}.@{fa-css-prefix}-mortar-board:before { content: @fa-var-graduation-cap; }
.@{fa-css-prefix}.@{fa-css-prefix}-yahoo {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-reddit {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-reddit-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-stumbleupon-circle {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-stumbleupon {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-delicious {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-digg {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pied-piper-pp {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pied-piper-alt {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-drupal {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-joomla {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-spoon:before { content: @fa-var-utensil-spoon; }
.@{fa-css-prefix}.@{fa-css-prefix}-behance {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-behance-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-steam {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-steam-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-automobile:before { content: @fa-var-car; }
.@{fa-css-prefix}.@{fa-css-prefix}-envelope-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-envelope-o:before { content: @fa-var-envelope; }
.@{fa-css-prefix}.@{fa-css-prefix}-spotify {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-deviantart {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-soundcloud {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-pdf-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-pdf-o:before { content: @fa-var-file-pdf; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-word-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-word-o:before { content: @fa-var-file-word; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-excel-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-excel-o:before { content: @fa-var-file-excel; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-powerpoint-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-powerpoint-o:before { content: @fa-var-file-powerpoint; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-image-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-image-o:before { content: @fa-var-file-image; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-photo-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-photo-o:before { content: @fa-var-file-image; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-picture-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-picture-o:before { content: @fa-var-file-image; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-archive-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-archive-o:before { content: @fa-var-file-archive; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-zip-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-zip-o:before { content: @fa-var-file-archive; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-audio-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-audio-o:before { content: @fa-var-file-audio; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-sound-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-sound-o:before { content: @fa-var-file-audio; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-video-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-video-o:before { content: @fa-var-file-video; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-movie-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-movie-o:before { content: @fa-var-file-video; }
.@{fa-css-prefix}.@{fa-css-prefix}-file-code-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-file-code-o:before { content: @fa-var-file-code; }
.@{fa-css-prefix}.@{fa-css-prefix}-vine {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-codepen {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-jsfiddle {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-life-ring {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-life-bouy {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-life-bouy:before { content: @fa-var-life-ring; }
.@{fa-css-prefix}.@{fa-css-prefix}-life-buoy {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-life-buoy:before { content: @fa-var-life-ring; }
.@{fa-css-prefix}.@{fa-css-prefix}-life-saver {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-life-saver:before { content: @fa-var-life-ring; }
.@{fa-css-prefix}.@{fa-css-prefix}-support {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-support:before { content: @fa-var-life-ring; }
.@{fa-css-prefix}.@{fa-css-prefix}-circle-o-notch:before { content: @fa-var-circle-notch; }
.@{fa-css-prefix}.@{fa-css-prefix}-rebel {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-ra {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-ra:before { content: @fa-var-rebel; }
.@{fa-css-prefix}.@{fa-css-prefix}-resistance {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-resistance:before { content: @fa-var-rebel; }
.@{fa-css-prefix}.@{fa-css-prefix}-empire {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-ge {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-ge:before { content: @fa-var-empire; }
.@{fa-css-prefix}.@{fa-css-prefix}-git-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-git {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hacker-news {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-y-combinator-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-y-combinator-square:before { content: @fa-var-hacker-news; }
.@{fa-css-prefix}.@{fa-css-prefix}-yc-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-yc-square:before { content: @fa-var-hacker-news; }
.@{fa-css-prefix}.@{fa-css-prefix}-tencent-weibo {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-qq {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-weixin {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wechat {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wechat:before { content: @fa-var-weixin; }
.@{fa-css-prefix}.@{fa-css-prefix}-send:before { content: @fa-var-paper-plane; }
.@{fa-css-prefix}.@{fa-css-prefix}-paper-plane-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-paper-plane-o:before { content: @fa-var-paper-plane; }
.@{fa-css-prefix}.@{fa-css-prefix}-send-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-send-o:before { content: @fa-var-paper-plane; }
.@{fa-css-prefix}.@{fa-css-prefix}-circle-thin {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-circle-thin:before { content: @fa-var-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-header:before { content: @fa-var-heading; }
.@{fa-css-prefix}.@{fa-css-prefix}-sliders:before { content: @fa-var-sliders-h; }
.@{fa-css-prefix}.@{fa-css-prefix}-futbol-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-futbol-o:before { content: @fa-var-futbol; }
.@{fa-css-prefix}.@{fa-css-prefix}-soccer-ball-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-soccer-ball-o:before { content: @fa-var-futbol; }
.@{fa-css-prefix}.@{fa-css-prefix}-slideshare {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-twitch {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-yelp {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-newspaper-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-newspaper-o:before { content: @fa-var-newspaper; }
.@{fa-css-prefix}.@{fa-css-prefix}-paypal {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google-wallet {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc-visa {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc-mastercard {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc-discover {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc-amex {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc-paypal {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc-stripe {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bell-slash-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bell-slash-o:before { content: @fa-var-bell-slash; }
.@{fa-css-prefix}.@{fa-css-prefix}-trash:before { content: @fa-var-trash-alt; }
.@{fa-css-prefix}.@{fa-css-prefix}-copyright {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-eyedropper:before { content: @fa-var-eye-dropper; }
.@{fa-css-prefix}.@{fa-css-prefix}-area-chart:before { content: @fa-var-chart-area; }
.@{fa-css-prefix}.@{fa-css-prefix}-pie-chart:before { content: @fa-var-chart-pie; }
.@{fa-css-prefix}.@{fa-css-prefix}-line-chart:before { content: @fa-var-chart-line; }
.@{fa-css-prefix}.@{fa-css-prefix}-lastfm {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-lastfm-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-ioxhost {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-angellist {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc:before { content: @fa-var-closed-captioning; }
.@{fa-css-prefix}.@{fa-css-prefix}-ils:before { content: @fa-var-shekel-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-shekel:before { content: @fa-var-shekel-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-sheqel:before { content: @fa-var-shekel-sign; }
.@{fa-css-prefix}.@{fa-css-prefix}-meanpath {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-meanpath:before { content: @fa-var-font-awesome; }
.@{fa-css-prefix}.@{fa-css-prefix}-buysellads {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-connectdevelop {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-dashcube {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-forumbee {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-leanpub {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-sellsy {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-shirtsinbulk {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-simplybuilt {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-skyatlas {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-diamond {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-diamond:before { content: @fa-var-gem; }
.@{fa-css-prefix}.@{fa-css-prefix}-intersex:before { content: @fa-var-transgender; }
.@{fa-css-prefix}.@{fa-css-prefix}-facebook-official {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-facebook-official:before { content: @fa-var-facebook; }
.@{fa-css-prefix}.@{fa-css-prefix}-pinterest-p {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-whatsapp {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hotel:before { content: @fa-var-bed; }
.@{fa-css-prefix}.@{fa-css-prefix}-viacoin {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-medium {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-y-combinator {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-yc {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-yc:before { content: @fa-var-y-combinator; }
.@{fa-css-prefix}.@{fa-css-prefix}-optin-monster {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-opencart {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-expeditedssl {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-battery-4:before { content: @fa-var-battery-full; }
.@{fa-css-prefix}.@{fa-css-prefix}-battery:before { content: @fa-var-battery-full; }
.@{fa-css-prefix}.@{fa-css-prefix}-battery-3:before { content: @fa-var-battery-three-quarters; }
.@{fa-css-prefix}.@{fa-css-prefix}-battery-2:before { content: @fa-var-battery-half; }
.@{fa-css-prefix}.@{fa-css-prefix}-battery-1:before { content: @fa-var-battery-quarter; }
.@{fa-css-prefix}.@{fa-css-prefix}-battery-0:before { content: @fa-var-battery-empty; }
.@{fa-css-prefix}.@{fa-css-prefix}-object-group {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-object-ungroup {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-sticky-note-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-sticky-note-o:before { content: @fa-var-sticky-note; }
.@{fa-css-prefix}.@{fa-css-prefix}-cc-jcb {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cc-diners-club {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-clone {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hourglass-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hourglass-o:before { content: @fa-var-hourglass; }
.@{fa-css-prefix}.@{fa-css-prefix}-hourglass-1:before { content: @fa-var-hourglass-start; }
.@{fa-css-prefix}.@{fa-css-prefix}-hourglass-2:before { content: @fa-var-hourglass-half; }
.@{fa-css-prefix}.@{fa-css-prefix}-hourglass-3:before { content: @fa-var-hourglass-end; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-rock-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-rock-o:before { content: @fa-var-hand-rock; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-grab-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-grab-o:before { content: @fa-var-hand-rock; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-paper-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-paper-o:before { content: @fa-var-hand-paper; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-stop-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-stop-o:before { content: @fa-var-hand-paper; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-scissors-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-scissors-o:before { content: @fa-var-hand-scissors; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-lizard-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-lizard-o:before { content: @fa-var-hand-lizard; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-spock-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-spock-o:before { content: @fa-var-hand-spock; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-pointer-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-pointer-o:before { content: @fa-var-hand-pointer; }
.@{fa-css-prefix}.@{fa-css-prefix}-hand-peace-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-hand-peace-o:before { content: @fa-var-hand-peace; }
.@{fa-css-prefix}.@{fa-css-prefix}-registered {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-creative-commons {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-gg {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-gg-circle {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-tripadvisor {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-odnoklassniki {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-odnoklassniki-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-get-pocket {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wikipedia-w {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-safari {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-chrome {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-firefox {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-opera {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-internet-explorer {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-television:before { content: @fa-var-tv; }
.@{fa-css-prefix}.@{fa-css-prefix}-contao {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-500px {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-amazon {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-plus-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-plus-o:before { content: @fa-var-calendar-plus; }
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-minus-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-minus-o:before { content: @fa-var-calendar-minus; }
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-times-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-times-o:before { content: @fa-var-calendar-times; }
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-check-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-calendar-check-o:before { content: @fa-var-calendar-check; }
.@{fa-css-prefix}.@{fa-css-prefix}-map-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-map-o:before { content: @fa-var-map; }
.@{fa-css-prefix}.@{fa-css-prefix}-commenting:before { content: @fa-var-comment-dots; }
.@{fa-css-prefix}.@{fa-css-prefix}-commenting-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-commenting-o:before { content: @fa-var-comment-dots; }
.@{fa-css-prefix}.@{fa-css-prefix}-houzz {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-vimeo {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-vimeo:before { content: @fa-var-vimeo-v; }
.@{fa-css-prefix}.@{fa-css-prefix}-black-tie {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-fonticons {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-reddit-alien {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-edge {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-credit-card-alt:before { content: @fa-var-credit-card; }
.@{fa-css-prefix}.@{fa-css-prefix}-codiepie {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-modx {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-fort-awesome {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-usb {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-product-hunt {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-mixcloud {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-scribd {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pause-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pause-circle-o:before { content: @fa-var-pause-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-stop-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-stop-circle-o:before { content: @fa-var-stop-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-bluetooth {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-bluetooth-b {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-gitlab {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wpbeginner {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wpforms {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-envira {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wheelchair-alt {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wheelchair-alt:before { content: @fa-var-accessible-icon; }
.@{fa-css-prefix}.@{fa-css-prefix}-question-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-question-circle-o:before { content: @fa-var-question-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-volume-control-phone:before { content: @fa-var-phone-volume; }
.@{fa-css-prefix}.@{fa-css-prefix}-asl-interpreting:before { content: @fa-var-american-sign-language-interpreting; }
.@{fa-css-prefix}.@{fa-css-prefix}-deafness:before { content: @fa-var-deaf; }
.@{fa-css-prefix}.@{fa-css-prefix}-hard-of-hearing:before { content: @fa-var-deaf; }
.@{fa-css-prefix}.@{fa-css-prefix}-glide {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-glide-g {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-signing:before { content: @fa-var-sign-language; }
.@{fa-css-prefix}.@{fa-css-prefix}-viadeo {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-viadeo-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-snapchat {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-snapchat-ghost {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-snapchat-square {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-pied-piper {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-first-order {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-yoast {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-themeisle {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google-plus-official {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google-plus-official:before { content: @fa-var-google-plus; }
.@{fa-css-prefix}.@{fa-css-prefix}-google-plus-circle {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-google-plus-circle:before { content: @fa-var-google-plus; }
.@{fa-css-prefix}.@{fa-css-prefix}-font-awesome {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-fa {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-fa:before { content: @fa-var-font-awesome; }
.@{fa-css-prefix}.@{fa-css-prefix}-handshake-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-handshake-o:before { content: @fa-var-handshake; }
.@{fa-css-prefix}.@{fa-css-prefix}-envelope-open-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-envelope-open-o:before { content: @fa-var-envelope-open; }
.@{fa-css-prefix}.@{fa-css-prefix}-linode {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-address-book-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-address-book-o:before { content: @fa-var-address-book; }
.@{fa-css-prefix}.@{fa-css-prefix}-vcard:before { content: @fa-var-address-card; }
.@{fa-css-prefix}.@{fa-css-prefix}-address-card-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-address-card-o:before { content: @fa-var-address-card; }
.@{fa-css-prefix}.@{fa-css-prefix}-vcard-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-vcard-o:before { content: @fa-var-address-card; }
.@{fa-css-prefix}.@{fa-css-prefix}-user-circle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-user-circle-o:before { content: @fa-var-user-circle; }
.@{fa-css-prefix}.@{fa-css-prefix}-user-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-user-o:before { content: @fa-var-user; }
.@{fa-css-prefix}.@{fa-css-prefix}-id-badge {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-drivers-license:before { content: @fa-var-id-card; }
.@{fa-css-prefix}.@{fa-css-prefix}-id-card-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-id-card-o:before { content: @fa-var-id-card; }
.@{fa-css-prefix}.@{fa-css-prefix}-drivers-license-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-drivers-license-o:before { content: @fa-var-id-card; }
.@{fa-css-prefix}.@{fa-css-prefix}-quora {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-free-code-camp {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-telegram {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-thermometer-4:before { content: @fa-var-thermometer-full; }
.@{fa-css-prefix}.@{fa-css-prefix}-thermometer:before { content: @fa-var-thermometer-full; }
.@{fa-css-prefix}.@{fa-css-prefix}-thermometer-3:before { content: @fa-var-thermometer-three-quarters; }
.@{fa-css-prefix}.@{fa-css-prefix}-thermometer-2:before { content: @fa-var-thermometer-half; }
.@{fa-css-prefix}.@{fa-css-prefix}-thermometer-1:before { content: @fa-var-thermometer-quarter; }
.@{fa-css-prefix}.@{fa-css-prefix}-thermometer-0:before { content: @fa-var-thermometer-empty; }
.@{fa-css-prefix}.@{fa-css-prefix}-bathtub:before { content: @fa-var-bath; }
.@{fa-css-prefix}.@{fa-css-prefix}-s15:before { content: @fa-var-bath; }
.@{fa-css-prefix}.@{fa-css-prefix}-window-maximize {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-window-restore {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-times-rectangle:before { content: @fa-var-window-close; }
.@{fa-css-prefix}.@{fa-css-prefix}-window-close-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-window-close-o:before { content: @fa-var-window-close; }
.@{fa-css-prefix}.@{fa-css-prefix}-times-rectangle-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-times-rectangle-o:before { content: @fa-var-window-close; }
.@{fa-css-prefix}.@{fa-css-prefix}-bandcamp {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-grav {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-etsy {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-imdb {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-ravelry {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-eercast {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-eercast:before { content: @fa-var-sellcast; }
.@{fa-css-prefix}.@{fa-css-prefix}-snowflake-o {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-snowflake-o:before { content: @fa-var-snowflake; }
.@{fa-css-prefix}.@{fa-css-prefix}-superpowers {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-wpexplorer {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
.@{fa-css-prefix}.@{fa-css-prefix}-cab:before { content: @fa-var-taxi; }
// Stacked Icons
// -------------------------
.@{fa-css-prefix}-stack {
display: inline-block;
height: 2em;
line-height: 2em;
position: relative;
vertical-align: middle;
width: 2em;
}
.@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x {
left: 0;
position: absolute;
text-align: center;
width: 100%;
}
.@{fa-css-prefix}-stack-1x { line-height: inherit; }
.@{fa-css-prefix}-stack-2x { font-size: 2em; }
.@{fa-css-prefix}-inverse { color: @fa-inverse; }
// Variables
// --------------------------
@fa-font-path: "../webfonts";
@fa-font-size-base: 16px;
@fa-font-display: block;
@fa-line-height-base: 1;
@fa-css-prefix: fa;
@fa-version: "5.13.0";
@fa-border-color: #eee;
@fa-inverse: #fff;
@fa-li-width: 2em;
@fa-primary-opacity: 1;
@fa-secondary-opacity: .4;
@fa-var-500px: "\f26e";
@fa-var-accessible-icon: "\f368";
@fa-var-accusoft: "\f369";
@fa-var-acquisitions-incorporated: "\f6af";
@fa-var-ad: "\f641";
@fa-var-address-book: "\f2b9";
@fa-var-address-card: "\f2bb";
@fa-var-adjust: "\f042";
@fa-var-adn: "\f170";
@fa-var-adobe: "\f778";
@fa-var-adversal: "\f36a";
@fa-var-affiliatetheme: "\f36b";
@fa-var-air-freshener: "\f5d0";
@fa-var-airbnb: "\f834";
@fa-var-algolia: "\f36c";
@fa-var-align-center: "\f037";
@fa-var-align-justify: "\f039";
@fa-var-align-left: "\f036";
@fa-var-align-right: "\f038";
@fa-var-alipay: "\f642";
@fa-var-allergies: "\f461";
@fa-var-amazon: "\f270";
@fa-var-amazon-pay: "\f42c";
@fa-var-ambulance: "\f0f9";
@fa-var-american-sign-language-interpreting: "\f2a3";
@fa-var-amilia: "\f36d";
@fa-var-anchor: "\f13d";
@fa-var-android: "\f17b";
@fa-var-angellist: "\f209";
@fa-var-angle-double-down: "\f103";
@fa-var-angle-double-left: "\f100";
@fa-var-angle-double-right: "\f101";
@fa-var-angle-double-up: "\f102";
@fa-var-angle-down: "\f107";
@fa-var-angle-left: "\f104";
@fa-var-angle-right: "\f105";
@fa-var-angle-up: "\f106";
@fa-var-angry: "\f556";
@fa-var-angrycreative: "\f36e";
@fa-var-angular: "\f420";
@fa-var-ankh: "\f644";
@fa-var-app-store: "\f36f";
@fa-var-app-store-ios: "\f370";
@fa-var-apper: "\f371";
@fa-var-apple: "\f179";
@fa-var-apple-alt: "\f5d1";
@fa-var-apple-pay: "\f415";
@fa-var-archive: "\f187";
@fa-var-archway: "\f557";
@fa-var-arrow-alt-circle-down: "\f358";
@fa-var-arrow-alt-circle-left: "\f359";
@fa-var-arrow-alt-circle-right: "\f35a";
@fa-var-arrow-alt-circle-up: "\f35b";
@fa-var-arrow-circle-down: "\f0ab";
@fa-var-arrow-circle-left: "\f0a8";
@fa-var-arrow-circle-right: "\f0a9";
@fa-var-arrow-circle-up: "\f0aa";
@fa-var-arrow-down: "\f063";
@fa-var-arrow-left: "\f060";
@fa-var-arrow-right: "\f061";
@fa-var-arrow-up: "\f062";
@fa-var-arrows-alt: "\f0b2";
@fa-var-arrows-alt-h: "\f337";
@fa-var-arrows-alt-v: "\f338";
@fa-var-artstation: "\f77a";
@fa-var-assistive-listening-systems: "\f2a2";
@fa-var-asterisk: "\f069";
@fa-var-asymmetrik: "\f372";
@fa-var-at: "\f1fa";
@fa-var-atlas: "\f558";
@fa-var-atlassian: "\f77b";
@fa-var-atom: "\f5d2";
@fa-var-audible: "\f373";
@fa-var-audio-description: "\f29e";
@fa-var-autoprefixer: "\f41c";
@fa-var-avianex: "\f374";
@fa-var-aviato: "\f421";
@fa-var-award: "\f559";
@fa-var-aws: "\f375";
@fa-var-baby: "\f77c";
@fa-var-baby-carriage: "\f77d";
@fa-var-backspace: "\f55a";
@fa-var-backward: "\f04a";
@fa-var-bacon: "\f7e5";
@fa-var-bahai: "\f666";
@fa-var-balance-scale: "\f24e";
@fa-var-balance-scale-left: "\f515";
@fa-var-balance-scale-right: "\f516";
@fa-var-ban: "\f05e";
@fa-var-band-aid: "\f462";
@fa-var-bandcamp: "\f2d5";
@fa-var-barcode: "\f02a";
@fa-var-bars: "\f0c9";
@fa-var-baseball-ball: "\f433";
@fa-var-basketball-ball: "\f434";
@fa-var-bath: "\f2cd";
@fa-var-battery-empty: "\f244";
@fa-var-battery-full: "\f240";
@fa-var-battery-half: "\f242";
@fa-var-battery-quarter: "\f243";
@fa-var-battery-three-quarters: "\f241";
@fa-var-battle-net: "\f835";
@fa-var-bed: "\f236";
@fa-var-beer: "\f0fc";
@fa-var-behance: "\f1b4";
@fa-var-behance-square: "\f1b5";
@fa-var-bell: "\f0f3";
@fa-var-bell-slash: "\f1f6";
@fa-var-bezier-curve: "\f55b";
@fa-var-bible: "\f647";
@fa-var-bicycle: "\f206";
@fa-var-biking: "\f84a";
@fa-var-bimobject: "\f378";
@fa-var-binoculars: "\f1e5";
@fa-var-biohazard: "\f780";
@fa-var-birthday-cake: "\f1fd";
@fa-var-bitbucket: "\f171";
@fa-var-bitcoin: "\f379";
@fa-var-bity: "\f37a";
@fa-var-black-tie: "\f27e";
@fa-var-blackberry: "\f37b";
@fa-var-blender: "\f517";
@fa-var-blender-phone: "\f6b6";
@fa-var-blind: "\f29d";
@fa-var-blog: "\f781";
@fa-var-blogger: "\f37c";
@fa-var-blogger-b: "\f37d";
@fa-var-bluetooth: "\f293";
@fa-var-bluetooth-b: "\f294";
@fa-var-bold: "\f032";
@fa-var-bolt: "\f0e7";
@fa-var-bomb: "\f1e2";
@fa-var-bone: "\f5d7";
@fa-var-bong: "\f55c";
@fa-var-book: "\f02d";
@fa-var-book-dead: "\f6b7";
@fa-var-book-medical: "\f7e6";
@fa-var-book-open: "\f518";
@fa-var-book-reader: "\f5da";
@fa-var-bookmark: "\f02e";
@fa-var-bootstrap: "\f836";
@fa-var-border-all: "\f84c";
@fa-var-border-none: "\f850";
@fa-var-border-style: "\f853";
@fa-var-bowling-ball: "\f436";
@fa-var-box: "\f466";
@fa-var-box-open: "\f49e";
@fa-var-box-tissue: "\f95b";
@fa-var-boxes: "\f468";
@fa-var-braille: "\f2a1";
@fa-var-brain: "\f5dc";
@fa-var-bread-slice: "\f7ec";
@fa-var-briefcase: "\f0b1";
@fa-var-briefcase-medical: "\f469";
@fa-var-broadcast-tower: "\f519";
@fa-var-broom: "\f51a";
@fa-var-brush: "\f55d";
@fa-var-btc: "\f15a";
@fa-var-buffer: "\f837";
@fa-var-bug: "\f188";
@fa-var-building: "\f1ad";
@fa-var-bullhorn: "\f0a1";
@fa-var-bullseye: "\f140";
@fa-var-burn: "\f46a";
@fa-var-buromobelexperte: "\f37f";
@fa-var-bus: "\f207";
@fa-var-bus-alt: "\f55e";
@fa-var-business-time: "\f64a";
@fa-var-buy-n-large: "\f8a6";
@fa-var-buysellads: "\f20d";
@fa-var-calculator: "\f1ec";
@fa-var-calendar: "\f133";
@fa-var-calendar-alt: "\f073";
@fa-var-calendar-check: "\f274";
@fa-var-calendar-day: "\f783";
@fa-var-calendar-minus: "\f272";
@fa-var-calendar-plus: "\f271";
@fa-var-calendar-times: "\f273";
@fa-var-calendar-week: "\f784";
@fa-var-camera: "\f030";
@fa-var-camera-retro: "\f083";
@fa-var-campground: "\f6bb";
@fa-var-canadian-maple-leaf: "\f785";
@fa-var-candy-cane: "\f786";
@fa-var-cannabis: "\f55f";
@fa-var-capsules: "\f46b";
@fa-var-car: "\f1b9";
@fa-var-car-alt: "\f5de";
@fa-var-car-battery: "\f5df";
@fa-var-car-crash: "\f5e1";
@fa-var-car-side: "\f5e4";
@fa-var-caravan: "\f8ff";
@fa-var-caret-down: "\f0d7";
@fa-var-caret-left: "\f0d9";
@fa-var-caret-right: "\f0da";
@fa-var-caret-square-down: "\f150";
@fa-var-caret-square-left: "\f191";
@fa-var-caret-square-right: "\f152";
@fa-var-caret-square-up: "\f151";
@fa-var-caret-up: "\f0d8";
@fa-var-carrot: "\f787";
@fa-var-cart-arrow-down: "\f218";
@fa-var-cart-plus: "\f217";
@fa-var-cash-register: "\f788";
@fa-var-cat: "\f6be";
@fa-var-cc-amazon-pay: "\f42d";
@fa-var-cc-amex: "\f1f3";
@fa-var-cc-apple-pay: "\f416";
@fa-var-cc-diners-club: "\f24c";
@fa-var-cc-discover: "\f1f2";
@fa-var-cc-jcb: "\f24b";
@fa-var-cc-mastercard: "\f1f1";
@fa-var-cc-paypal: "\f1f4";
@fa-var-cc-stripe: "\f1f5";
@fa-var-cc-visa: "\f1f0";
@fa-var-centercode: "\f380";
@fa-var-centos: "\f789";
@fa-var-certificate: "\f0a3";
@fa-var-chair: "\f6c0";
@fa-var-chalkboard: "\f51b";
@fa-var-chalkboard-teacher: "\f51c";
@fa-var-charging-station: "\f5e7";
@fa-var-chart-area: "\f1fe";
@fa-var-chart-bar: "\f080";
@fa-var-chart-line: "\f201";
@fa-var-chart-pie: "\f200";
@fa-var-check: "\f00c";
@fa-var-check-circle: "\f058";
@fa-var-check-double: "\f560";
@fa-var-check-square: "\f14a";
@fa-var-cheese: "\f7ef";
@fa-var-chess: "\f439";
@fa-var-chess-bishop: "\f43a";
@fa-var-chess-board: "\f43c";
@fa-var-chess-king: "\f43f";
@fa-var-chess-knight: "\f441";
@fa-var-chess-pawn: "\f443";
@fa-var-chess-queen: "\f445";
@fa-var-chess-rook: "\f447";
@fa-var-chevron-circle-down: "\f13a";
@fa-var-chevron-circle-left: "\f137";
@fa-var-chevron-circle-right: "\f138";
@fa-var-chevron-circle-up: "\f139";
@fa-var-chevron-down: "\f078";
@fa-var-chevron-left: "\f053";
@fa-var-chevron-right: "\f054";
@fa-var-chevron-up: "\f077";
@fa-var-child: "\f1ae";
@fa-var-chrome: "\f268";
@fa-var-chromecast: "\f838";
@fa-var-church: "\f51d";
@fa-var-circle: "\f111";
@fa-var-circle-notch: "\f1ce";
@fa-var-city: "\f64f";
@fa-var-clinic-medical: "\f7f2";
@fa-var-clipboard: "\f328";
@fa-var-clipboard-check: "\f46c";
@fa-var-clipboard-list: "\f46d";
@fa-var-clock: "\f017";
@fa-var-clone: "\f24d";
@fa-var-closed-captioning: "\f20a";
@fa-var-cloud: "\f0c2";
@fa-var-cloud-download-alt: "\f381";
@fa-var-cloud-meatball: "\f73b";
@fa-var-cloud-moon: "\f6c3";
@fa-var-cloud-moon-rain: "\f73c";
@fa-var-cloud-rain: "\f73d";
@fa-var-cloud-showers-heavy: "\f740";
@fa-var-cloud-sun: "\f6c4";
@fa-var-cloud-sun-rain: "\f743";
@fa-var-cloud-upload-alt: "\f382";
@fa-var-cloudscale: "\f383";
@fa-var-cloudsmith: "\f384";
@fa-var-cloudversify: "\f385";
@fa-var-cocktail: "\f561";
@fa-var-code: "\f121";
@fa-var-code-branch: "\f126";
@fa-var-codepen: "\f1cb";
@fa-var-codiepie: "\f284";
@fa-var-coffee: "\f0f4";
@fa-var-cog: "\f013";
@fa-var-cogs: "\f085";
@fa-var-coins: "\f51e";
@fa-var-columns: "\f0db";
@fa-var-comment: "\f075";
@fa-var-comment-alt: "\f27a";
@fa-var-comment-dollar: "\f651";
@fa-var-comment-dots: "\f4ad";
@fa-var-comment-medical: "\f7f5";
@fa-var-comment-slash: "\f4b3";
@fa-var-comments: "\f086";
@fa-var-comments-dollar: "\f653";
@fa-var-compact-disc: "\f51f";
@fa-var-compass: "\f14e";
@fa-var-compress: "\f066";
@fa-var-compress-alt: "\f422";
@fa-var-compress-arrows-alt: "\f78c";
@fa-var-concierge-bell: "\f562";
@fa-var-confluence: "\f78d";
@fa-var-connectdevelop: "\f20e";
@fa-var-contao: "\f26d";
@fa-var-cookie: "\f563";
@fa-var-cookie-bite: "\f564";
@fa-var-copy: "\f0c5";
@fa-var-copyright: "\f1f9";
@fa-var-cotton-bureau: "\f89e";
@fa-var-couch: "\f4b8";
@fa-var-cpanel: "\f388";
@fa-var-creative-commons: "\f25e";
@fa-var-creative-commons-by: "\f4e7";
@fa-var-creative-commons-nc: "\f4e8";
@fa-var-creative-commons-nc-eu: "\f4e9";
@fa-var-creative-commons-nc-jp: "\f4ea";
@fa-var-creative-commons-nd: "\f4eb";
@fa-var-creative-commons-pd: "\f4ec";
@fa-var-creative-commons-pd-alt: "\f4ed";
@fa-var-creative-commons-remix: "\f4ee";
@fa-var-creative-commons-sa: "\f4ef";
@fa-var-creative-commons-sampling: "\f4f0";
@fa-var-creative-commons-sampling-plus: "\f4f1";
@fa-var-creative-commons-share: "\f4f2";
@fa-var-creative-commons-zero: "\f4f3";
@fa-var-credit-card: "\f09d";
@fa-var-critical-role: "\f6c9";
@fa-var-crop: "\f125";
@fa-var-crop-alt: "\f565";
@fa-var-cross: "\f654";
@fa-var-crosshairs: "\f05b";
@fa-var-crow: "\f520";
@fa-var-crown: "\f521";
@fa-var-crutch: "\f7f7";
@fa-var-css3: "\f13c";
@fa-var-css3-alt: "\f38b";
@fa-var-cube: "\f1b2";
@fa-var-cubes: "\f1b3";
@fa-var-cut: "\f0c4";
@fa-var-cuttlefish: "\f38c";
@fa-var-d-and-d: "\f38d";
@fa-var-d-and-d-beyond: "\f6ca";
@fa-var-dailymotion: "\f952";
@fa-var-dashcube: "\f210";
@fa-var-database: "\f1c0";
@fa-var-deaf: "\f2a4";
@fa-var-delicious: "\f1a5";
@fa-var-democrat: "\f747";
@fa-var-deploydog: "\f38e";
@fa-var-deskpro: "\f38f";
@fa-var-desktop: "\f108";
@fa-var-dev: "\f6cc";
@fa-var-deviantart: "\f1bd";
@fa-var-dharmachakra: "\f655";
@fa-var-dhl: "\f790";
@fa-var-diagnoses: "\f470";
@fa-var-diaspora: "\f791";
@fa-var-dice: "\f522";
@fa-var-dice-d20: "\f6cf";
@fa-var-dice-d6: "\f6d1";
@fa-var-dice-five: "\f523";
@fa-var-dice-four: "\f524";
@fa-var-dice-one: "\f525";
@fa-var-dice-six: "\f526";
@fa-var-dice-three: "\f527";
@fa-var-dice-two: "\f528";
@fa-var-digg: "\f1a6";
@fa-var-digital-ocean: "\f391";
@fa-var-digital-tachograph: "\f566";
@fa-var-directions: "\f5eb";
@fa-var-discord: "\f392";
@fa-var-discourse: "\f393";
@fa-var-disease: "\f7fa";
@fa-var-divide: "\f529";
@fa-var-dizzy: "\f567";
@fa-var-dna: "\f471";
@fa-var-dochub: "\f394";
@fa-var-docker: "\f395";
@fa-var-dog: "\f6d3";
@fa-var-dollar-sign: "\f155";
@fa-var-dolly: "\f472";
@fa-var-dolly-flatbed: "\f474";
@fa-var-donate: "\f4b9";
@fa-var-door-closed: "\f52a";
@fa-var-door-open: "\f52b";
@fa-var-dot-circle: "\f192";
@fa-var-dove: "\f4ba";
@fa-var-download: "\f019";
@fa-var-draft2digital: "\f396";
@fa-var-drafting-compass: "\f568";
@fa-var-dragon: "\f6d5";
@fa-var-draw-polygon: "\f5ee";
@fa-var-dribbble: "\f17d";
@fa-var-dribbble-square: "\f397";
@fa-var-dropbox: "\f16b";
@fa-var-drum: "\f569";
@fa-var-drum-steelpan: "\f56a";
@fa-var-drumstick-bite: "\f6d7";
@fa-var-drupal: "\f1a9";
@fa-var-dumbbell: "\f44b";
@fa-var-dumpster: "\f793";
@fa-var-dumpster-fire: "\f794";
@fa-var-dungeon: "\f6d9";
@fa-var-dyalog: "\f399";
@fa-var-earlybirds: "\f39a";
@fa-var-ebay: "\f4f4";
@fa-var-edge: "\f282";
@fa-var-edit: "\f044";
@fa-var-egg: "\f7fb";
@fa-var-eject: "\f052";
@fa-var-elementor: "\f430";
@fa-var-ellipsis-h: "\f141";
@fa-var-ellipsis-v: "\f142";
@fa-var-ello: "\f5f1";
@fa-var-ember: "\f423";
@fa-var-empire: "\f1d1";
@fa-var-envelope: "\f0e0";
@fa-var-envelope-open: "\f2b6";
@fa-var-envelope-open-text: "\f658";
@fa-var-envelope-square: "\f199";
@fa-var-envira: "\f299";
@fa-var-equals: "\f52c";
@fa-var-eraser: "\f12d";
@fa-var-erlang: "\f39d";
@fa-var-ethereum: "\f42e";
@fa-var-ethernet: "\f796";
@fa-var-etsy: "\f2d7";
@fa-var-euro-sign: "\f153";
@fa-var-evernote: "\f839";
@fa-var-exchange-alt: "\f362";
@fa-var-exclamation: "\f12a";
@fa-var-exclamation-circle: "\f06a";
@fa-var-exclamation-triangle: "\f071";
@fa-var-expand: "\f065";
@fa-var-expand-alt: "\f424";
@fa-var-expand-arrows-alt: "\f31e";
@fa-var-expeditedssl: "\f23e";
@fa-var-external-link-alt: "\f35d";
@fa-var-external-link-square-alt: "\f360";
@fa-var-eye: "\f06e";
@fa-var-eye-dropper: "\f1fb";
@fa-var-eye-slash: "\f070";
@fa-var-facebook: "\f09a";
@fa-var-facebook-f: "\f39e";
@fa-var-facebook-messenger: "\f39f";
@fa-var-facebook-square: "\f082";
@fa-var-fan: "\f863";
@fa-var-fantasy-flight-games: "\f6dc";
@fa-var-fast-backward: "\f049";
@fa-var-fast-forward: "\f050";
@fa-var-faucet: "\f905";
@fa-var-fax: "\f1ac";
@fa-var-feather: "\f52d";
@fa-var-feather-alt: "\f56b";
@fa-var-fedex: "\f797";
@fa-var-fedora: "\f798";
@fa-var-female: "\f182";
@fa-var-fighter-jet: "\f0fb";
@fa-var-figma: "\f799";
@fa-var-file: "\f15b";
@fa-var-file-alt: "\f15c";
@fa-var-file-archive: "\f1c6";
@fa-var-file-audio: "\f1c7";
@fa-var-file-code: "\f1c9";
@fa-var-file-contract: "\f56c";
@fa-var-file-csv: "\f6dd";
@fa-var-file-download: "\f56d";
@fa-var-file-excel: "\f1c3";
@fa-var-file-export: "\f56e";
@fa-var-file-image: "\f1c5";
@fa-var-file-import: "\f56f";
@fa-var-file-invoice: "\f570";
@fa-var-file-invoice-dollar: "\f571";
@fa-var-file-medical: "\f477";
@fa-var-file-medical-alt: "\f478";
@fa-var-file-pdf: "\f1c1";
@fa-var-file-powerpoint: "\f1c4";
@fa-var-file-prescription: "\f572";
@fa-var-file-signature: "\f573";
@fa-var-file-upload: "\f574";
@fa-var-file-video: "\f1c8";
@fa-var-file-word: "\f1c2";
@fa-var-fill: "\f575";
@fa-var-fill-drip: "\f576";
@fa-var-film: "\f008";
@fa-var-filter: "\f0b0";
@fa-var-fingerprint: "\f577";
@fa-var-fire: "\f06d";
@fa-var-fire-alt: "\f7e4";
@fa-var-fire-extinguisher: "\f134";
@fa-var-firefox: "\f269";
@fa-var-firefox-browser: "\f907";
@fa-var-first-aid: "\f479";
@fa-var-first-order: "\f2b0";
@fa-var-first-order-alt: "\f50a";
@fa-var-firstdraft: "\f3a1";
@fa-var-fish: "\f578";
@fa-var-fist-raised: "\f6de";
@fa-var-flag: "\f024";
@fa-var-flag-checkered: "\f11e";
@fa-var-flag-usa: "\f74d";
@fa-var-flask: "\f0c3";
@fa-var-flickr: "\f16e";
@fa-var-flipboard: "\f44d";
@fa-var-flushed: "\f579";
@fa-var-fly: "\f417";
@fa-var-folder: "\f07b";
@fa-var-folder-minus: "\f65d";
@fa-var-folder-open: "\f07c";
@fa-var-folder-plus: "\f65e";
@fa-var-font: "\f031";
@fa-var-font-awesome: "\f2b4";
@fa-var-font-awesome-alt: "\f35c";
@fa-var-font-awesome-flag: "\f425";
@fa-var-font-awesome-logo-full: "\f4e6";
@fa-var-fonticons: "\f280";
@fa-var-fonticons-fi: "\f3a2";
@fa-var-football-ball: "\f44e";
@fa-var-fort-awesome: "\f286";
@fa-var-fort-awesome-alt: "\f3a3";
@fa-var-forumbee: "\f211";
@fa-var-forward: "\f04e";
@fa-var-foursquare: "\f180";
@fa-var-free-code-camp: "\f2c5";
@fa-var-freebsd: "\f3a4";
@fa-var-frog: "\f52e";
@fa-var-frown: "\f119";
@fa-var-frown-open: "\f57a";
@fa-var-fulcrum: "\f50b";
@fa-var-funnel-dollar: "\f662";
@fa-var-futbol: "\f1e3";
@fa-var-galactic-republic: "\f50c";
@fa-var-galactic-senate: "\f50d";
@fa-var-gamepad: "\f11b";
@fa-var-gas-pump: "\f52f";
@fa-var-gavel: "\f0e3";
@fa-var-gem: "\f3a5";
@fa-var-genderless: "\f22d";
@fa-var-get-pocket: "\f265";
@fa-var-gg: "\f260";
@fa-var-gg-circle: "\f261";
@fa-var-ghost: "\f6e2";
@fa-var-gift: "\f06b";
@fa-var-gifts: "\f79c";
@fa-var-git: "\f1d3";
@fa-var-git-alt: "\f841";
@fa-var-git-square: "\f1d2";
@fa-var-github: "\f09b";
@fa-var-github-alt: "\f113";
@fa-var-github-square: "\f092";
@fa-var-gitkraken: "\f3a6";
@fa-var-gitlab: "\f296";
@fa-var-gitter: "\f426";
@fa-var-glass-cheers: "\f79f";
@fa-var-glass-martini: "\f000";
@fa-var-glass-martini-alt: "\f57b";
@fa-var-glass-whiskey: "\f7a0";
@fa-var-glasses: "\f530";
@fa-var-glide: "\f2a5";
@fa-var-glide-g: "\f2a6";
@fa-var-globe: "\f0ac";
@fa-var-globe-africa: "\f57c";
@fa-var-globe-americas: "\f57d";
@fa-var-globe-asia: "\f57e";
@fa-var-globe-europe: "\f7a2";
@fa-var-gofore: "\f3a7";
@fa-var-golf-ball: "\f450";
@fa-var-goodreads: "\f3a8";
@fa-var-goodreads-g: "\f3a9";
@fa-var-google: "\f1a0";
@fa-var-google-drive: "\f3aa";
@fa-var-google-play: "\f3ab";
@fa-var-google-plus: "\f2b3";
@fa-var-google-plus-g: "\f0d5";
@fa-var-google-plus-square: "\f0d4";
@fa-var-google-wallet: "\f1ee";
@fa-var-gopuram: "\f664";
@fa-var-graduation-cap: "\f19d";
@fa-var-gratipay: "\f184";
@fa-var-grav: "\f2d6";
@fa-var-greater-than: "\f531";
@fa-var-greater-than-equal: "\f532";
@fa-var-grimace: "\f57f";
@fa-var-grin: "\f580";
@fa-var-grin-alt: "\f581";
@fa-var-grin-beam: "\f582";
@fa-var-grin-beam-sweat: "\f583";
@fa-var-grin-hearts: "\f584";
@fa-var-grin-squint: "\f585";
@fa-var-grin-squint-tears: "\f586";
@fa-var-grin-stars: "\f587";
@fa-var-grin-tears: "\f588";
@fa-var-grin-tongue: "\f589";
@fa-var-grin-tongue-squint: "\f58a";
@fa-var-grin-tongue-wink: "\f58b";
@fa-var-grin-wink: "\f58c";
@fa-var-grip-horizontal: "\f58d";
@fa-var-grip-lines: "\f7a4";
@fa-var-grip-lines-vertical: "\f7a5";
@fa-var-grip-vertical: "\f58e";
@fa-var-gripfire: "\f3ac";
@fa-var-grunt: "\f3ad";
@fa-var-guitar: "\f7a6";
@fa-var-gulp: "\f3ae";
@fa-var-h-square: "\f0fd";
@fa-var-hacker-news: "\f1d4";
@fa-var-hacker-news-square: "\f3af";
@fa-var-hackerrank: "\f5f7";
@fa-var-hamburger: "\f805";
@fa-var-hammer: "\f6e3";
@fa-var-hamsa: "\f665";
@fa-var-hand-holding: "\f4bd";
@fa-var-hand-holding-heart: "\f4be";
@fa-var-hand-holding-medical: "\f95c";
@fa-var-hand-holding-usd: "\f4c0";
@fa-var-hand-holding-water: "\f4c1";
@fa-var-hand-lizard: "\f258";
@fa-var-hand-middle-finger: "\f806";
@fa-var-hand-paper: "\f256";
@fa-var-hand-peace: "\f25b";
@fa-var-hand-point-down: "\f0a7";
@fa-var-hand-point-left: "\f0a5";
@fa-var-hand-point-right: "\f0a4";
@fa-var-hand-point-up: "\f0a6";
@fa-var-hand-pointer: "\f25a";
@fa-var-hand-rock: "\f255";
@fa-var-hand-scissors: "\f257";
@fa-var-hand-sparkles: "\f95d";
@fa-var-hand-spock: "\f259";
@fa-var-hands: "\f4c2";
@fa-var-hands-helping: "\f4c4";
@fa-var-hands-wash: "\f95e";
@fa-var-handshake: "\f2b5";
@fa-var-handshake-alt-slash: "\f95f";
@fa-var-handshake-slash: "\f960";
@fa-var-hanukiah: "\f6e6";
@fa-var-hard-hat: "\f807";
@fa-var-hashtag: "\f292";
@fa-var-hat-cowboy: "\f8c0";
@fa-var-hat-cowboy-side: "\f8c1";
@fa-var-hat-wizard: "\f6e8";
@fa-var-hdd: "\f0a0";
@fa-var-head-side-cough: "\f961";
@fa-var-head-side-cough-slash: "\f962";
@fa-var-head-side-mask: "\f963";
@fa-var-head-side-virus: "\f964";
@fa-var-heading: "\f1dc";
@fa-var-headphones: "\f025";
@fa-var-headphones-alt: "\f58f";
@fa-var-headset: "\f590";
@fa-var-heart: "\f004";
@fa-var-heart-broken: "\f7a9";
@fa-var-heartbeat: "\f21e";
@fa-var-helicopter: "\f533";
@fa-var-highlighter: "\f591";
@fa-var-hiking: "\f6ec";
@fa-var-hippo: "\f6ed";
@fa-var-hips: "\f452";
@fa-var-hire-a-helper: "\f3b0";
@fa-var-history: "\f1da";
@fa-var-hockey-puck: "\f453";
@fa-var-holly-berry: "\f7aa";
@fa-var-home: "\f015";
@fa-var-hooli: "\f427";
@fa-var-hornbill: "\f592";
@fa-var-horse: "\f6f0";
@fa-var-horse-head: "\f7ab";
@fa-var-hospital: "\f0f8";
@fa-var-hospital-alt: "\f47d";
@fa-var-hospital-symbol: "\f47e";
@fa-var-hospital-user: "\f80d";
@fa-var-hot-tub: "\f593";
@fa-var-hotdog: "\f80f";
@fa-var-hotel: "\f594";
@fa-var-hotjar: "\f3b1";
@fa-var-hourglass: "\f254";
@fa-var-hourglass-end: "\f253";
@fa-var-hourglass-half: "\f252";
@fa-var-hourglass-start: "\f251";
@fa-var-house-damage: "\f6f1";
@fa-var-house-user: "\f965";
@fa-var-houzz: "\f27c";
@fa-var-hryvnia: "\f6f2";
@fa-var-html5: "\f13b";
@fa-var-hubspot: "\f3b2";
@fa-var-i-cursor: "\f246";
@fa-var-ice-cream: "\f810";
@fa-var-icicles: "\f7ad";
@fa-var-icons: "\f86d";
@fa-var-id-badge: "\f2c1";
@fa-var-id-card: "\f2c2";
@fa-var-id-card-alt: "\f47f";
@fa-var-ideal: "\f913";
@fa-var-igloo: "\f7ae";
@fa-var-image: "\f03e";
@fa-var-images: "\f302";
@fa-var-imdb: "\f2d8";
@fa-var-inbox: "\f01c";
@fa-var-indent: "\f03c";
@fa-var-industry: "\f275";
@fa-var-infinity: "\f534";
@fa-var-info: "\f129";
@fa-var-info-circle: "\f05a";
@fa-var-instagram: "\f16d";
@fa-var-instagram-square: "\f955";
@fa-var-intercom: "\f7af";
@fa-var-internet-explorer: "\f26b";
@fa-var-invision: "\f7b0";
@fa-var-ioxhost: "\f208";
@fa-var-italic: "\f033";
@fa-var-itch-io: "\f83a";
@fa-var-itunes: "\f3b4";
@fa-var-itunes-note: "\f3b5";
@fa-var-java: "\f4e4";
@fa-var-jedi: "\f669";
@fa-var-jedi-order: "\f50e";
@fa-var-jenkins: "\f3b6";
@fa-var-jira: "\f7b1";
@fa-var-joget: "\f3b7";
@fa-var-joint: "\f595";
@fa-var-joomla: "\f1aa";
@fa-var-journal-whills: "\f66a";
@fa-var-js: "\f3b8";
@fa-var-js-square: "\f3b9";
@fa-var-jsfiddle: "\f1cc";
@fa-var-kaaba: "\f66b";
@fa-var-kaggle: "\f5fa";
@fa-var-key: "\f084";
@fa-var-keybase: "\f4f5";
@fa-var-keyboard: "\f11c";
@fa-var-keycdn: "\f3ba";
@fa-var-khanda: "\f66d";
@fa-var-kickstarter: "\f3bb";
@fa-var-kickstarter-k: "\f3bc";
@fa-var-kiss: "\f596";
@fa-var-kiss-beam: "\f597";
@fa-var-kiss-wink-heart: "\f598";
@fa-var-kiwi-bird: "\f535";
@fa-var-korvue: "\f42f";
@fa-var-landmark: "\f66f";
@fa-var-language: "\f1ab";
@fa-var-laptop: "\f109";
@fa-var-laptop-code: "\f5fc";
@fa-var-laptop-house: "\f966";
@fa-var-laptop-medical: "\f812";
@fa-var-laravel: "\f3bd";
@fa-var-lastfm: "\f202";
@fa-var-lastfm-square: "\f203";
@fa-var-laugh: "\f599";
@fa-var-laugh-beam: "\f59a";
@fa-var-laugh-squint: "\f59b";
@fa-var-laugh-wink: "\f59c";
@fa-var-layer-group: "\f5fd";
@fa-var-leaf: "\f06c";
@fa-var-leanpub: "\f212";
@fa-var-lemon: "\f094";
@fa-var-less: "\f41d";
@fa-var-less-than: "\f536";
@fa-var-less-than-equal: "\f537";
@fa-var-level-down-alt: "\f3be";
@fa-var-level-up-alt: "\f3bf";
@fa-var-life-ring: "\f1cd";
@fa-var-lightbulb: "\f0eb";
@fa-var-line: "\f3c0";
@fa-var-link: "\f0c1";
@fa-var-linkedin: "\f08c";
@fa-var-linkedin-in: "\f0e1";
@fa-var-linode: "\f2b8";
@fa-var-linux: "\f17c";
@fa-var-lira-sign: "\f195";
@fa-var-list: "\f03a";
@fa-var-list-alt: "\f022";
@fa-var-list-ol: "\f0cb";
@fa-var-list-ul: "\f0ca";
@fa-var-location-arrow: "\f124";
@fa-var-lock: "\f023";
@fa-var-lock-open: "\f3c1";
@fa-var-long-arrow-alt-down: "\f309";
@fa-var-long-arrow-alt-left: "\f30a";
@fa-var-long-arrow-alt-right: "\f30b";
@fa-var-long-arrow-alt-up: "\f30c";
@fa-var-low-vision: "\f2a8";
@fa-var-luggage-cart: "\f59d";
@fa-var-lungs: "\f604";
@fa-var-lungs-virus: "\f967";
@fa-var-lyft: "\f3c3";
@fa-var-magento: "\f3c4";
@fa-var-magic: "\f0d0";
@fa-var-magnet: "\f076";
@fa-var-mail-bulk: "\f674";
@fa-var-mailchimp: "\f59e";
@fa-var-male: "\f183";
@fa-var-mandalorian: "\f50f";
@fa-var-map: "\f279";
@fa-var-map-marked: "\f59f";
@fa-var-map-marked-alt: "\f5a0";
@fa-var-map-marker: "\f041";
@fa-var-map-marker-alt: "\f3c5";
@fa-var-map-pin: "\f276";
@fa-var-map-signs: "\f277";
@fa-var-markdown: "\f60f";
@fa-var-marker: "\f5a1";
@fa-var-mars: "\f222";
@fa-var-mars-double: "\f227";
@fa-var-mars-stroke: "\f229";
@fa-var-mars-stroke-h: "\f22b";
@fa-var-mars-stroke-v: "\f22a";
@fa-var-mask: "\f6fa";
@fa-var-mastodon: "\f4f6";
@fa-var-maxcdn: "\f136";
@fa-var-mdb: "\f8ca";
@fa-var-medal: "\f5a2";
@fa-var-medapps: "\f3c6";
@fa-var-medium: "\f23a";
@fa-var-medium-m: "\f3c7";
@fa-var-medkit: "\f0fa";
@fa-var-medrt: "\f3c8";
@fa-var-meetup: "\f2e0";
@fa-var-megaport: "\f5a3";
@fa-var-meh: "\f11a";
@fa-var-meh-blank: "\f5a4";
@fa-var-meh-rolling-eyes: "\f5a5";
@fa-var-memory: "\f538";
@fa-var-mendeley: "\f7b3";
@fa-var-menorah: "\f676";
@fa-var-mercury: "\f223";
@fa-var-meteor: "\f753";
@fa-var-microblog: "\f91a";
@fa-var-microchip: "\f2db";
@fa-var-microphone: "\f130";
@fa-var-microphone-alt: "\f3c9";
@fa-var-microphone-alt-slash: "\f539";
@fa-var-microphone-slash: "\f131";
@fa-var-microscope: "\f610";
@fa-var-microsoft: "\f3ca";
@fa-var-minus: "\f068";
@fa-var-minus-circle: "\f056";
@fa-var-minus-square: "\f146";
@fa-var-mitten: "\f7b5";
@fa-var-mix: "\f3cb";
@fa-var-mixcloud: "\f289";
@fa-var-mixer: "\f956";
@fa-var-mizuni: "\f3cc";
@fa-var-mobile: "\f10b";
@fa-var-mobile-alt: "\f3cd";
@fa-var-modx: "\f285";
@fa-var-monero: "\f3d0";
@fa-var-money-bill: "\f0d6";
@fa-var-money-bill-alt: "\f3d1";
@fa-var-money-bill-wave: "\f53a";
@fa-var-money-bill-wave-alt: "\f53b";
@fa-var-money-check: "\f53c";
@fa-var-money-check-alt: "\f53d";
@fa-var-monument: "\f5a6";
@fa-var-moon: "\f186";
@fa-var-mortar-pestle: "\f5a7";
@fa-var-mosque: "\f678";
@fa-var-motorcycle: "\f21c";
@fa-var-mountain: "\f6fc";
@fa-var-mouse: "\f8cc";
@fa-var-mouse-pointer: "\f245";
@fa-var-mug-hot: "\f7b6";
@fa-var-music: "\f001";
@fa-var-napster: "\f3d2";
@fa-var-neos: "\f612";
@fa-var-network-wired: "\f6ff";
@fa-var-neuter: "\f22c";
@fa-var-newspaper: "\f1ea";
@fa-var-nimblr: "\f5a8";
@fa-var-node: "\f419";
@fa-var-node-js: "\f3d3";
@fa-var-not-equal: "\f53e";
@fa-var-notes-medical: "\f481";
@fa-var-npm: "\f3d4";
@fa-var-ns8: "\f3d5";
@fa-var-nutritionix: "\f3d6";
@fa-var-object-group: "\f247";
@fa-var-object-ungroup: "\f248";
@fa-var-odnoklassniki: "\f263";
@fa-var-odnoklassniki-square: "\f264";
@fa-var-oil-can: "\f613";
@fa-var-old-republic: "\f510";
@fa-var-om: "\f679";
@fa-var-opencart: "\f23d";
@fa-var-openid: "\f19b";
@fa-var-opera: "\f26a";
@fa-var-optin-monster: "\f23c";
@fa-var-orcid: "\f8d2";
@fa-var-osi: "\f41a";
@fa-var-otter: "\f700";
@fa-var-outdent: "\f03b";
@fa-var-page4: "\f3d7";
@fa-var-pagelines: "\f18c";
@fa-var-pager: "\f815";
@fa-var-paint-brush: "\f1fc";
@fa-var-paint-roller: "\f5aa";
@fa-var-palette: "\f53f";
@fa-var-palfed: "\f3d8";
@fa-var-pallet: "\f482";
@fa-var-paper-plane: "\f1d8";
@fa-var-paperclip: "\f0c6";
@fa-var-parachute-box: "\f4cd";
@fa-var-paragraph: "\f1dd";
@fa-var-parking: "\f540";
@fa-var-passport: "\f5ab";
@fa-var-pastafarianism: "\f67b";
@fa-var-paste: "\f0ea";
@fa-var-patreon: "\f3d9";
@fa-var-pause: "\f04c";
@fa-var-pause-circle: "\f28b";
@fa-var-paw: "\f1b0";
@fa-var-paypal: "\f1ed";
@fa-var-peace: "\f67c";
@fa-var-pen: "\f304";
@fa-var-pen-alt: "\f305";
@fa-var-pen-fancy: "\f5ac";
@fa-var-pen-nib: "\f5ad";
@fa-var-pen-square: "\f14b";
@fa-var-pencil-alt: "\f303";
@fa-var-pencil-ruler: "\f5ae";
@fa-var-penny-arcade: "\f704";
@fa-var-people-arrows: "\f968";
@fa-var-people-carry: "\f4ce";
@fa-var-pepper-hot: "\f816";
@fa-var-percent: "\f295";
@fa-var-percentage: "\f541";
@fa-var-periscope: "\f3da";
@fa-var-person-booth: "\f756";
@fa-var-phabricator: "\f3db";
@fa-var-phoenix-framework: "\f3dc";
@fa-var-phoenix-squadron: "\f511";
@fa-var-phone: "\f095";
@fa-var-phone-alt: "\f879";
@fa-var-phone-slash: "\f3dd";
@fa-var-phone-square: "\f098";
@fa-var-phone-square-alt: "\f87b";
@fa-var-phone-volume: "\f2a0";
@fa-var-photo-video: "\f87c";
@fa-var-php: "\f457";
@fa-var-pied-piper: "\f2ae";
@fa-var-pied-piper-alt: "\f1a8";
@fa-var-pied-piper-hat: "\f4e5";
@fa-var-pied-piper-pp: "\f1a7";
@fa-var-pied-piper-square: "\f91e";
@fa-var-piggy-bank: "\f4d3";
@fa-var-pills: "\f484";
@fa-var-pinterest: "\f0d2";
@fa-var-pinterest-p: "\f231";
@fa-var-pinterest-square: "\f0d3";
@fa-var-pizza-slice: "\f818";
@fa-var-place-of-worship: "\f67f";
@fa-var-plane: "\f072";
@fa-var-plane-arrival: "\f5af";
@fa-var-plane-departure: "\f5b0";
@fa-var-plane-slash: "\f969";
@fa-var-play: "\f04b";
@fa-var-play-circle: "\f144";
@fa-var-playstation: "\f3df";
@fa-var-plug: "\f1e6";
@fa-var-plus: "\f067";
@fa-var-plus-circle: "\f055";
@fa-var-plus-square: "\f0fe";
@fa-var-podcast: "\f2ce";
@fa-var-poll: "\f681";
@fa-var-poll-h: "\f682";
@fa-var-poo: "\f2fe";
@fa-var-poo-storm: "\f75a";
@fa-var-poop: "\f619";
@fa-var-portrait: "\f3e0";
@fa-var-pound-sign: "\f154";
@fa-var-power-off: "\f011";
@fa-var-pray: "\f683";
@fa-var-praying-hands: "\f684";
@fa-var-prescription: "\f5b1";
@fa-var-prescription-bottle: "\f485";
@fa-var-prescription-bottle-alt: "\f486";
@fa-var-print: "\f02f";
@fa-var-procedures: "\f487";
@fa-var-product-hunt: "\f288";
@fa-var-project-diagram: "\f542";
@fa-var-pump-medical: "\f96a";
@fa-var-pump-soap: "\f96b";
@fa-var-pushed: "\f3e1";
@fa-var-puzzle-piece: "\f12e";
@fa-var-python: "\f3e2";
@fa-var-qq: "\f1d6";
@fa-var-qrcode: "\f029";
@fa-var-question: "\f128";
@fa-var-question-circle: "\f059";
@fa-var-quidditch: "\f458";
@fa-var-quinscape: "\f459";
@fa-var-quora: "\f2c4";
@fa-var-quote-left: "\f10d";
@fa-var-quote-right: "\f10e";
@fa-var-quran: "\f687";
@fa-var-r-project: "\f4f7";
@fa-var-radiation: "\f7b9";
@fa-var-radiation-alt: "\f7ba";
@fa-var-rainbow: "\f75b";
@fa-var-random: "\f074";
@fa-var-raspberry-pi: "\f7bb";
@fa-var-ravelry: "\f2d9";
@fa-var-react: "\f41b";
@fa-var-reacteurope: "\f75d";
@fa-var-readme: "\f4d5";
@fa-var-rebel: "\f1d0";
@fa-var-receipt: "\f543";
@fa-var-record-vinyl: "\f8d9";
@fa-var-recycle: "\f1b8";
@fa-var-red-river: "\f3e3";
@fa-var-reddit: "\f1a1";
@fa-var-reddit-alien: "\f281";
@fa-var-reddit-square: "\f1a2";
@fa-var-redhat: "\f7bc";
@fa-var-redo: "\f01e";
@fa-var-redo-alt: "\f2f9";
@fa-var-registered: "\f25d";
@fa-var-remove-format: "\f87d";
@fa-var-renren: "\f18b";
@fa-var-reply: "\f3e5";
@fa-var-reply-all: "\f122";
@fa-var-replyd: "\f3e6";
@fa-var-republican: "\f75e";
@fa-var-researchgate: "\f4f8";
@fa-var-resolving: "\f3e7";
@fa-var-restroom: "\f7bd";
@fa-var-retweet: "\f079";
@fa-var-rev: "\f5b2";
@fa-var-ribbon: "\f4d6";
@fa-var-ring: "\f70b";
@fa-var-road: "\f018";
@fa-var-robot: "\f544";
@fa-var-rocket: "\f135";
@fa-var-rocketchat: "\f3e8";
@fa-var-rockrms: "\f3e9";
@fa-var-route: "\f4d7";
@fa-var-rss: "\f09e";
@fa-var-rss-square: "\f143";
@fa-var-ruble-sign: "\f158";
@fa-var-ruler: "\f545";
@fa-var-ruler-combined: "\f546";
@fa-var-ruler-horizontal: "\f547";
@fa-var-ruler-vertical: "\f548";
@fa-var-running: "\f70c";
@fa-var-rupee-sign: "\f156";
@fa-var-sad-cry: "\f5b3";
@fa-var-sad-tear: "\f5b4";
@fa-var-safari: "\f267";
@fa-var-salesforce: "\f83b";
@fa-var-sass: "\f41e";
@fa-var-satellite: "\f7bf";
@fa-var-satellite-dish: "\f7c0";
@fa-var-save: "\f0c7";
@fa-var-schlix: "\f3ea";
@fa-var-school: "\f549";
@fa-var-screwdriver: "\f54a";
@fa-var-scribd: "\f28a";
@fa-var-scroll: "\f70e";
@fa-var-sd-card: "\f7c2";
@fa-var-search: "\f002";
@fa-var-search-dollar: "\f688";
@fa-var-search-location: "\f689";
@fa-var-search-minus: "\f010";
@fa-var-search-plus: "\f00e";
@fa-var-searchengin: "\f3eb";
@fa-var-seedling: "\f4d8";
@fa-var-sellcast: "\f2da";
@fa-var-sellsy: "\f213";
@fa-var-server: "\f233";
@fa-var-servicestack: "\f3ec";
@fa-var-shapes: "\f61f";
@fa-var-share: "\f064";
@fa-var-share-alt: "\f1e0";
@fa-var-share-alt-square: "\f1e1";
@fa-var-share-square: "\f14d";
@fa-var-shekel-sign: "\f20b";
@fa-var-shield-alt: "\f3ed";
@fa-var-shield-virus: "\f96c";
@fa-var-ship: "\f21a";
@fa-var-shipping-fast: "\f48b";
@fa-var-shirtsinbulk: "\f214";
@fa-var-shoe-prints: "\f54b";
@fa-var-shopify: "\f957";
@fa-var-shopping-bag: "\f290";
@fa-var-shopping-basket: "\f291";
@fa-var-shopping-cart: "\f07a";
@fa-var-shopware: "\f5b5";
@fa-var-shower: "\f2cc";
@fa-var-shuttle-van: "\f5b6";
@fa-var-sign: "\f4d9";
@fa-var-sign-in-alt: "\f2f6";
@fa-var-sign-language: "\f2a7";
@fa-var-sign-out-alt: "\f2f5";
@fa-var-signal: "\f012";
@fa-var-signature: "\f5b7";
@fa-var-sim-card: "\f7c4";
@fa-var-simplybuilt: "\f215";
@fa-var-sistrix: "\f3ee";
@fa-var-sitemap: "\f0e8";
@fa-var-sith: "\f512";
@fa-var-skating: "\f7c5";
@fa-var-sketch: "\f7c6";
@fa-var-skiing: "\f7c9";
@fa-var-skiing-nordic: "\f7ca";
@fa-var-skull: "\f54c";
@fa-var-skull-crossbones: "\f714";
@fa-var-skyatlas: "\f216";
@fa-var-skype: "\f17e";
@fa-var-slack: "\f198";
@fa-var-slack-hash: "\f3ef";
@fa-var-slash: "\f715";
@fa-var-sleigh: "\f7cc";
@fa-var-sliders-h: "\f1de";
@fa-var-slideshare: "\f1e7";
@fa-var-smile: "\f118";
@fa-var-smile-beam: "\f5b8";
@fa-var-smile-wink: "\f4da";
@fa-var-smog: "\f75f";
@fa-var-smoking: "\f48d";
@fa-var-smoking-ban: "\f54d";
@fa-var-sms: "\f7cd";
@fa-var-snapchat: "\f2ab";
@fa-var-snapchat-ghost: "\f2ac";
@fa-var-snapchat-square: "\f2ad";
@fa-var-snowboarding: "\f7ce";
@fa-var-snowflake: "\f2dc";
@fa-var-snowman: "\f7d0";
@fa-var-snowplow: "\f7d2";
@fa-var-soap: "\f96e";
@fa-var-socks: "\f696";
@fa-var-solar-panel: "\f5ba";
@fa-var-sort: "\f0dc";
@fa-var-sort-alpha-down: "\f15d";
@fa-var-sort-alpha-down-alt: "\f881";
@fa-var-sort-alpha-up: "\f15e";
@fa-var-sort-alpha-up-alt: "\f882";
@fa-var-sort-amount-down: "\f160";
@fa-var-sort-amount-down-alt: "\f884";
@fa-var-sort-amount-up: "\f161";
@fa-var-sort-amount-up-alt: "\f885";
@fa-var-sort-down: "\f0dd";
@fa-var-sort-numeric-down: "\f162";
@fa-var-sort-numeric-down-alt: "\f886";
@fa-var-sort-numeric-up: "\f163";
@fa-var-sort-numeric-up-alt: "\f887";
@fa-var-sort-up: "\f0de";
@fa-var-soundcloud: "\f1be";
@fa-var-sourcetree: "\f7d3";
@fa-var-spa: "\f5bb";
@fa-var-space-shuttle: "\f197";
@fa-var-speakap: "\f3f3";
@fa-var-speaker-deck: "\f83c";
@fa-var-spell-check: "\f891";
@fa-var-spider: "\f717";
@fa-var-spinner: "\f110";
@fa-var-splotch: "\f5bc";
@fa-var-spotify: "\f1bc";
@fa-var-spray-can: "\f5bd";
@fa-var-square: "\f0c8";
@fa-var-square-full: "\f45c";
@fa-var-square-root-alt: "\f698";
@fa-var-squarespace: "\f5be";
@fa-var-stack-exchange: "\f18d";
@fa-var-stack-overflow: "\f16c";
@fa-var-stackpath: "\f842";
@fa-var-stamp: "\f5bf";
@fa-var-star: "\f005";
@fa-var-star-and-crescent: "\f699";
@fa-var-star-half: "\f089";
@fa-var-star-half-alt: "\f5c0";
@fa-var-star-of-david: "\f69a";
@fa-var-star-of-life: "\f621";
@fa-var-staylinked: "\f3f5";
@fa-var-steam: "\f1b6";
@fa-var-steam-square: "\f1b7";
@fa-var-steam-symbol: "\f3f6";
@fa-var-step-backward: "\f048";
@fa-var-step-forward: "\f051";
@fa-var-stethoscope: "\f0f1";
@fa-var-sticker-mule: "\f3f7";
@fa-var-sticky-note: "\f249";
@fa-var-stop: "\f04d";
@fa-var-stop-circle: "\f28d";
@fa-var-stopwatch: "\f2f2";
@fa-var-stopwatch-20: "\f96f";
@fa-var-store: "\f54e";
@fa-var-store-alt: "\f54f";
@fa-var-store-alt-slash: "\f970";
@fa-var-store-slash: "\f971";
@fa-var-strava: "\f428";
@fa-var-stream: "\f550";
@fa-var-street-view: "\f21d";
@fa-var-strikethrough: "\f0cc";
@fa-var-stripe: "\f429";
@fa-var-stripe-s: "\f42a";
@fa-var-stroopwafel: "\f551";
@fa-var-studiovinari: "\f3f8";
@fa-var-stumbleupon: "\f1a4";
@fa-var-stumbleupon-circle: "\f1a3";
@fa-var-subscript: "\f12c";
@fa-var-subway: "\f239";
@fa-var-suitcase: "\f0f2";
@fa-var-suitcase-rolling: "\f5c1";
@fa-var-sun: "\f185";
@fa-var-superpowers: "\f2dd";
@fa-var-superscript: "\f12b";
@fa-var-supple: "\f3f9";
@fa-var-surprise: "\f5c2";
@fa-var-suse: "\f7d6";
@fa-var-swatchbook: "\f5c3";
@fa-var-swift: "\f8e1";
@fa-var-swimmer: "\f5c4";
@fa-var-swimming-pool: "\f5c5";
@fa-var-symfony: "\f83d";
@fa-var-synagogue: "\f69b";
@fa-var-sync: "\f021";
@fa-var-sync-alt: "\f2f1";
@fa-var-syringe: "\f48e";
@fa-var-table: "\f0ce";
@fa-var-table-tennis: "\f45d";
@fa-var-tablet: "\f10a";
@fa-var-tablet-alt: "\f3fa";
@fa-var-tablets: "\f490";
@fa-var-tachometer-alt: "\f3fd";
@fa-var-tag: "\f02b";
@fa-var-tags: "\f02c";
@fa-var-tape: "\f4db";
@fa-var-tasks: "\f0ae";
@fa-var-taxi: "\f1ba";
@fa-var-teamspeak: "\f4f9";
@fa-var-teeth: "\f62e";
@fa-var-teeth-open: "\f62f";
@fa-var-telegram: "\f2c6";
@fa-var-telegram-plane: "\f3fe";
@fa-var-temperature-high: "\f769";
@fa-var-temperature-low: "\f76b";
@fa-var-tencent-weibo: "\f1d5";
@fa-var-tenge: "\f7d7";
@fa-var-terminal: "\f120";
@fa-var-text-height: "\f034";
@fa-var-text-width: "\f035";
@fa-var-th: "\f00a";
@fa-var-th-large: "\f009";
@fa-var-th-list: "\f00b";
@fa-var-the-red-yeti: "\f69d";
@fa-var-theater-masks: "\f630";
@fa-var-themeco: "\f5c6";
@fa-var-themeisle: "\f2b2";
@fa-var-thermometer: "\f491";
@fa-var-thermometer-empty: "\f2cb";
@fa-var-thermometer-full: "\f2c7";
@fa-var-thermometer-half: "\f2c9";
@fa-var-thermometer-quarter: "\f2ca";
@fa-var-thermometer-three-quarters: "\f2c8";
@fa-var-think-peaks: "\f731";
@fa-var-thumbs-down: "\f165";
@fa-var-thumbs-up: "\f164";
@fa-var-thumbtack: "\f08d";
@fa-var-ticket-alt: "\f3ff";
@fa-var-times: "\f00d";
@fa-var-times-circle: "\f057";
@fa-var-tint: "\f043";
@fa-var-tint-slash: "\f5c7";
@fa-var-tired: "\f5c8";
@fa-var-toggle-off: "\f204";
@fa-var-toggle-on: "\f205";
@fa-var-toilet: "\f7d8";
@fa-var-toilet-paper: "\f71e";
@fa-var-toilet-paper-slash: "\f972";
@fa-var-toolbox: "\f552";
@fa-var-tools: "\f7d9";
@fa-var-tooth: "\f5c9";
@fa-var-torah: "\f6a0";
@fa-var-torii-gate: "\f6a1";
@fa-var-tractor: "\f722";
@fa-var-trade-federation: "\f513";
@fa-var-trademark: "\f25c";
@fa-var-traffic-light: "\f637";
@fa-var-trailer: "\f941";
@fa-var-train: "\f238";
@fa-var-tram: "\f7da";
@fa-var-transgender: "\f224";
@fa-var-transgender-alt: "\f225";
@fa-var-trash: "\f1f8";
@fa-var-trash-alt: "\f2ed";
@fa-var-trash-restore: "\f829";
@fa-var-trash-restore-alt: "\f82a";
@fa-var-tree: "\f1bb";
@fa-var-trello: "\f181";
@fa-var-tripadvisor: "\f262";
@fa-var-trophy: "\f091";
@fa-var-truck: "\f0d1";
@fa-var-truck-loading: "\f4de";
@fa-var-truck-monster: "\f63b";
@fa-var-truck-moving: "\f4df";
@fa-var-truck-pickup: "\f63c";
@fa-var-tshirt: "\f553";
@fa-var-tty: "\f1e4";
@fa-var-tumblr: "\f173";
@fa-var-tumblr-square: "\f174";
@fa-var-tv: "\f26c";
@fa-var-twitch: "\f1e8";
@fa-var-twitter: "\f099";
@fa-var-twitter-square: "\f081";
@fa-var-typo3: "\f42b";
@fa-var-uber: "\f402";
@fa-var-ubuntu: "\f7df";
@fa-var-uikit: "\f403";
@fa-var-umbraco: "\f8e8";
@fa-var-umbrella: "\f0e9";
@fa-var-umbrella-beach: "\f5ca";
@fa-var-underline: "\f0cd";
@fa-var-undo: "\f0e2";
@fa-var-undo-alt: "\f2ea";
@fa-var-uniregistry: "\f404";
@fa-var-unity: "\f949";
@fa-var-universal-access: "\f29a";
@fa-var-university: "\f19c";
@fa-var-unlink: "\f127";
@fa-var-unlock: "\f09c";
@fa-var-unlock-alt: "\f13e";
@fa-var-untappd: "\f405";
@fa-var-upload: "\f093";
@fa-var-ups: "\f7e0";
@fa-var-usb: "\f287";
@fa-var-user: "\f007";
@fa-var-user-alt: "\f406";
@fa-var-user-alt-slash: "\f4fa";
@fa-var-user-astronaut: "\f4fb";
@fa-var-user-check: "\f4fc";
@fa-var-user-circle: "\f2bd";
@fa-var-user-clock: "\f4fd";
@fa-var-user-cog: "\f4fe";
@fa-var-user-edit: "\f4ff";
@fa-var-user-friends: "\f500";
@fa-var-user-graduate: "\f501";
@fa-var-user-injured: "\f728";
@fa-var-user-lock: "\f502";
@fa-var-user-md: "\f0f0";
@fa-var-user-minus: "\f503";
@fa-var-user-ninja: "\f504";
@fa-var-user-nurse: "\f82f";
@fa-var-user-plus: "\f234";
@fa-var-user-secret: "\f21b";
@fa-var-user-shield: "\f505";
@fa-var-user-slash: "\f506";
@fa-var-user-tag: "\f507";
@fa-var-user-tie: "\f508";
@fa-var-user-times: "\f235";
@fa-var-users: "\f0c0";
@fa-var-users-cog: "\f509";
@fa-var-usps: "\f7e1";
@fa-var-ussunnah: "\f407";
@fa-var-utensil-spoon: "\f2e5";
@fa-var-utensils: "\f2e7";
@fa-var-vaadin: "\f408";
@fa-var-vector-square: "\f5cb";
@fa-var-venus: "\f221";
@fa-var-venus-double: "\f226";
@fa-var-venus-mars: "\f228";
@fa-var-viacoin: "\f237";
@fa-var-viadeo: "\f2a9";
@fa-var-viadeo-square: "\f2aa";
@fa-var-vial: "\f492";
@fa-var-vials: "\f493";
@fa-var-viber: "\f409";
@fa-var-video: "\f03d";
@fa-var-video-slash: "\f4e2";
@fa-var-vihara: "\f6a7";
@fa-var-vimeo: "\f40a";
@fa-var-vimeo-square: "\f194";
@fa-var-vimeo-v: "\f27d";
@fa-var-vine: "\f1ca";
@fa-var-virus: "\f974";
@fa-var-virus-slash: "\f975";
@fa-var-viruses: "\f976";
@fa-var-vk: "\f189";
@fa-var-vnv: "\f40b";
@fa-var-voicemail: "\f897";
@fa-var-volleyball-ball: "\f45f";
@fa-var-volume-down: "\f027";
@fa-var-volume-mute: "\f6a9";
@fa-var-volume-off: "\f026";
@fa-var-volume-up: "\f028";
@fa-var-vote-yea: "\f772";
@fa-var-vr-cardboard: "\f729";
@fa-var-vuejs: "\f41f";
@fa-var-walking: "\f554";
@fa-var-wallet: "\f555";
@fa-var-warehouse: "\f494";
@fa-var-water: "\f773";
@fa-var-wave-square: "\f83e";
@fa-var-waze: "\f83f";
@fa-var-weebly: "\f5cc";
@fa-var-weibo: "\f18a";
@fa-var-weight: "\f496";
@fa-var-weight-hanging: "\f5cd";
@fa-var-weixin: "\f1d7";
@fa-var-whatsapp: "\f232";
@fa-var-whatsapp-square: "\f40c";
@fa-var-wheelchair: "\f193";
@fa-var-whmcs: "\f40d";
@fa-var-wifi: "\f1eb";
@fa-var-wikipedia-w: "\f266";
@fa-var-wind: "\f72e";
@fa-var-window-close: "\f410";
@fa-var-window-maximize: "\f2d0";
@fa-var-window-minimize: "\f2d1";
@fa-var-window-restore: "\f2d2";
@fa-var-windows: "\f17a";
@fa-var-wine-bottle: "\f72f";
@fa-var-wine-glass: "\f4e3";
@fa-var-wine-glass-alt: "\f5ce";
@fa-var-wix: "\f5cf";
@fa-var-wizards-of-the-coast: "\f730";
@fa-var-wolf-pack-battalion: "\f514";
@fa-var-won-sign: "\f159";
@fa-var-wordpress: "\f19a";
@fa-var-wordpress-simple: "\f411";
@fa-var-wpbeginner: "\f297";
@fa-var-wpexplorer: "\f2de";
@fa-var-wpforms: "\f298";
@fa-var-wpressr: "\f3e4";
@fa-var-wrench: "\f0ad";
@fa-var-x-ray: "\f497";
@fa-var-xbox: "\f412";
@fa-var-xing: "\f168";
@fa-var-xing-square: "\f169";
@fa-var-y-combinator: "\f23b";
@fa-var-yahoo: "\f19e";
@fa-var-yammer: "\f840";
@fa-var-yandex: "\f413";
@fa-var-yandex-international: "\f414";
@fa-var-yarn: "\f7e3";
@fa-var-yelp: "\f1e9";
@fa-var-yen-sign: "\f157";
@fa-var-yin-yang: "\f6ad";
@fa-var-yoast: "\f2b1";
@fa-var-youtube: "\f167";
@fa-var-youtube-square: "\f431";
@fa-var-zhihu: "\f63f";
/*!
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
*/
@import "_variables.less";
@font-face {
font-family: 'Font Awesome 5 Brands';
font-style: normal;
font-weight: 400;
font-display: @fa-font-display;
src: url('@{fa-font-path}/fa-brands-400.eot');
src: url('@{fa-font-path}/fa-brands-400.eot?#iefix') format('embedded-opentype'),
url('@{fa-font-path}/fa-brands-400.woff2') format('woff2'),
url('@{fa-font-path}/fa-brands-400.woff') format('woff'),
url('@{fa-font-path}/fa-brands-400.ttf') format('truetype'),
url('@{fa-font-path}/fa-brands-400.svg#fontawesome') format('svg');
}
.fab {
font-family: 'Font Awesome 5 Brands';
font-weight: 400;
}
/*!
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
*/
@import "_variables.less";
@import "_mixins.less";
@import "_core.less";
@import "_larger.less";
@import "_fixed-width.less";
@import "_list.less";
@import "_bordered-pulled.less";
@import "_animated.less";
@import "_rotated-flipped.less";
@import "_stacked.less";
@import "_icons.less";
@import "_screen-reader.less";
/*!
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
*/
@import "_variables.less";
@font-face {
font-family: 'Font Awesome 5 Free';
font-style: normal;
font-weight: 400;
font-display: @fa-font-display;
src: url('@{fa-font-path}/fa-regular-400.eot');
src: url('@{fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'),
url('@{fa-font-path}/fa-regular-400.woff2') format('woff2'),
url('@{fa-font-path}/fa-regular-400.woff') format('woff'),
url('@{fa-font-path}/fa-regular-400.ttf') format('truetype'),
url('@{fa-font-path}/fa-regular-400.svg#fontawesome') format('svg');
}
.far {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
/*!
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
*/
@import "_variables.less";
@font-face {
font-family: 'Font Awesome 5 Free';
font-style: normal;
font-weight: 900;
font-display: @fa-font-display;
src: url('@{fa-font-path}/fa-solid-900.eot');
src: url('@{fa-font-path}/fa-solid-900.eot?#iefix') format('embedded-opentype'),
url('@{fa-font-path}/fa-solid-900.woff2') format('woff2'),
url('@{fa-font-path}/fa-solid-900.woff') format('woff'),
url('@{fa-font-path}/fa-solid-900.ttf') format('truetype'),
url('@{fa-font-path}/fa-solid-900.svg#fontawesome') format('svg');
}
.fa,
.fas {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
}
/*!
* Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
*/
@import '_variables.less';
@import '_shims.less';
/**
* Copyright © Customily. All rights reserved.
*/
.admin__field-group-columns .admin__field-label {
width: auto !important;
label {
position: relative;
}
}
.cl-swatch-color, .sp-replacer {
width: 33px;
height: 33px;
vertical-align: top;
margin-right: 3px;
padding: 0;
border: 2px solid #adadad;
}
.sp-replacer {
.sp-preview {
height: 100% !important;
}
.sp-dd {
padding: 4px 0 !important;
display: block !important;
}
}
.cl-swatch-image {
display: flex;
min-width: 100px;
}
.cl-swatch-image img {
width: 40px;
height: 40px;
cursor: pointer;
}
.cl-swatch-image img:hover {
opacity: 0.8;
}
.cl-swatch-image button {
margin-left: 8px;
}
.cl-hidden {
display: none !important;
}
.cl-display-table-cell {
display: table-cell !important;
}
.cl-position-fixed {
position: fixed !important;
left: -99999px !important;
}
.cl-is_default-checkbox {
position: relative;
}
.customily-options-container {
.customily-row {
display: flex;
margin-bottom: 10px;
label:not(.switch) {
width: 80px;
line-height: 2.2;
}
label.label-position {
width: 120px;
}
input, select {
width: 200px;
height: 35px;
padding: 0 8px;
margin-right: 8px;
}
span:not(.slider) {
margin: 0 6px;
line-height: 2.2;
}
button.delete {
height: 35px;
background-color: #F44336;
box-shadow: 0 1px 0 #C62828;
}
button.delete:hover {
background-color: #ef5350;
}
.delete-function, .delete-condition {
margin: 0 10px !important;
padding: 0 4px;
}
}
}
#customily_extension_plugins-link,
#customily_extension_plugins-head,
#customily_extension_plugins,
#row_customily_general_enable_swatches_unselection,
#row_customily_production_file_export_file,
[data-index="attributes_options"],
[data-index="customily_is_swatch"],
[name="product[attributes_options]"],
[name*="customily_functions"],
[name*="customily_conditions"],
[name*="customily_swatch_settings"],
[name*="customily_index_positions"] {
display: none !important;
}
@media (min-width: 1024px) {
#customily_general_additional_frontend_styles,
#customily_general_additional_frontend_scripts {
width: 550px;
height: 350px;
}
#customily_api_user_api_key {
width: 550px;
}
}
\ No newline at end of file
/**
* Copyright © Customily, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'jquery',
'underscore'
], function ($, _) {
'use strict';
var mixin = {
updateComponents: function(currentValue, isInitialization) {
if (window.customily) {
setTimeout(async function () {
customily.showLoader();
var $target = $(customily.selectedOptionsType);
var $field = $target
? $target.parents('.data-row').find('div[data-role="selected-option"]').first()
: null;
await customily.handleGlobalFields();
await customily.handleSelectableFields();
customily.hideLoader();
}, 0);
}
return this._super(currentValue, isInitialization);
}
};
return function (target) {
return target.extend(mixin);
};
});
\ No newline at end of file
// Spectrum Colorpicker v1.8.0
// https://github.com/bgrins/spectrum
// Author: Brian Grinstead
// License: MIT
(function (factory) {
"use strict";
if (typeof define === 'function' && define.amd) { // AMD
define(['jquery'], factory);
}
else if (typeof exports == "object" && typeof module == "object") { // CommonJS
module.exports = factory(require('jquery'));
}
else { // Browser
factory(jQuery);
}
})(function($, undefined) {
"use strict";
var defaultOpts = {
// Callbacks
beforeShow: noop,
move: noop,
change: noop,
show: noop,
hide: noop,
// Options
color: false,
flat: false,
showInput: false,
allowEmpty: false,
showButtons: true,
clickoutFiresChange: true,
showInitial: false,
showPalette: false,
showPaletteOnly: false,
hideAfterPaletteSelect: false,
togglePaletteOnly: false,
showSelectionPalette: true,
localStorageKey: false,
appendTo: "body",
maxSelectionSize: 7,
cancelText: "cancel",
chooseText: "choose",
togglePaletteMoreText: "more",
togglePaletteLessText: "less",
clearText: "Clear Color Selection",
noColorSelectedText: "No Color Selected",
preferredFormat: false,
className: "", // Deprecated - use containerClassName and replacerClassName instead.
containerClassName: "",
replacerClassName: "",
showAlpha: false,
theme: "sp-light",
palette: [["#ffffff", "#000000", "#ff0000", "#ff8000", "#ffff00", "#008000", "#0000ff", "#4b0082", "#9400d3"]],
selectionPalette: [],
disabled: false,
offset: null
},
spectrums = [],
IE = !!/msie/i.exec( window.navigator.userAgent ),
rgbaSupport = (function() {
function contains( str, substr ) {
return !!~('' + str).indexOf(substr);
}
var elem = document.createElement('div');
var style = elem.style;
style.cssText = 'background-color:rgba(0,0,0,.5)';
return contains(style.backgroundColor, 'rgba') || contains(style.backgroundColor, 'hsla');
})(),
replaceInput = [
"<div class='sp-replacer'>",
"<div class='sp-preview'><div class='sp-preview-inner'></div></div>",
"<div class='sp-dd'>&#9660;</div>",
"</div>"
].join(''),
markup = (function () {
// IE does not support gradients with multiple stops, so we need to simulate
// that for the rainbow slider with 8 divs that each have a single gradient
var gradientFix = "";
if (IE) {
for (var i = 1; i <= 6; i++) {
gradientFix += "<div class='sp-" + i + "'></div>";
}
}
return [
"<div class='sp-container sp-hidden'>",
"<div class='sp-palette-container'>",
"<div class='sp-palette sp-thumb sp-cf'></div>",
"<div class='sp-palette-button-container sp-cf'>",
"<button type='button' class='sp-palette-toggle'></button>",
"</div>",
"</div>",
"<div class='sp-picker-container'>",
"<div class='sp-top sp-cf'>",
"<div class='sp-fill'></div>",
"<div class='sp-top-inner'>",
"<div class='sp-color'>",
"<div class='sp-sat'>",
"<div class='sp-val'>",
"<div class='sp-dragger'></div>",
"</div>",
"</div>",
"</div>",
"<div class='sp-clear sp-clear-display'>",
"</div>",
"<div class='sp-hue'>",
"<div class='sp-slider'></div>",
gradientFix,
"</div>",
"</div>",
"<div class='sp-alpha'><div class='sp-alpha-inner'><div class='sp-alpha-handle'></div></div></div>",
"</div>",
"<div class='sp-input-container sp-cf'>",
"<input class='sp-input' type='text' spellcheck='false' />",
"</div>",
"<div class='sp-initial sp-thumb sp-cf'></div>",
"<div class='sp-button-container sp-cf'>",
"<a class='sp-cancel' href='#'></a>",
"<button type='button' class='sp-choose'></button>",
"</div>",
"</div>",
"</div>"
].join("");
})();
function paletteTemplate (p, color, className, opts) {
var html = [];
for (var i = 0; i < p.length; i++) {
var current = p[i];
if(current) {
var tiny = tinycolor(current);
var c = tiny.toHsl().l < 0.5 ? "sp-thumb-el sp-thumb-dark" : "sp-thumb-el sp-thumb-light";
c += (tinycolor.equals(color, current)) ? " sp-thumb-active" : "";
var formattedString = tiny.toString(opts.preferredFormat || "rgb");
var swatchStyle = rgbaSupport ? ("background-color:" + tiny.toRgbString()) : "filter:" + tiny.toFilter();
html.push('<span title="' + formattedString + '" data-color="' + tiny.toRgbString() + '" class="' + c + '"><span class="sp-thumb-inner" style="' + swatchStyle + ';" /></span>');
} else {
var cls = 'sp-clear-display';
html.push($('<div />')
.append($('<span data-color="" style="background-color:transparent;" class="' + cls + '"></span>')
.attr('title', opts.noColorSelectedText)
)
.html()
);
}
}
return "<div class='sp-cf " + className + "'>" + html.join('') + "</div>";
}
function hideAll() {
for (var i = 0; i < spectrums.length; i++) {
if (spectrums[i]) {
spectrums[i].hide();
}
}
}
function instanceOptions(o, callbackContext) {
var opts = $.extend({}, defaultOpts, o);
opts.callbacks = {
'move': bind(opts.move, callbackContext),
'change': bind(opts.change, callbackContext),
'show': bind(opts.show, callbackContext),
'hide': bind(opts.hide, callbackContext),
'beforeShow': bind(opts.beforeShow, callbackContext)
};
return opts;
}
function spectrum(element, o) {
var opts = instanceOptions(o, element),
flat = opts.flat,
showSelectionPalette = opts.showSelectionPalette,
localStorageKey = opts.localStorageKey,
theme = opts.theme,
callbacks = opts.callbacks,
resize = throttle(reflow, 10),
visible = false,
isDragging = false,
dragWidth = 0,
dragHeight = 0,
dragHelperHeight = 0,
slideHeight = 0,
slideWidth = 0,
alphaWidth = 0,
alphaSlideHelperWidth = 0,
slideHelperHeight = 0,
currentHue = 0,
currentSaturation = 0,
currentValue = 0,
currentAlpha = 1,
palette = [],
paletteArray = [],
paletteLookup = {},
selectionPalette = opts.selectionPalette.slice(0),
maxSelectionSize = opts.maxSelectionSize,
draggingClass = "sp-dragging",
shiftMovementDirection = null;
var doc = element.ownerDocument,
body = doc.body,
boundElement = $(element),
disabled = false,
container = $(markup, doc).addClass(theme),
pickerContainer = container.find(".sp-picker-container"),
dragger = container.find(".sp-color"),
dragHelper = container.find(".sp-dragger"),
slider = container.find(".sp-hue"),
slideHelper = container.find(".sp-slider"),
alphaSliderInner = container.find(".sp-alpha-inner"),
alphaSlider = container.find(".sp-alpha"),
alphaSlideHelper = container.find(".sp-alpha-handle"),
textInput = container.find(".sp-input"),
paletteContainer = container.find(".sp-palette"),
initialColorContainer = container.find(".sp-initial"),
cancelButton = container.find(".sp-cancel"),
clearButton = container.find(".sp-clear"),
chooseButton = container.find(".sp-choose"),
toggleButton = container.find(".sp-palette-toggle"),
isInput = boundElement.is("input"),
isInputTypeColor = isInput && boundElement.attr("type") === "color" && inputTypeColorSupport(),
shouldReplace = isInput && !flat,
replacer = (shouldReplace) ? $(replaceInput).addClass(theme).addClass(opts.className).addClass(opts.replacerClassName) : $([]),
offsetElement = (shouldReplace) ? replacer : boundElement,
previewElement = replacer.find(".sp-preview-inner"),
initialColor = opts.color || (isInput && boundElement.val()),
colorOnShow = false,
currentPreferredFormat = opts.preferredFormat,
clickoutFiresChange = !opts.showButtons || opts.clickoutFiresChange,
isEmpty = !initialColor,
allowEmpty = opts.allowEmpty && !isInputTypeColor;
function applyOptions() {
if (opts.showPaletteOnly) {
opts.showPalette = true;
}
toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
if (opts.palette) {
palette = opts.palette.slice(0);
paletteArray = $.isArray(palette[0]) ? palette : [palette];
paletteLookup = {};
for (var i = 0; i < paletteArray.length; i++) {
for (var j = 0; j < paletteArray[i].length; j++) {
var rgb = tinycolor(paletteArray[i][j]).toRgbString();
paletteLookup[rgb] = true;
}
}
}
container.toggleClass("sp-flat", flat);
container.toggleClass("sp-input-disabled", !opts.showInput);
container.toggleClass("sp-alpha-enabled", opts.showAlpha);
container.toggleClass("sp-clear-enabled", allowEmpty);
container.toggleClass("sp-buttons-disabled", !opts.showButtons);
container.toggleClass("sp-palette-buttons-disabled", !opts.togglePaletteOnly);
container.toggleClass("sp-palette-disabled", !opts.showPalette);
container.toggleClass("sp-palette-only", opts.showPaletteOnly);
container.toggleClass("sp-initial-disabled", !opts.showInitial);
container.addClass(opts.className).addClass(opts.containerClassName);
reflow();
}
function initialize() {
if (IE) {
container.find("*:not(input)").attr("unselectable", "on");
}
applyOptions();
if (shouldReplace) {
boundElement.after(replacer).hide();
}
if (!allowEmpty) {
clearButton.hide();
}
if (flat) {
boundElement.after(container).hide();
}
else {
var appendTo = opts.appendTo === "parent" ? boundElement.parent() : $(opts.appendTo);
if (appendTo.length !== 1) {
appendTo = $("body");
}
appendTo.append(container);
}
updateSelectionPaletteFromStorage();
offsetElement.bind("click.spectrum touchstart.spectrum", function (e) {
if (!disabled) {
toggle();
}
e.stopPropagation();
if (!$(e.target).is("input")) {
e.preventDefault();
}
});
if(boundElement.is(":disabled") || (opts.disabled === true)) {
disable();
}
// Prevent clicks from bubbling up to document. This would cause it to be hidden.
container.click(stopPropagation);
// Handle user typed input
textInput.change(setFromTextInput);
textInput.bind("paste", function () {
setTimeout(setFromTextInput, 1);
});
textInput.keydown(function (e) { if (e.keyCode == 13) { setFromTextInput(); } });
cancelButton.text(opts.cancelText);
cancelButton.bind("click.spectrum", function (e) {
e.stopPropagation();
e.preventDefault();
revert();
hide();
});
clearButton.attr("title", opts.clearText);
clearButton.bind("click.spectrum", function (e) {
e.stopPropagation();
e.preventDefault();
isEmpty = true;
move();
if(flat) {
//for the flat style, this is a change event
updateOriginalInput(true);
}
});
chooseButton.text(opts.chooseText);
chooseButton.bind("click.spectrum", function (e) {
e.stopPropagation();
e.preventDefault();
if (IE && textInput.is(":focus")) {
textInput.trigger('change');
}
if (isValid()) {
updateOriginalInput(true);
hide();
}
});
toggleButton.text(opts.showPaletteOnly ? opts.togglePaletteMoreText : opts.togglePaletteLessText);
toggleButton.bind("click.spectrum", function (e) {
e.stopPropagation();
e.preventDefault();
opts.showPaletteOnly = !opts.showPaletteOnly;
// To make sure the Picker area is drawn on the right, next to the
// Palette area (and not below the palette), first move the Palette
// to the left to make space for the picker, plus 5px extra.
// The 'applyOptions' function puts the whole container back into place
// and takes care of the button-text and the sp-palette-only CSS class.
if (!opts.showPaletteOnly && !flat) {
container.css('left', '-=' + (pickerContainer.outerWidth(true) + 5));
}
applyOptions();
});
draggable(alphaSlider, function (dragX, dragY, e) {
currentAlpha = (dragX / alphaWidth);
isEmpty = false;
if (e.shiftKey) {
currentAlpha = Math.round(currentAlpha * 10) / 10;
}
move();
}, dragStart, dragStop);
draggable(slider, function (dragX, dragY) {
currentHue = parseFloat(dragY / slideHeight);
isEmpty = false;
if (!opts.showAlpha) {
currentAlpha = 1;
}
move();
}, dragStart, dragStop);
draggable(dragger, function (dragX, dragY, e) {
// shift+drag should snap the movement to either the x or y axis.
if (!e.shiftKey) {
shiftMovementDirection = null;
}
else if (!shiftMovementDirection) {
var oldDragX = currentSaturation * dragWidth;
var oldDragY = dragHeight - (currentValue * dragHeight);
var furtherFromX = Math.abs(dragX - oldDragX) > Math.abs(dragY - oldDragY);
shiftMovementDirection = furtherFromX ? "x" : "y";
}
var setSaturation = !shiftMovementDirection || shiftMovementDirection === "x";
var setValue = !shiftMovementDirection || shiftMovementDirection === "y";
if (setSaturation) {
currentSaturation = parseFloat(dragX / dragWidth);
}
if (setValue) {
currentValue = parseFloat((dragHeight - dragY) / dragHeight);
}
isEmpty = false;
if (!opts.showAlpha) {
currentAlpha = 1;
}
move();
}, dragStart, dragStop);
if (!!initialColor) {
set(initialColor);
// In case color was black - update the preview UI and set the format
// since the set function will not run (default color is black).
updateUI();
currentPreferredFormat = opts.preferredFormat || tinycolor(initialColor).format;
addColorToSelectionPalette(initialColor);
}
else {
updateUI();
}
if (flat) {
show();
}
function paletteElementClick(e) {
if (e.data && e.data.ignore) {
set($(e.target).closest(".sp-thumb-el").data("color"));
move();
}
else {
set($(e.target).closest(".sp-thumb-el").data("color"));
move();
updateOriginalInput(true);
if (opts.hideAfterPaletteSelect) {
hide();
}
}
return false;
}
var paletteEvent = IE ? "mousedown.spectrum" : "click.spectrum touchstart.spectrum";
paletteContainer.delegate(".sp-thumb-el", paletteEvent, paletteElementClick);
initialColorContainer.delegate(".sp-thumb-el:nth-child(1)", paletteEvent, { ignore: true }, paletteElementClick);
}
function updateSelectionPaletteFromStorage() {
if (localStorageKey && window.localStorage) {
// Migrate old palettes over to new format. May want to remove this eventually.
try {
var oldPalette = window.localStorage[localStorageKey].split(",#");
if (oldPalette.length > 1) {
delete window.localStorage[localStorageKey];
$.each(oldPalette, function(i, c) {
addColorToSelectionPalette(c);
});
}
}
catch(e) { }
try {
selectionPalette = window.localStorage[localStorageKey].split(";");
}
catch (e) { }
}
}
function addColorToSelectionPalette(color) {
if (showSelectionPalette) {
var rgb = tinycolor(color).toRgbString();
if (!paletteLookup[rgb] && $.inArray(rgb, selectionPalette) === -1) {
selectionPalette.push(rgb);
while(selectionPalette.length > maxSelectionSize) {
selectionPalette.shift();
}
}
if (localStorageKey && window.localStorage) {
try {
window.localStorage[localStorageKey] = selectionPalette.join(";");
}
catch(e) { }
}
}
}
function getUniqueSelectionPalette() {
var unique = [];
if (opts.showPalette) {
for (var i = 0; i < selectionPalette.length; i++) {
var rgb = tinycolor(selectionPalette[i]).toRgbString();
if (!paletteLookup[rgb]) {
unique.push(selectionPalette[i]);
}
}
}
return unique.reverse().slice(0, opts.maxSelectionSize);
}
function drawPalette() {
var currentColor = get();
var html = $.map(paletteArray, function (palette, i) {
return paletteTemplate(palette, currentColor, "sp-palette-row sp-palette-row-" + i, opts);
});
updateSelectionPaletteFromStorage();
if (selectionPalette) {
html.push(paletteTemplate(getUniqueSelectionPalette(), currentColor, "sp-palette-row sp-palette-row-selection", opts));
}
paletteContainer.html(html.join(""));
}
function drawInitial() {
if (opts.showInitial) {
var initial = colorOnShow;
var current = get();
initialColorContainer.html(paletteTemplate([initial, current], current, "sp-palette-row-initial", opts));
}
}
function dragStart() {
if (dragHeight <= 0 || dragWidth <= 0 || slideHeight <= 0) {
reflow();
}
isDragging = true;
container.addClass(draggingClass);
shiftMovementDirection = null;
boundElement.trigger('dragstart.spectrum', [ get() ]);
}
function dragStop() {
isDragging = false;
container.removeClass(draggingClass);
boundElement.trigger('dragstop.spectrum', [ get() ]);
}
function setFromTextInput() {
var value = textInput.val();
if ((value === null || value === "") && allowEmpty) {
set(null);
updateOriginalInput(true);
}
else {
var tiny = tinycolor(value);
if (tiny.isValid()) {
set(tiny);
updateOriginalInput(true);
}
else {
textInput.addClass("sp-validation-error");
}
}
}
function toggle() {
if (visible) {
hide();
}
else {
show();
}
}
function show() {
var event = $.Event('beforeShow.spectrum');
if (visible) {
reflow();
return;
}
boundElement.trigger(event, [ get() ]);
if (callbacks.beforeShow(get()) === false || event.isDefaultPrevented()) {
return;
}
hideAll();
visible = true;
$(doc).bind("keydown.spectrum", onkeydown);
$(doc).bind("click.spectrum", clickout);
$(window).bind("resize.spectrum", resize);
replacer.addClass("sp-active");
container.removeClass("sp-hidden");
reflow();
updateUI();
colorOnShow = get();
drawInitial();
callbacks.show(colorOnShow);
boundElement.trigger('show.spectrum', [ colorOnShow ]);
}
function onkeydown(e) {
// Close on ESC
if (e.keyCode === 27) {
hide();
}
}
function clickout(e) {
// Return on right click.
if (e.button == 2) { return; }
// If a drag event was happening during the mouseup, don't hide
// on click.
if (isDragging) { return; }
if (clickoutFiresChange) {
updateOriginalInput(true);
}
else {
revert();
}
hide();
}
function hide() {
// Return if hiding is unnecessary
if (!visible || flat) { return; }
visible = false;
$(doc).unbind("keydown.spectrum", onkeydown);
$(doc).unbind("click.spectrum", clickout);
$(window).unbind("resize.spectrum", resize);
replacer.removeClass("sp-active");
container.addClass("sp-hidden");
callbacks.hide(get());
boundElement.trigger('hide.spectrum', [ get() ]);
}
function revert() {
set(colorOnShow, true);
}
function set(color, ignoreFormatChange) {
if (tinycolor.equals(color, get())) {
// Update UI just in case a validation error needs
// to be cleared.
updateUI();
return;
}
var newColor, newHsv;
if (!color && allowEmpty) {
isEmpty = true;
} else {
isEmpty = false;
newColor = tinycolor(color);
newHsv = newColor.toHsv();
currentHue = (newHsv.h % 360) / 360;
currentSaturation = newHsv.s;
currentValue = newHsv.v;
currentAlpha = newHsv.a;
}
updateUI();
if (newColor && newColor.isValid() && !ignoreFormatChange) {
currentPreferredFormat = opts.preferredFormat || newColor.getFormat();
}
}
function get(opts) {
opts = opts || { };
if (allowEmpty && isEmpty) {
return null;
}
return tinycolor.fromRatio({
h: currentHue,
s: currentSaturation,
v: currentValue,
a: Math.round(currentAlpha * 100) / 100
}, { format: opts.format || currentPreferredFormat });
}
function isValid() {
return !textInput.hasClass("sp-validation-error");
}
function move() {
updateUI();
callbacks.move(get());
boundElement.trigger('move.spectrum', [ get() ]);
}
function updateUI() {
textInput.removeClass("sp-validation-error");
updateHelperLocations();
// Update dragger background color (gradients take care of saturation and value).
var flatColor = tinycolor.fromRatio({ h: currentHue, s: 1, v: 1 });
dragger.css("background-color", flatColor.toHexString());
// Get a format that alpha will be included in (hex and names ignore alpha)
var format = currentPreferredFormat;
if (currentAlpha < 1 && !(currentAlpha === 0 && format === "name")) {
if (format === "hex" || format === "hex3" || format === "hex6" || format === "name") {
format = "rgb";
}
}
var realColor = get({ format: format }),
displayColor = '';
//reset background info for preview element
previewElement.removeClass("sp-clear-display");
previewElement.css('background-color', 'transparent');
if (!realColor && allowEmpty) {
// Update the replaced elements background with icon indicating no color selection
previewElement.addClass("sp-clear-display");
}
else {
var realHex = realColor.toHexString(),
realRgb = realColor.toRgbString();
// Update the replaced elements background color (with actual selected color)
if (rgbaSupport || realColor.alpha === 1) {
previewElement.css("background-color", realRgb);
}
else {
previewElement.css("background-color", "transparent");
previewElement.css("filter", realColor.toFilter());
}
if (opts.showAlpha) {
var rgb = realColor.toRgb();
rgb.a = 0;
var realAlpha = tinycolor(rgb).toRgbString();
var gradient = "linear-gradient(left, " + realAlpha + ", " + realHex + ")";
if (IE) {
alphaSliderInner.css("filter", tinycolor(realAlpha).toFilter({ gradientType: 1 }, realHex));
}
else {
alphaSliderInner.css("background", "-webkit-" + gradient);
alphaSliderInner.css("background", "-moz-" + gradient);
alphaSliderInner.css("background", "-ms-" + gradient);
// Use current syntax gradient on unprefixed property.
alphaSliderInner.css("background",
"linear-gradient(to right, " + realAlpha + ", " + realHex + ")");
}
}
displayColor = realColor.toString(format);
}
// Update the text entry input as it changes happen
if (opts.showInput) {
textInput.val(displayColor);
}
if (opts.showPalette) {
drawPalette();
}
drawInitial();
}
function updateHelperLocations() {
var s = currentSaturation;
var v = currentValue;
if(allowEmpty && isEmpty) {
//if selected color is empty, hide the helpers
alphaSlideHelper.hide();
slideHelper.hide();
dragHelper.hide();
}
else {
//make sure helpers are visible
alphaSlideHelper.show();
slideHelper.show();
dragHelper.show();
// Where to show the little circle in that displays your current selected color
var dragX = s * dragWidth;
var dragY = dragHeight - (v * dragHeight);
dragX = Math.max(
-dragHelperHeight,
Math.min(dragWidth - dragHelperHeight, dragX - dragHelperHeight)
);
dragY = Math.max(
-dragHelperHeight,
Math.min(dragHeight - dragHelperHeight, dragY - dragHelperHeight)
);
dragHelper.css({
"top": dragY + "px",
"left": dragX + "px"
});
var alphaX = currentAlpha * alphaWidth;
alphaSlideHelper.css({
"left": (alphaX - (alphaSlideHelperWidth / 2)) + "px"
});
// Where to show the bar that displays your current selected hue
var slideY = (currentHue) * slideHeight;
slideHelper.css({
"top": (slideY - slideHelperHeight) + "px"
});
}
}
function updateOriginalInput(fireCallback) {
var color = get(),
displayColor = '',
hasChanged = !tinycolor.equals(color, colorOnShow);
if (color) {
displayColor = color.toString(currentPreferredFormat);
// Update the selection palette with the current color
addColorToSelectionPalette(color);
}
if (isInput) {
boundElement.val(displayColor);
}
if (fireCallback && hasChanged) {
callbacks.change(color);
boundElement.trigger('change', [ color ]);
}
}
function reflow() {
if (!visible) {
return; // Calculations would be useless and wouldn't be reliable anyways
}
dragWidth = dragger.width();
dragHeight = dragger.height();
dragHelperHeight = dragHelper.height();
slideWidth = slider.width();
slideHeight = slider.height();
slideHelperHeight = slideHelper.height();
alphaWidth = alphaSlider.width();
alphaSlideHelperWidth = alphaSlideHelper.width();
if (!flat) {
container.css("position", "absolute");
if (opts.offset) {
container.offset(opts.offset);
} else {
container.offset(getOffset(container, offsetElement));
}
}
updateHelperLocations();
if (opts.showPalette) {
drawPalette();
}
boundElement.trigger('reflow.spectrum');
}
function destroy() {
boundElement.show();
offsetElement.unbind("click.spectrum touchstart.spectrum");
container.remove();
replacer.remove();
spectrums[spect.id] = null;
}
function option(optionName, optionValue) {
if (optionName === undefined) {
return $.extend({}, opts);
}
if (optionValue === undefined) {
return opts[optionName];
}
opts[optionName] = optionValue;
if (optionName === "preferredFormat") {
currentPreferredFormat = opts.preferredFormat;
}
applyOptions();
}
function enable() {
disabled = false;
boundElement.attr("disabled", false);
offsetElement.removeClass("sp-disabled");
}
function disable() {
hide();
disabled = true;
boundElement.attr("disabled", true);
offsetElement.addClass("sp-disabled");
}
function setOffset(coord) {
opts.offset = coord;
reflow();
}
initialize();
var spect = {
show: show,
hide: hide,
toggle: toggle,
reflow: reflow,
option: option,
enable: enable,
disable: disable,
offset: setOffset,
set: function (c) {
set(c);
updateOriginalInput();
},
get: get,
destroy: destroy,
container: container
};
spect.id = spectrums.push(spect) - 1;
return spect;
}
/**
* checkOffset - get the offset below/above and left/right element depending on screen position
* Thanks https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
*/
function getOffset(picker, input) {
var extraY = 0;
var dpWidth = picker.outerWidth();
var dpHeight = picker.outerHeight();
var inputHeight = input.outerHeight();
var doc = picker[0].ownerDocument;
var docElem = doc.documentElement;
var viewWidth = docElem.clientWidth + $(doc).scrollLeft();
var viewHeight = docElem.clientHeight + $(doc).scrollTop();
var offset = input.offset();
offset.top += inputHeight;
offset.left -=
Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
Math.abs(offset.left + dpWidth - viewWidth) : 0);
offset.top -=
Math.min(offset.top, ((offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
Math.abs(dpHeight + inputHeight - extraY) : extraY));
return offset;
}
/**
* noop - do nothing
*/
function noop() {
}
/**
* stopPropagation - makes the code only doing this a little easier to read in line
*/
function stopPropagation(e) {
e.stopPropagation();
}
/**
* Create a function bound to a given object
* Thanks to underscore.js
*/
function bind(func, obj) {
var slice = Array.prototype.slice;
var args = slice.call(arguments, 2);
return function () {
return func.apply(obj, args.concat(slice.call(arguments)));
};
}
/**
* Lightweight drag helper. Handles containment within the element, so that
* when dragging, the x is within [0,element.width] and y is within [0,element.height]
*/
function draggable(element, onmove, onstart, onstop) {
onmove = onmove || function () { };
onstart = onstart || function () { };
onstop = onstop || function () { };
var doc = document;
var dragging = false;
var offset = {};
var maxHeight = 0;
var maxWidth = 0;
var hasTouch = ('ontouchstart' in window);
var duringDragEvents = {};
duringDragEvents["selectstart"] = prevent;
duringDragEvents["dragstart"] = prevent;
duringDragEvents["touchmove mousemove"] = move;
duringDragEvents["touchend mouseup"] = stop;
function prevent(e) {
if (e.stopPropagation) {
e.stopPropagation();
}
if (e.preventDefault) {
e.preventDefault();
}
e.returnValue = false;
}
function move(e) {
if (dragging) {
// Mouseup happened outside of window
if (IE && doc.documentMode < 9 && !e.button) {
return stop();
}
var t0 = e.originalEvent && e.originalEvent.touches && e.originalEvent.touches[0];
var pageX = t0 && t0.pageX || e.pageX;
var pageY = t0 && t0.pageY || e.pageY;
var dragX = Math.max(0, Math.min(pageX - offset.left, maxWidth));
var dragY = Math.max(0, Math.min(pageY - offset.top, maxHeight));
if (hasTouch) {
// Stop scrolling in iOS
prevent(e);
}
onmove.apply(element, [dragX, dragY, e]);
}
}
function start(e) {
var rightclick = (e.which) ? (e.which == 3) : (e.button == 2);
if (!rightclick && !dragging) {
if (onstart.apply(element, arguments) !== false) {
dragging = true;
maxHeight = $(element).height();
maxWidth = $(element).width();
offset = $(element).offset();
$(doc).bind(duringDragEvents);
$(doc.body).addClass("sp-dragging");
move(e);
prevent(e);
}
}
}
function stop() {
if (dragging) {
$(doc).unbind(duringDragEvents);
$(doc.body).removeClass("sp-dragging");
// Wait a tick before notifying observers to allow the click event
// to fire in Chrome.
setTimeout(function() {
onstop.apply(element, arguments);
}, 0);
}
dragging = false;
}
$(element).bind("touchstart mousedown", start);
}
function throttle(func, wait, debounce) {
var timeout;
return function () {
var context = this, args = arguments;
var throttler = function () {
timeout = null;
func.apply(context, args);
};
if (debounce) clearTimeout(timeout);
if (debounce || !timeout) timeout = setTimeout(throttler, wait);
};
}
function inputTypeColorSupport() {
return $.fn.spectrum.inputTypeColorSupport();
}
/**
* Define a jQuery plugin
*/
var dataID = "spectrum.id";
$.fn.spectrum = function (opts, extra) {
if (typeof opts == "string") {
var returnValue = this;
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function () {
var spect = spectrums[$(this).data(dataID)];
if (spect) {
var method = spect[opts];
if (!method) {
throw new Error( "Spectrum: no such method: '" + opts + "'" );
}
if (opts == "get") {
returnValue = spect.get();
}
else if (opts == "container") {
returnValue = spect.container;
}
else if (opts == "option") {
returnValue = spect.option.apply(spect, args);
}
else if (opts == "destroy") {
spect.destroy();
$(this).removeData(dataID);
}
else {
method.apply(spect, args);
}
}
});
return returnValue;
}
// Initializing a new instance of spectrum
return this.spectrum("destroy").each(function () {
var options = $.extend({}, opts, $(this).data());
var spect = spectrum(this, options);
$(this).data(dataID, spect.id);
});
};
$.fn.spectrum.load = true;
$.fn.spectrum.loadOpts = {};
$.fn.spectrum.draggable = draggable;
$.fn.spectrum.defaults = defaultOpts;
$.fn.spectrum.inputTypeColorSupport = function inputTypeColorSupport() {
if (typeof inputTypeColorSupport._cachedResult === "undefined") {
var colorInput = $("<input type='color'/>")[0]; // if color element is supported, value will default to not null
inputTypeColorSupport._cachedResult = colorInput.type === "color" && colorInput.value !== "";
}
return inputTypeColorSupport._cachedResult;
};
$.spectrum = { };
$.spectrum.localization = { };
$.spectrum.palettes = { };
$.fn.spectrum.processNativeColorInputs = function () {
var colorInputs = $("input[type=color]");
if (colorInputs.length && !inputTypeColorSupport()) {
colorInputs.spectrum({
preferredFormat: "hex6"
});
}
};
// TinyColor v1.1.2
// https://github.com/bgrins/TinyColor
// Brian Grinstead, MIT License
(function() {
var trimLeft = /^[\s,#]+/,
trimRight = /\s+$/,
tinyCounter = 0,
math = Math,
mathRound = math.round,
mathMin = math.min,
mathMax = math.max,
mathRandom = math.random;
var tinycolor = function(color, opts) {
color = (color) ? color : '';
opts = opts || { };
// If input is already a tinycolor, return itself
if (color instanceof tinycolor) {
return color;
}
// If we are called as a function, call using new instead
if (!(this instanceof tinycolor)) {
return new tinycolor(color, opts);
}
var rgb = inputToRGB(color);
this._originalInput = color,
this._r = rgb.r,
this._g = rgb.g,
this._b = rgb.b,
this._a = rgb.a,
this._roundA = mathRound(100*this._a) / 100,
this._format = opts.format || rgb.format;
this._gradientType = opts.gradientType;
// Don't let the range of [0,255] come back in [0,1].
// Potentially lose a little bit of precision here, but will fix issues where
// .5 gets interpreted as half of the total, instead of half of 1
// If it was supposed to be 128, this was already taken care of by `inputToRgb`
if (this._r < 1) { this._r = mathRound(this._r); }
if (this._g < 1) { this._g = mathRound(this._g); }
if (this._b < 1) { this._b = mathRound(this._b); }
this._ok = rgb.ok;
this._tc_id = tinyCounter++;
};
tinycolor.prototype = {
isDark: function() {
return this.getBrightness() < 128;
},
isLight: function() {
return !this.isDark();
},
isValid: function() {
return this._ok;
},
getOriginalInput: function() {
return this._originalInput;
},
getFormat: function() {
return this._format;
},
getAlpha: function() {
return this._a;
},
getBrightness: function() {
var rgb = this.toRgb();
return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
},
setAlpha: function(value) {
this._a = boundAlpha(value);
this._roundA = mathRound(100*this._a) / 100;
return this;
},
toHsv: function() {
var hsv = rgbToHsv(this._r, this._g, this._b);
return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a };
},
toHsvString: function() {
var hsv = rgbToHsv(this._r, this._g, this._b);
var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100);
return (this._a == 1) ?
"hsv(" + h + ", " + s + "%, " + v + "%)" :
"hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")";
},
toHsl: function() {
var hsl = rgbToHsl(this._r, this._g, this._b);
return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a };
},
toHslString: function() {
var hsl = rgbToHsl(this._r, this._g, this._b);
var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100);
return (this._a == 1) ?
"hsl(" + h + ", " + s + "%, " + l + "%)" :
"hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")";
},
toHex: function(allow3Char) {
return rgbToHex(this._r, this._g, this._b, allow3Char);
},
toHexString: function(allow3Char) {
return '#' + this.toHex(allow3Char);
},
toHex8: function() {
return rgbaToHex(this._r, this._g, this._b, this._a);
},
toHex8String: function() {
return '#' + this.toHex8();
},
toRgb: function() {
return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a };
},
toRgbString: function() {
return (this._a == 1) ?
"rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" :
"rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")";
},
toPercentageRgb: function() {
return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a };
},
toPercentageRgbString: function() {
return (this._a == 1) ?
"rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" :
"rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")";
},
toName: function() {
if (this._a === 0) {
return "transparent";
}
if (this._a < 1) {
return false;
}
return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;
},
toFilter: function(secondColor) {
var hex8String = '#' + rgbaToHex(this._r, this._g, this._b, this._a);
var secondHex8String = hex8String;
var gradientType = this._gradientType ? "GradientType = 1, " : "";
if (secondColor) {
var s = tinycolor(secondColor);
secondHex8String = s.toHex8String();
}
return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")";
},
toString: function(format) {
var formatSet = !!format;
format = format || this._format;
var formattedString = false;
var hasAlpha = this._a < 1 && this._a >= 0;
var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "name");
if (needsAlphaFormat) {
// Special case for "transparent", all other non-alpha formats
// will return rgba when there is transparency.
if (format === "name" && this._a === 0) {
return this.toName();
}
return this.toRgbString();
}
if (format === "rgb") {
formattedString = this.toRgbString();
}
if (format === "prgb") {
formattedString = this.toPercentageRgbString();
}
if (format === "hex" || format === "hex6") {
formattedString = this.toHexString();
}
if (format === "hex3") {
formattedString = this.toHexString(true);
}
if (format === "hex8") {
formattedString = this.toHex8String();
}
if (format === "name") {
formattedString = this.toName();
}
if (format === "hsl") {
formattedString = this.toHslString();
}
if (format === "hsv") {
formattedString = this.toHsvString();
}
return formattedString || this.toHexString();
},
_applyModification: function(fn, args) {
var color = fn.apply(null, [this].concat([].slice.call(args)));
this._r = color._r;
this._g = color._g;
this._b = color._b;
this.setAlpha(color._a);
return this;
},
lighten: function() {
return this._applyModification(lighten, arguments);
},
brighten: function() {
return this._applyModification(brighten, arguments);
},
darken: function() {
return this._applyModification(darken, arguments);
},
desaturate: function() {
return this._applyModification(desaturate, arguments);
},
saturate: function() {
return this._applyModification(saturate, arguments);
},
greyscale: function() {
return this._applyModification(greyscale, arguments);
},
spin: function() {
return this._applyModification(spin, arguments);
},
_applyCombination: function(fn, args) {
return fn.apply(null, [this].concat([].slice.call(args)));
},
analogous: function() {
return this._applyCombination(analogous, arguments);
},
complement: function() {
return this._applyCombination(complement, arguments);
},
monochromatic: function() {
return this._applyCombination(monochromatic, arguments);
},
splitcomplement: function() {
return this._applyCombination(splitcomplement, arguments);
},
triad: function() {
return this._applyCombination(triad, arguments);
},
tetrad: function() {
return this._applyCombination(tetrad, arguments);
}
};
// If input is an object, force 1 into "1.0" to handle ratios properly
// String input requires "1.0" as input, so 1 will be treated as 1
tinycolor.fromRatio = function(color, opts) {
if (typeof color == "object") {
var newColor = {};
for (var i in color) {
if (color.hasOwnProperty(i)) {
if (i === "a") {
newColor[i] = color[i];
}
else {
newColor[i] = convertToPercentage(color[i]);
}
}
}
color = newColor;
}
return tinycolor(color, opts);
};
// Given a string or object, convert that input to RGB
// Possible string inputs:
//
// "red"
// "#f00" or "f00"
// "#ff0000" or "ff0000"
// "#ff000000" or "ff000000"
// "rgb 255 0 0" or "rgb (255, 0, 0)"
// "rgb 1.0 0 0" or "rgb (1, 0, 0)"
// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1"
// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1"
// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%"
// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1"
// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%"
//
function inputToRGB(color) {
var rgb = { r: 0, g: 0, b: 0 };
var a = 1;
var ok = false;
var format = false;
if (typeof color == "string") {
color = stringInputToObject(color);
}
if (typeof color == "object") {
if (color.hasOwnProperty("r") && color.hasOwnProperty("g") && color.hasOwnProperty("b")) {
rgb = rgbToRgb(color.r, color.g, color.b);
ok = true;
format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb";
}
else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("v")) {
color.s = convertToPercentage(color.s);
color.v = convertToPercentage(color.v);
rgb = hsvToRgb(color.h, color.s, color.v);
ok = true;
format = "hsv";
}
else if (color.hasOwnProperty("h") && color.hasOwnProperty("s") && color.hasOwnProperty("l")) {
color.s = convertToPercentage(color.s);
color.l = convertToPercentage(color.l);
rgb = hslToRgb(color.h, color.s, color.l);
ok = true;
format = "hsl";
}
if (color.hasOwnProperty("a")) {
a = color.a;
}
}
a = boundAlpha(a);
return {
ok: ok,
format: color.format || format,
r: mathMin(255, mathMax(rgb.r, 0)),
g: mathMin(255, mathMax(rgb.g, 0)),
b: mathMin(255, mathMax(rgb.b, 0)),
a: a
};
}
// Conversion Functions
// --------------------
// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:
// <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
// `rgbToRgb`
// Handle bounds / percentage checking to conform to CSS color spec
// <http://www.w3.org/TR/css3-color/>
// *Assumes:* r, g, b in [0, 255] or [0, 1]
// *Returns:* { r, g, b } in [0, 255]
function rgbToRgb(r, g, b){
return {
r: bound01(r, 255) * 255,
g: bound01(g, 255) * 255,
b: bound01(b, 255) * 255
};
}
// `rgbToHsl`
// Converts an RGB color value to HSL.
// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]
// *Returns:* { h, s, l } in [0,1]
function rgbToHsl(r, g, b) {
r = bound01(r, 255);
g = bound01(g, 255);
b = bound01(b, 255);
var max = mathMax(r, g, b), min = mathMin(r, g, b);
var h, s, l = (max + min) / 2;
if(max == min) {
h = s = 0; // achromatic
}
else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch(max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return { h: h, s: s, l: l };
}
// `hslToRgb`
// Converts an HSL color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function hslToRgb(h, s, l) {
var r, g, b;
h = bound01(h, 360);
s = bound01(s, 100);
l = bound01(l, 100);
function hue2rgb(p, q, t) {
if(t < 0) t += 1;
if(t > 1) t -= 1;
if(t < 1/6) return p + (q - p) * 6 * t;
if(t < 1/2) return q;
if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
}
if(s === 0) {
r = g = b = l; // achromatic
}
else {
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return { r: r * 255, g: g * 255, b: b * 255 };
}
// `rgbToHsv`
// Converts an RGB color value to HSV
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
// *Returns:* { h, s, v } in [0,1]
function rgbToHsv(r, g, b) {
r = bound01(r, 255);
g = bound01(g, 255);
b = bound01(b, 255);
var max = mathMax(r, g, b), min = mathMin(r, g, b);
var h, s, v = max;
var d = max - min;
s = max === 0 ? 0 : d / max;
if(max == min) {
h = 0; // achromatic
}
else {
switch(max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return { h: h, s: s, v: v };
}
// `hsvToRgb`
// Converts an HSV color value to RGB.
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
// *Returns:* { r, g, b } in the set [0, 255]
function hsvToRgb(h, s, v) {
h = bound01(h, 360) * 6;
s = bound01(s, 100);
v = bound01(v, 100);
var i = math.floor(h),
f = h - i,
p = v * (1 - s),
q = v * (1 - f * s),
t = v * (1 - (1 - f) * s),
mod = i % 6,
r = [v, q, p, p, t, v][mod],
g = [t, v, v, q, p, p][mod],
b = [p, p, t, v, v, q][mod];
return { r: r * 255, g: g * 255, b: b * 255 };
}
// `rgbToHex`
// Converts an RGB color to hex
// Assumes r, g, and b are contained in the set [0, 255]
// Returns a 3 or 6 character hex
function rgbToHex(r, g, b, allow3Char) {
var hex = [
pad2(mathRound(r).toString(16)),
pad2(mathRound(g).toString(16)),
pad2(mathRound(b).toString(16))
];
// Return a 3 character hex if possible
if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {
return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
}
return hex.join("");
}
// `rgbaToHex`
// Converts an RGBA color plus alpha transparency to hex
// Assumes r, g, b and a are contained in the set [0, 255]
// Returns an 8 character hex
function rgbaToHex(r, g, b, a) {
var hex = [
pad2(convertDecimalToHex(a)),
pad2(mathRound(r).toString(16)),
pad2(mathRound(g).toString(16)),
pad2(mathRound(b).toString(16))
];
return hex.join("");
}
// `equals`
// Can be called with any tinycolor input
tinycolor.equals = function (color1, color2) {
if (!color1 || !color2) { return false; }
return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();
};
tinycolor.random = function() {
return tinycolor.fromRatio({
r: mathRandom(),
g: mathRandom(),
b: mathRandom()
});
};
// Modification Functions
// ----------------------
// Thanks to less.js for some of the basics here
// <https://github.com/cloudhead/less.js/blob/master/lib/less/functions.js>
function desaturate(color, amount) {
amount = (amount === 0) ? 0 : (amount || 10);
var hsl = tinycolor(color).toHsl();
hsl.s -= amount / 100;
hsl.s = clamp01(hsl.s);
return tinycolor(hsl);
}
function saturate(color, amount) {
amount = (amount === 0) ? 0 : (amount || 10);
var hsl = tinycolor(color).toHsl();
hsl.s += amount / 100;
hsl.s = clamp01(hsl.s);
return tinycolor(hsl);
}
function greyscale(color) {
return tinycolor(color).desaturate(100);
}
function lighten (color, amount) {
amount = (amount === 0) ? 0 : (amount || 10);
var hsl = tinycolor(color).toHsl();
hsl.l += amount / 100;
hsl.l = clamp01(hsl.l);
return tinycolor(hsl);
}
function brighten(color, amount) {
amount = (amount === 0) ? 0 : (amount || 10);
var rgb = tinycolor(color).toRgb();
rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100))));
rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100))));
rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100))));
return tinycolor(rgb);
}
function darken (color, amount) {
amount = (amount === 0) ? 0 : (amount || 10);
var hsl = tinycolor(color).toHsl();
hsl.l -= amount / 100;
hsl.l = clamp01(hsl.l);
return tinycolor(hsl);
}
// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.
// Values outside of this range will be wrapped into this range.
function spin(color, amount) {
var hsl = tinycolor(color).toHsl();
var hue = (mathRound(hsl.h) + amount) % 360;
hsl.h = hue < 0 ? 360 + hue : hue;
return tinycolor(hsl);
}
// Combination Functions
// ---------------------
// Thanks to jQuery xColor for some of the ideas behind these
// <https://github.com/infusion/jQuery-xcolor/blob/master/jquery.xcolor.js>
function complement(color) {
var hsl = tinycolor(color).toHsl();
hsl.h = (hsl.h + 180) % 360;
return tinycolor(hsl);
}
function triad(color) {
var hsl = tinycolor(color).toHsl();
var h = hsl.h;
return [
tinycolor(color),
tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }),
tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l })
];
}
function tetrad(color) {
var hsl = tinycolor(color).toHsl();
var h = hsl.h;
return [
tinycolor(color),
tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }),
tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }),
tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l })
];
}
function splitcomplement(color) {
var hsl = tinycolor(color).toHsl();
var h = hsl.h;
return [
tinycolor(color),
tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}),
tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l})
];
}
function analogous(color, results, slices) {
results = results || 6;
slices = slices || 30;
var hsl = tinycolor(color).toHsl();
var part = 360 / slices;
var ret = [tinycolor(color)];
for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) {
hsl.h = (hsl.h + part) % 360;
ret.push(tinycolor(hsl));
}
return ret;
}
function monochromatic(color, results) {
results = results || 6;
var hsv = tinycolor(color).toHsv();
var h = hsv.h, s = hsv.s, v = hsv.v;
var ret = [];
var modification = 1 / results;
while (results--) {
ret.push(tinycolor({ h: h, s: s, v: v}));
v = (v + modification) % 1;
}
return ret;
}
// Utility Functions
// ---------------------
tinycolor.mix = function(color1, color2, amount) {
amount = (amount === 0) ? 0 : (amount || 50);
var rgb1 = tinycolor(color1).toRgb();
var rgb2 = tinycolor(color2).toRgb();
var p = amount / 100;
var w = p * 2 - 1;
var a = rgb2.a - rgb1.a;
var w1;
if (w * a == -1) {
w1 = w;
} else {
w1 = (w + a) / (1 + w * a);
}
w1 = (w1 + 1) / 2;
var w2 = 1 - w1;
var rgba = {
r: rgb2.r * w1 + rgb1.r * w2,
g: rgb2.g * w1 + rgb1.g * w2,
b: rgb2.b * w1 + rgb1.b * w2,
a: rgb2.a * p + rgb1.a * (1 - p)
};
return tinycolor(rgba);
};
// Readability Functions
// ---------------------
// <http://www.w3.org/TR/AERT#color-contrast>
// `readability`
// Analyze the 2 colors and returns an object with the following properties:
// `brightness`: difference in brightness between the two colors
// `color`: difference in color/hue between the two colors
tinycolor.readability = function(color1, color2) {
var c1 = tinycolor(color1);
var c2 = tinycolor(color2);
var rgb1 = c1.toRgb();
var rgb2 = c2.toRgb();
var brightnessA = c1.getBrightness();
var brightnessB = c2.getBrightness();
var colorDiff = (
Math.max(rgb1.r, rgb2.r) - Math.min(rgb1.r, rgb2.r) +
Math.max(rgb1.g, rgb2.g) - Math.min(rgb1.g, rgb2.g) +
Math.max(rgb1.b, rgb2.b) - Math.min(rgb1.b, rgb2.b)
);
return {
brightness: Math.abs(brightnessA - brightnessB),
color: colorDiff
};
};
// `readable`
// http://www.w3.org/TR/AERT#color-contrast
// Ensure that foreground and background color combinations provide sufficient contrast.
// *Example*
// tinycolor.isReadable("#000", "#111") => false
tinycolor.isReadable = function(color1, color2) {
var readability = tinycolor.readability(color1, color2);
return readability.brightness > 125 && readability.color > 500;
};
// `mostReadable`
// Given a base color and a list of possible foreground or background
// colors for that base, returns the most readable color.
// *Example*
// tinycolor.mostReadable("#123", ["#fff", "#000"]) => "#000"
tinycolor.mostReadable = function(baseColor, colorList) {
var bestColor = null;
var bestScore = 0;
var bestIsReadable = false;
for (var i=0; i < colorList.length; i++) {
// We normalize both around the "acceptable" breaking point,
// but rank brightness constrast higher than hue.
var readability = tinycolor.readability(baseColor, colorList[i]);
var readable = readability.brightness > 125 && readability.color > 500;
var score = 3 * (readability.brightness / 125) + (readability.color / 500);
if ((readable && ! bestIsReadable) ||
(readable && bestIsReadable && score > bestScore) ||
((! readable) && (! bestIsReadable) && score > bestScore)) {
bestIsReadable = readable;
bestScore = score;
bestColor = tinycolor(colorList[i]);
}
}
return bestColor;
};
// Big List of Colors
// ------------------
// <http://www.w3.org/TR/css3-color/#svg-color>
var names = tinycolor.names = {
aliceblue: "f0f8ff",
antiquewhite: "faebd7",
aqua: "0ff",
aquamarine: "7fffd4",
azure: "f0ffff",
beige: "f5f5dc",
bisque: "ffe4c4",
black: "000",
blanchedalmond: "ffebcd",
blue: "00f",
blueviolet: "8a2be2",
brown: "a52a2a",
burlywood: "deb887",
burntsienna: "ea7e5d",
cadetblue: "5f9ea0",
chartreuse: "7fff00",
chocolate: "d2691e",
coral: "ff7f50",
cornflowerblue: "6495ed",
cornsilk: "fff8dc",
crimson: "dc143c",
cyan: "0ff",
darkblue: "00008b",
darkcyan: "008b8b",
darkgoldenrod: "b8860b",
darkgray: "a9a9a9",
darkgreen: "006400",
darkgrey: "a9a9a9",
darkkhaki: "bdb76b",
darkmagenta: "8b008b",
darkolivegreen: "556b2f",
darkorange: "ff8c00",
darkorchid: "9932cc",
darkred: "8b0000",
darksalmon: "e9967a",
darkseagreen: "8fbc8f",
darkslateblue: "483d8b",
darkslategray: "2f4f4f",
darkslategrey: "2f4f4f",
darkturquoise: "00ced1",
darkviolet: "9400d3",
deeppink: "ff1493",
deepskyblue: "00bfff",
dimgray: "696969",
dimgrey: "696969",
dodgerblue: "1e90ff",
firebrick: "b22222",
floralwhite: "fffaf0",
forestgreen: "228b22",
fuchsia: "f0f",
gainsboro: "dcdcdc",
ghostwhite: "f8f8ff",
gold: "ffd700",
goldenrod: "daa520",
gray: "808080",
green: "008000",
greenyellow: "adff2f",
grey: "808080",
honeydew: "f0fff0",
hotpink: "ff69b4",
indianred: "cd5c5c",
indigo: "4b0082",
ivory: "fffff0",
khaki: "f0e68c",
lavender: "e6e6fa",
lavenderblush: "fff0f5",
lawngreen: "7cfc00",
lemonchiffon: "fffacd",
lightblue: "add8e6",
lightcoral: "f08080",
lightcyan: "e0ffff",
lightgoldenrodyellow: "fafad2",
lightgray: "d3d3d3",
lightgreen: "90ee90",
lightgrey: "d3d3d3",
lightpink: "ffb6c1",
lightsalmon: "ffa07a",
lightseagreen: "20b2aa",
lightskyblue: "87cefa",
lightslategray: "789",
lightslategrey: "789",
lightsteelblue: "b0c4de",
lightyellow: "ffffe0",
lime: "0f0",
limegreen: "32cd32",
linen: "faf0e6",
magenta: "f0f",
maroon: "800000",
mediumaquamarine: "66cdaa",
mediumblue: "0000cd",
mediumorchid: "ba55d3",
mediumpurple: "9370db",
mediumseagreen: "3cb371",
mediumslateblue: "7b68ee",
mediumspringgreen: "00fa9a",
mediumturquoise: "48d1cc",
mediumvioletred: "c71585",
midnightblue: "191970",
mintcream: "f5fffa",
mistyrose: "ffe4e1",
moccasin: "ffe4b5",
navajowhite: "ffdead",
navy: "000080",
oldlace: "fdf5e6",
olive: "808000",
olivedrab: "6b8e23",
orange: "ffa500",
orangered: "ff4500",
orchid: "da70d6",
palegoldenrod: "eee8aa",
palegreen: "98fb98",
paleturquoise: "afeeee",
palevioletred: "db7093",
papayawhip: "ffefd5",
peachpuff: "ffdab9",
peru: "cd853f",
pink: "ffc0cb",
plum: "dda0dd",
powderblue: "b0e0e6",
purple: "800080",
rebeccapurple: "663399",
red: "f00",
rosybrown: "bc8f8f",
royalblue: "4169e1",
saddlebrown: "8b4513",
salmon: "fa8072",
sandybrown: "f4a460",
seagreen: "2e8b57",
seashell: "fff5ee",
sienna: "a0522d",
silver: "c0c0c0",
skyblue: "87ceeb",
slateblue: "6a5acd",
slategray: "708090",
slategrey: "708090",
snow: "fffafa",
springgreen: "00ff7f",
steelblue: "4682b4",
tan: "d2b48c",
teal: "008080",
thistle: "d8bfd8",
tomato: "ff6347",
turquoise: "40e0d0",
violet: "ee82ee",
wheat: "f5deb3",
white: "fff",
whitesmoke: "f5f5f5",
yellow: "ff0",
yellowgreen: "9acd32"
};
// Make it easy to access colors via `hexNames[hex]`
var hexNames = tinycolor.hexNames = flip(names);
// Utilities
// ---------
// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`
function flip(o) {
var flipped = { };
for (var i in o) {
if (o.hasOwnProperty(i)) {
flipped[o[i]] = i;
}
}
return flipped;
}
// Return a valid alpha value [0,1] with all invalid values being set to 1
function boundAlpha(a) {
a = parseFloat(a);
if (isNaN(a) || a < 0 || a > 1) {
a = 1;
}
return a;
}
// Take input from [0, n] and return it as [0, 1]
function bound01(n, max) {
if (isOnePointZero(n)) { n = "100%"; }
var processPercent = isPercentage(n);
n = mathMin(max, mathMax(0, parseFloat(n)));
// Automatically convert percentage into number
if (processPercent) {
n = parseInt(n * max, 10) / 100;
}
// Handle floating point rounding errors
if ((math.abs(n - max) < 0.000001)) {
return 1;
}
// Convert into [0, 1] range if it isn't already
return (n % max) / parseFloat(max);
}
// Force a number between 0 and 1
function clamp01(val) {
return mathMin(1, mathMax(0, val));
}
// Parse a base-16 hex value into a base-10 integer
function parseIntFromHex(val) {
return parseInt(val, 16);
}
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
function isOnePointZero(n) {
return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1;
}
// Check to see if string passed in is a percentage
function isPercentage(n) {
return typeof n === "string" && n.indexOf('%') != -1;
}
// Force a hex value to have 2 characters
function pad2(c) {
return c.length == 1 ? '0' + c : '' + c;
}
// Replace a decimal with it's percentage value
function convertToPercentage(n) {
if (n <= 1) {
n = (n * 100) + "%";
}
return n;
}
// Converts a decimal to a hex value
function convertDecimalToHex(d) {
return Math.round(parseFloat(d) * 255).toString(16);
}
// Converts a hex value to a decimal
function convertHexToDecimal(h) {
return (parseIntFromHex(h) / 255);
}
var matchers = (function() {
// <http://www.w3.org/TR/css3-values/#integers>
var CSS_INTEGER = "[-\\+]?\\d+%?";
// <http://www.w3.org/TR/css3-values/#number-value>
var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?";
// Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.
var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")";
// Actual matching.
// Parentheses and commas are optional, but not required.
// Whitespace can take the place of commas or opening paren
var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?";
return {
rgb: new RegExp("rgb" + PERMISSIVE_MATCH3),
rgba: new RegExp("rgba" + PERMISSIVE_MATCH4),
hsl: new RegExp("hsl" + PERMISSIVE_MATCH3),
hsla: new RegExp("hsla" + PERMISSIVE_MATCH4),
hsv: new RegExp("hsv" + PERMISSIVE_MATCH3),
hsva: new RegExp("hsva" + PERMISSIVE_MATCH4),
hex3: /^([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
hex6: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
hex8: /^([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/
};
})();
// `stringInputToObject`
// Permissive string parsing. Take in a number of formats, and output an object
// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`
function stringInputToObject(color) {
color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase();
var named = false;
if (names[color]) {
color = names[color];
named = true;
}
else if (color == 'transparent') {
return { r: 0, g: 0, b: 0, a: 0, format: "name" };
}
// Try to match string input using regular expressions.
// Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]
// Just return an object and let the conversion functions handle that.
// This way the result will be the same whether the tinycolor is initialized with string or object.
var match;
if ((match = matchers.rgb.exec(color))) {
return { r: match[1], g: match[2], b: match[3] };
}
if ((match = matchers.rgba.exec(color))) {
return { r: match[1], g: match[2], b: match[3], a: match[4] };
}
if ((match = matchers.hsl.exec(color))) {
return { h: match[1], s: match[2], l: match[3] };
}
if ((match = matchers.hsla.exec(color))) {
return { h: match[1], s: match[2], l: match[3], a: match[4] };
}
if ((match = matchers.hsv.exec(color))) {
return { h: match[1], s: match[2], v: match[3] };
}
if ((match = matchers.hsva.exec(color))) {
return { h: match[1], s: match[2], v: match[3], a: match[4] };
}
if ((match = matchers.hex8.exec(color))) {
return {
a: convertHexToDecimal(match[1]),
r: parseIntFromHex(match[2]),
g: parseIntFromHex(match[3]),
b: parseIntFromHex(match[4]),
format: named ? "name" : "hex8"
};
}
if ((match = matchers.hex6.exec(color))) {
return {
r: parseIntFromHex(match[1]),
g: parseIntFromHex(match[2]),
b: parseIntFromHex(match[3]),
format: named ? "name" : "hex"
};
}
if ((match = matchers.hex3.exec(color))) {
return {
r: parseIntFromHex(match[1] + '' + match[1]),
g: parseIntFromHex(match[2] + '' + match[2]),
b: parseIntFromHex(match[3] + '' + match[3]),
format: named ? "name" : "hex"
};
}
return false;
}
window.tinycolor = tinycolor;
})();
$(function () {
if ($.fn.spectrum.load) {
$.fn.spectrum.processNativeColorInputs();
}
});
});
/*!
* Vue.js v2.6.11
* (c) 2014-2019 Evan You
* Released under the MIT License.
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Vue=t()}(this,function(){"use strict";var e=Object.freeze({});function t(e){return null==e}function n(e){return null!=e}function r(e){return!0===e}function i(e){return"string"==typeof e||"number"==typeof e||"symbol"==typeof e||"boolean"==typeof e}function o(e){return null!==e&&"object"==typeof e}var a=Object.prototype.toString;function s(e){return"[object Object]"===a.call(e)}function c(e){var t=parseFloat(String(e));return t>=0&&Math.floor(t)===t&&isFinite(e)}function u(e){return n(e)&&"function"==typeof e.then&&"function"==typeof e.catch}function l(e){return null==e?"":Array.isArray(e)||s(e)&&e.toString===a?JSON.stringify(e,null,2):String(e)}function f(e){var t=parseFloat(e);return isNaN(t)?e:t}function p(e,t){for(var n=Object.create(null),r=e.split(","),i=0;i<r.length;i++)n[r[i]]=!0;return t?function(e){return n[e.toLowerCase()]}:function(e){return n[e]}}var d=p("slot,component",!0),v=p("key,ref,slot,slot-scope,is");function h(e,t){if(e.length){var n=e.indexOf(t);if(n>-1)return e.splice(n,1)}}var m=Object.prototype.hasOwnProperty;function y(e,t){return m.call(e,t)}function g(e){var t=Object.create(null);return function(n){return t[n]||(t[n]=e(n))}}var _=/-(\w)/g,b=g(function(e){return e.replace(_,function(e,t){return t?t.toUpperCase():""})}),$=g(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),w=/\B([A-Z])/g,C=g(function(e){return e.replace(w,"-$1").toLowerCase()});var x=Function.prototype.bind?function(e,t){return e.bind(t)}:function(e,t){function n(n){var r=arguments.length;return r?r>1?e.apply(t,arguments):e.call(t,n):e.call(t)}return n._length=e.length,n};function k(e,t){t=t||0;for(var n=e.length-t,r=new Array(n);n--;)r[n]=e[n+t];return r}function A(e,t){for(var n in t)e[n]=t[n];return e}function O(e){for(var t={},n=0;n<e.length;n++)e[n]&&A(t,e[n]);return t}function S(e,t,n){}var T=function(e,t,n){return!1},E=function(e){return e};function N(e,t){if(e===t)return!0;var n=o(e),r=o(t);if(!n||!r)return!n&&!r&&String(e)===String(t);try{var i=Array.isArray(e),a=Array.isArray(t);if(i&&a)return e.length===t.length&&e.every(function(e,n){return N(e,t[n])});if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(i||a)return!1;var s=Object.keys(e),c=Object.keys(t);return s.length===c.length&&s.every(function(n){return N(e[n],t[n])})}catch(e){return!1}}function j(e,t){for(var n=0;n<e.length;n++)if(N(e[n],t))return n;return-1}function D(e){var t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}var L="data-server-rendered",M=["component","directive","filter"],I=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured","serverPrefetch"],F={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:T,isReservedAttr:T,isUnknownElement:T,getTagNamespace:S,parsePlatformTagName:E,mustUseProp:T,async:!0,_lifecycleHooks:I},P=/a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/;function R(e,t,n,r){Object.defineProperty(e,t,{value:n,enumerable:!!r,writable:!0,configurable:!0})}var H=new RegExp("[^"+P.source+".$_\\d]");var B,U="__proto__"in{},z="undefined"!=typeof window,V="undefined"!=typeof WXEnvironment&&!!WXEnvironment.platform,K=V&&WXEnvironment.platform.toLowerCase(),J=z&&window.navigator.userAgent.toLowerCase(),q=J&&/msie|trident/.test(J),W=J&&J.indexOf("msie 9.0")>0,Z=J&&J.indexOf("edge/")>0,G=(J&&J.indexOf("android"),J&&/iphone|ipad|ipod|ios/.test(J)||"ios"===K),X=(J&&/chrome\/\d+/.test(J),J&&/phantomjs/.test(J),J&&J.match(/firefox\/(\d+)/)),Y={}.watch,Q=!1;if(z)try{var ee={};Object.defineProperty(ee,"passive",{get:function(){Q=!0}}),window.addEventListener("test-passive",null,ee)}catch(e){}var te=function(){return void 0===B&&(B=!z&&!V&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),B},ne=z&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function re(e){return"function"==typeof e&&/native code/.test(e.toString())}var ie,oe="undefined"!=typeof Symbol&&re(Symbol)&&"undefined"!=typeof Reflect&&re(Reflect.ownKeys);ie="undefined"!=typeof Set&&re(Set)?Set:function(){function e(){this.set=Object.create(null)}return e.prototype.has=function(e){return!0===this.set[e]},e.prototype.add=function(e){this.set[e]=!0},e.prototype.clear=function(){this.set=Object.create(null)},e}();var ae=S,se=0,ce=function(){this.id=se++,this.subs=[]};ce.prototype.addSub=function(e){this.subs.push(e)},ce.prototype.removeSub=function(e){h(this.subs,e)},ce.prototype.depend=function(){ce.target&&ce.target.addDep(this)},ce.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},ce.target=null;var ue=[];function le(e){ue.push(e),ce.target=e}function fe(){ue.pop(),ce.target=ue[ue.length-1]}var pe=function(e,t,n,r,i,o,a,s){this.tag=e,this.data=t,this.children=n,this.text=r,this.elm=i,this.ns=void 0,this.context=o,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},de={child:{configurable:!0}};de.child.get=function(){return this.componentInstance},Object.defineProperties(pe.prototype,de);var ve=function(e){void 0===e&&(e="");var t=new pe;return t.text=e,t.isComment=!0,t};function he(e){return new pe(void 0,void 0,void 0,String(e))}function me(e){var t=new pe(e.tag,e.data,e.children&&e.children.slice(),e.text,e.elm,e.context,e.componentOptions,e.asyncFactory);return t.ns=e.ns,t.isStatic=e.isStatic,t.key=e.key,t.isComment=e.isComment,t.fnContext=e.fnContext,t.fnOptions=e.fnOptions,t.fnScopeId=e.fnScopeId,t.asyncMeta=e.asyncMeta,t.isCloned=!0,t}var ye=Array.prototype,ge=Object.create(ye);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=ye[e];R(ge,e,function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];var i,o=t.apply(this,n),a=this.__ob__;switch(e){case"push":case"unshift":i=n;break;case"splice":i=n.slice(2)}return i&&a.observeArray(i),a.dep.notify(),o})});var _e=Object.getOwnPropertyNames(ge),be=!0;function $e(e){be=e}var we=function(e){var t;this.value=e,this.dep=new ce,this.vmCount=0,R(e,"__ob__",this),Array.isArray(e)?(U?(t=ge,e.__proto__=t):function(e,t,n){for(var r=0,i=n.length;r<i;r++){var o=n[r];R(e,o,t[o])}}(e,ge,_e),this.observeArray(e)):this.walk(e)};function Ce(e,t){var n;if(o(e)&&!(e instanceof pe))return y(e,"__ob__")&&e.__ob__ instanceof we?n=e.__ob__:be&&!te()&&(Array.isArray(e)||s(e))&&Object.isExtensible(e)&&!e._isVue&&(n=new we(e)),t&&n&&n.vmCount++,n}function xe(e,t,n,r,i){var o=new ce,a=Object.getOwnPropertyDescriptor(e,t);if(!a||!1!==a.configurable){var s=a&&a.get,c=a&&a.set;s&&!c||2!==arguments.length||(n=e[t]);var u=!i&&Ce(n);Object.defineProperty(e,t,{enumerable:!0,configurable:!0,get:function(){var t=s?s.call(e):n;return ce.target&&(o.depend(),u&&(u.dep.depend(),Array.isArray(t)&&function e(t){for(var n=void 0,r=0,i=t.length;r<i;r++)(n=t[r])&&n.__ob__&&n.__ob__.dep.depend(),Array.isArray(n)&&e(n)}(t))),t},set:function(t){var r=s?s.call(e):n;t===r||t!=t&&r!=r||s&&!c||(c?c.call(e,t):n=t,u=!i&&Ce(t),o.notify())}})}}function ke(e,t,n){if(Array.isArray(e)&&c(t))return e.length=Math.max(e.length,t),e.splice(t,1,n),n;if(t in e&&!(t in Object.prototype))return e[t]=n,n;var r=e.__ob__;return e._isVue||r&&r.vmCount?n:r?(xe(r.value,t,n),r.dep.notify(),n):(e[t]=n,n)}function Ae(e,t){if(Array.isArray(e)&&c(t))e.splice(t,1);else{var n=e.__ob__;e._isVue||n&&n.vmCount||y(e,t)&&(delete e[t],n&&n.dep.notify())}}we.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)xe(e,t[n])},we.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)Ce(e[t])};var Oe=F.optionMergeStrategies;function Se(e,t){if(!t)return e;for(var n,r,i,o=oe?Reflect.ownKeys(t):Object.keys(t),a=0;a<o.length;a++)"__ob__"!==(n=o[a])&&(r=e[n],i=t[n],y(e,n)?r!==i&&s(r)&&s(i)&&Se(r,i):ke(e,n,i));return e}function Te(e,t,n){return n?function(){var r="function"==typeof t?t.call(n,n):t,i="function"==typeof e?e.call(n,n):e;return r?Se(r,i):i}:t?e?function(){return Se("function"==typeof t?t.call(this,this):t,"function"==typeof e?e.call(this,this):e)}:t:e}function Ee(e,t){var n=t?e?e.concat(t):Array.isArray(t)?t:[t]:e;return n?function(e){for(var t=[],n=0;n<e.length;n++)-1===t.indexOf(e[n])&&t.push(e[n]);return t}(n):n}function Ne(e,t,n,r){var i=Object.create(e||null);return t?A(i,t):i}Oe.data=function(e,t,n){return n?Te(e,t,n):t&&"function"!=typeof t?e:Te(e,t)},I.forEach(function(e){Oe[e]=Ee}),M.forEach(function(e){Oe[e+"s"]=Ne}),Oe.watch=function(e,t,n,r){if(e===Y&&(e=void 0),t===Y&&(t=void 0),!t)return Object.create(e||null);if(!e)return t;var i={};for(var o in A(i,e),t){var a=i[o],s=t[o];a&&!Array.isArray(a)&&(a=[a]),i[o]=a?a.concat(s):Array.isArray(s)?s:[s]}return i},Oe.props=Oe.methods=Oe.inject=Oe.computed=function(e,t,n,r){if(!e)return t;var i=Object.create(null);return A(i,e),t&&A(i,t),i},Oe.provide=Te;var je=function(e,t){return void 0===t?e:t};function De(e,t,n){if("function"==typeof t&&(t=t.options),function(e,t){var n=e.props;if(n){var r,i,o={};if(Array.isArray(n))for(r=n.length;r--;)"string"==typeof(i=n[r])&&(o[b(i)]={type:null});else if(s(n))for(var a in n)i=n[a],o[b(a)]=s(i)?i:{type:i};e.props=o}}(t),function(e,t){var n=e.inject;if(n){var r=e.inject={};if(Array.isArray(n))for(var i=0;i<n.length;i++)r[n[i]]={from:n[i]};else if(s(n))for(var o in n){var a=n[o];r[o]=s(a)?A({from:o},a):{from:a}}}}(t),function(e){var t=e.directives;if(t)for(var n in t){var r=t[n];"function"==typeof r&&(t[n]={bind:r,update:r})}}(t),!t._base&&(t.extends&&(e=De(e,t.extends,n)),t.mixins))for(var r=0,i=t.mixins.length;r<i;r++)e=De(e,t.mixins[r],n);var o,a={};for(o in e)c(o);for(o in t)y(e,o)||c(o);function c(r){var i=Oe[r]||je;a[r]=i(e[r],t[r],n,r)}return a}function Le(e,t,n,r){if("string"==typeof n){var i=e[t];if(y(i,n))return i[n];var o=b(n);if(y(i,o))return i[o];var a=$(o);return y(i,a)?i[a]:i[n]||i[o]||i[a]}}function Me(e,t,n,r){var i=t[e],o=!y(n,e),a=n[e],s=Pe(Boolean,i.type);if(s>-1)if(o&&!y(i,"default"))a=!1;else if(""===a||a===C(e)){var c=Pe(String,i.type);(c<0||s<c)&&(a=!0)}if(void 0===a){a=function(e,t,n){if(!y(t,"default"))return;var r=t.default;if(e&&e.$options.propsData&&void 0===e.$options.propsData[n]&&void 0!==e._props[n])return e._props[n];return"function"==typeof r&&"Function"!==Ie(t.type)?r.call(e):r}(r,i,e);var u=be;$e(!0),Ce(a),$e(u)}return a}function Ie(e){var t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:""}function Fe(e,t){return Ie(e)===Ie(t)}function Pe(e,t){if(!Array.isArray(t))return Fe(t,e)?0:-1;for(var n=0,r=t.length;n<r;n++)if(Fe(t[n],e))return n;return-1}function Re(e,t,n){le();try{if(t)for(var r=t;r=r.$parent;){var i=r.$options.errorCaptured;if(i)for(var o=0;o<i.length;o++)try{if(!1===i[o].call(r,e,t,n))return}catch(e){Be(e,r,"errorCaptured hook")}}Be(e,t,n)}finally{fe()}}function He(e,t,n,r,i){var o;try{(o=n?e.apply(t,n):e.call(t))&&!o._isVue&&u(o)&&!o._handled&&(o.catch(function(e){return Re(e,r,i+" (Promise/async)")}),o._handled=!0)}catch(e){Re(e,r,i)}return o}function Be(e,t,n){if(F.errorHandler)try{return F.errorHandler.call(null,e,t,n)}catch(t){t!==e&&Ue(t,null,"config.errorHandler")}Ue(e,t,n)}function Ue(e,t,n){if(!z&&!V||"undefined"==typeof console)throw e;console.error(e)}var ze,Ve=!1,Ke=[],Je=!1;function qe(){Je=!1;var e=Ke.slice(0);Ke.length=0;for(var t=0;t<e.length;t++)e[t]()}if("undefined"!=typeof Promise&&re(Promise)){var We=Promise.resolve();ze=function(){We.then(qe),G&&setTimeout(S)},Ve=!0}else if(q||"undefined"==typeof MutationObserver||!re(MutationObserver)&&"[object MutationObserverConstructor]"!==MutationObserver.toString())ze="undefined"!=typeof setImmediate&&re(setImmediate)?function(){setImmediate(qe)}:function(){setTimeout(qe,0)};else{var Ze=1,Ge=new MutationObserver(qe),Xe=document.createTextNode(String(Ze));Ge.observe(Xe,{characterData:!0}),ze=function(){Ze=(Ze+1)%2,Xe.data=String(Ze)},Ve=!0}function Ye(e,t){var n;if(Ke.push(function(){if(e)try{e.call(t)}catch(e){Re(e,t,"nextTick")}else n&&n(t)}),Je||(Je=!0,ze()),!e&&"undefined"!=typeof Promise)return new Promise(function(e){n=e})}var Qe=new ie;function et(e){!function e(t,n){var r,i;var a=Array.isArray(t);if(!a&&!o(t)||Object.isFrozen(t)||t instanceof pe)return;if(t.__ob__){var s=t.__ob__.dep.id;if(n.has(s))return;n.add(s)}if(a)for(r=t.length;r--;)e(t[r],n);else for(i=Object.keys(t),r=i.length;r--;)e(t[i[r]],n)}(e,Qe),Qe.clear()}var tt=g(function(e){var t="&"===e.charAt(0),n="~"===(e=t?e.slice(1):e).charAt(0),r="!"===(e=n?e.slice(1):e).charAt(0);return{name:e=r?e.slice(1):e,once:n,capture:r,passive:t}});function nt(e,t){function n(){var e=arguments,r=n.fns;if(!Array.isArray(r))return He(r,null,arguments,t,"v-on handler");for(var i=r.slice(),o=0;o<i.length;o++)He(i[o],null,e,t,"v-on handler")}return n.fns=e,n}function rt(e,n,i,o,a,s){var c,u,l,f;for(c in e)u=e[c],l=n[c],f=tt(c),t(u)||(t(l)?(t(u.fns)&&(u=e[c]=nt(u,s)),r(f.once)&&(u=e[c]=a(f.name,u,f.capture)),i(f.name,u,f.capture,f.passive,f.params)):u!==l&&(l.fns=u,e[c]=l));for(c in n)t(e[c])&&o((f=tt(c)).name,n[c],f.capture)}function it(e,i,o){var a;e instanceof pe&&(e=e.data.hook||(e.data.hook={}));var s=e[i];function c(){o.apply(this,arguments),h(a.fns,c)}t(s)?a=nt([c]):n(s.fns)&&r(s.merged)?(a=s).fns.push(c):a=nt([s,c]),a.merged=!0,e[i]=a}function ot(e,t,r,i,o){if(n(t)){if(y(t,r))return e[r]=t[r],o||delete t[r],!0;if(y(t,i))return e[r]=t[i],o||delete t[i],!0}return!1}function at(e){return i(e)?[he(e)]:Array.isArray(e)?function e(o,a){var s=[];var c,u,l,f;for(c=0;c<o.length;c++)t(u=o[c])||"boolean"==typeof u||(l=s.length-1,f=s[l],Array.isArray(u)?u.length>0&&(st((u=e(u,(a||"")+"_"+c))[0])&&st(f)&&(s[l]=he(f.text+u[0].text),u.shift()),s.push.apply(s,u)):i(u)?st(f)?s[l]=he(f.text+u):""!==u&&s.push(he(u)):st(u)&&st(f)?s[l]=he(f.text+u.text):(r(o._isVList)&&n(u.tag)&&t(u.key)&&n(a)&&(u.key="__vlist"+a+"_"+c+"__"),s.push(u)));return s}(e):void 0}function st(e){return n(e)&&n(e.text)&&!1===e.isComment}function ct(e,t){if(e){for(var n=Object.create(null),r=oe?Reflect.ownKeys(e):Object.keys(e),i=0;i<r.length;i++){var o=r[i];if("__ob__"!==o){for(var a=e[o].from,s=t;s;){if(s._provided&&y(s._provided,a)){n[o]=s._provided[a];break}s=s.$parent}if(!s&&"default"in e[o]){var c=e[o].default;n[o]="function"==typeof c?c.call(t):c}}}return n}}function ut(e,t){if(!e||!e.length)return{};for(var n={},r=0,i=e.length;r<i;r++){var o=e[r],a=o.data;if(a&&a.attrs&&a.attrs.slot&&delete a.attrs.slot,o.context!==t&&o.fnContext!==t||!a||null==a.slot)(n.default||(n.default=[])).push(o);else{var s=a.slot,c=n[s]||(n[s]=[]);"template"===o.tag?c.push.apply(c,o.children||[]):c.push(o)}}for(var u in n)n[u].every(lt)&&delete n[u];return n}function lt(e){return e.isComment&&!e.asyncFactory||" "===e.text}function ft(t,n,r){var i,o=Object.keys(n).length>0,a=t?!!t.$stable:!o,s=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(a&&r&&r!==e&&s===r.$key&&!o&&!r.$hasNormal)return r;for(var c in i={},t)t[c]&&"$"!==c[0]&&(i[c]=pt(n,c,t[c]))}else i={};for(var u in n)u in i||(i[u]=dt(n,u));return t&&Object.isExtensible(t)&&(t._normalized=i),R(i,"$stable",a),R(i,"$key",s),R(i,"$hasNormal",o),i}function pt(e,t,n){var r=function(){var e=arguments.length?n.apply(null,arguments):n({});return(e=e&&"object"==typeof e&&!Array.isArray(e)?[e]:at(e))&&(0===e.length||1===e.length&&e[0].isComment)?void 0:e};return n.proxy&&Object.defineProperty(e,t,{get:r,enumerable:!0,configurable:!0}),r}function dt(e,t){return function(){return e[t]}}function vt(e,t){var r,i,a,s,c;if(Array.isArray(e)||"string"==typeof e)for(r=new Array(e.length),i=0,a=e.length;i<a;i++)r[i]=t(e[i],i);else if("number"==typeof e)for(r=new Array(e),i=0;i<e;i++)r[i]=t(i+1,i);else if(o(e))if(oe&&e[Symbol.iterator]){r=[];for(var u=e[Symbol.iterator](),l=u.next();!l.done;)r.push(t(l.value,r.length)),l=u.next()}else for(s=Object.keys(e),r=new Array(s.length),i=0,a=s.length;i<a;i++)c=s[i],r[i]=t(e[c],c,i);return n(r)||(r=[]),r._isVList=!0,r}function ht(e,t,n,r){var i,o=this.$scopedSlots[e];o?(n=n||{},r&&(n=A(A({},r),n)),i=o(n)||t):i=this.$slots[e]||t;var a=n&&n.slot;return a?this.$createElement("template",{slot:a},i):i}function mt(e){return Le(this.$options,"filters",e)||E}function yt(e,t){return Array.isArray(e)?-1===e.indexOf(t):e!==t}function gt(e,t,n,r,i){var o=F.keyCodes[t]||n;return i&&r&&!F.keyCodes[t]?yt(i,r):o?yt(o,e):r?C(r)!==t:void 0}function _t(e,t,n,r,i){if(n)if(o(n)){var a;Array.isArray(n)&&(n=O(n));var s=function(o){if("class"===o||"style"===o||v(o))a=e;else{var s=e.attrs&&e.attrs.type;a=r||F.mustUseProp(t,s,o)?e.domProps||(e.domProps={}):e.attrs||(e.attrs={})}var c=b(o),u=C(o);c in a||u in a||(a[o]=n[o],i&&((e.on||(e.on={}))["update:"+o]=function(e){n[o]=e}))};for(var c in n)s(c)}else;return e}function bt(e,t){var n=this._staticTrees||(this._staticTrees=[]),r=n[e];return r&&!t?r:(wt(r=n[e]=this.$options.staticRenderFns[e].call(this._renderProxy,null,this),"__static__"+e,!1),r)}function $t(e,t,n){return wt(e,"__once__"+t+(n?"_"+n:""),!0),e}function wt(e,t,n){if(Array.isArray(e))for(var r=0;r<e.length;r++)e[r]&&"string"!=typeof e[r]&&Ct(e[r],t+"_"+r,n);else Ct(e,t,n)}function Ct(e,t,n){e.isStatic=!0,e.key=t,e.isOnce=n}function xt(e,t){if(t)if(s(t)){var n=e.on=e.on?A({},e.on):{};for(var r in t){var i=n[r],o=t[r];n[r]=i?[].concat(i,o):o}}else;return e}function kt(e,t,n,r){t=t||{$stable:!n};for(var i=0;i<e.length;i++){var o=e[i];Array.isArray(o)?kt(o,t,n):o&&(o.proxy&&(o.fn.proxy=!0),t[o.key]=o.fn)}return r&&(t.$key=r),t}function At(e,t){for(var n=0;n<t.length;n+=2){var r=t[n];"string"==typeof r&&r&&(e[t[n]]=t[n+1])}return e}function Ot(e,t){return"string"==typeof e?t+e:e}function St(e){e._o=$t,e._n=f,e._s=l,e._l=vt,e._t=ht,e._q=N,e._i=j,e._m=bt,e._f=mt,e._k=gt,e._b=_t,e._v=he,e._e=ve,e._u=kt,e._g=xt,e._d=At,e._p=Ot}function Tt(t,n,i,o,a){var s,c=this,u=a.options;y(o,"_uid")?(s=Object.create(o))._original=o:(s=o,o=o._original);var l=r(u._compiled),f=!l;this.data=t,this.props=n,this.children=i,this.parent=o,this.listeners=t.on||e,this.injections=ct(u.inject,o),this.slots=function(){return c.$slots||ft(t.scopedSlots,c.$slots=ut(i,o)),c.$slots},Object.defineProperty(this,"scopedSlots",{enumerable:!0,get:function(){return ft(t.scopedSlots,this.slots())}}),l&&(this.$options=u,this.$slots=this.slots(),this.$scopedSlots=ft(t.scopedSlots,this.$slots)),u._scopeId?this._c=function(e,t,n,r){var i=Pt(s,e,t,n,r,f);return i&&!Array.isArray(i)&&(i.fnScopeId=u._scopeId,i.fnContext=o),i}:this._c=function(e,t,n,r){return Pt(s,e,t,n,r,f)}}function Et(e,t,n,r,i){var o=me(e);return o.fnContext=n,o.fnOptions=r,t.slot&&((o.data||(o.data={})).slot=t.slot),o}function Nt(e,t){for(var n in t)e[b(n)]=t[n]}St(Tt.prototype);var jt={init:function(e,t){if(e.componentInstance&&!e.componentInstance._isDestroyed&&e.data.keepAlive){var r=e;jt.prepatch(r,r)}else{(e.componentInstance=function(e,t){var r={_isComponent:!0,_parentVnode:e,parent:t},i=e.data.inlineTemplate;n(i)&&(r.render=i.render,r.staticRenderFns=i.staticRenderFns);return new e.componentOptions.Ctor(r)}(e,Wt)).$mount(t?e.elm:void 0,t)}},prepatch:function(t,n){var r=n.componentOptions;!function(t,n,r,i,o){var a=i.data.scopedSlots,s=t.$scopedSlots,c=!!(a&&!a.$stable||s!==e&&!s.$stable||a&&t.$scopedSlots.$key!==a.$key),u=!!(o||t.$options._renderChildren||c);t.$options._parentVnode=i,t.$vnode=i,t._vnode&&(t._vnode.parent=i);if(t.$options._renderChildren=o,t.$attrs=i.data.attrs||e,t.$listeners=r||e,n&&t.$options.props){$e(!1);for(var l=t._props,f=t.$options._propKeys||[],p=0;p<f.length;p++){var d=f[p],v=t.$options.props;l[d]=Me(d,v,n,t)}$e(!0),t.$options.propsData=n}r=r||e;var h=t.$options._parentListeners;t.$options._parentListeners=r,qt(t,r,h),u&&(t.$slots=ut(o,i.context),t.$forceUpdate())}(n.componentInstance=t.componentInstance,r.propsData,r.listeners,n,r.children)},insert:function(e){var t,n=e.context,r=e.componentInstance;r._isMounted||(r._isMounted=!0,Yt(r,"mounted")),e.data.keepAlive&&(n._isMounted?((t=r)._inactive=!1,en.push(t)):Xt(r,!0))},destroy:function(e){var t=e.componentInstance;t._isDestroyed||(e.data.keepAlive?function e(t,n){if(n&&(t._directInactive=!0,Gt(t)))return;if(!t._inactive){t._inactive=!0;for(var r=0;r<t.$children.length;r++)e(t.$children[r]);Yt(t,"deactivated")}}(t,!0):t.$destroy())}},Dt=Object.keys(jt);function Lt(i,a,s,c,l){if(!t(i)){var f=s.$options._base;if(o(i)&&(i=f.extend(i)),"function"==typeof i){var p;if(t(i.cid)&&void 0===(i=function(e,i){if(r(e.error)&&n(e.errorComp))return e.errorComp;if(n(e.resolved))return e.resolved;var a=Ht;a&&n(e.owners)&&-1===e.owners.indexOf(a)&&e.owners.push(a);if(r(e.loading)&&n(e.loadingComp))return e.loadingComp;if(a&&!n(e.owners)){var s=e.owners=[a],c=!0,l=null,f=null;a.$on("hook:destroyed",function(){return h(s,a)});var p=function(e){for(var t=0,n=s.length;t<n;t++)s[t].$forceUpdate();e&&(s.length=0,null!==l&&(clearTimeout(l),l=null),null!==f&&(clearTimeout(f),f=null))},d=D(function(t){e.resolved=Bt(t,i),c?s.length=0:p(!0)}),v=D(function(t){n(e.errorComp)&&(e.error=!0,p(!0))}),m=e(d,v);return o(m)&&(u(m)?t(e.resolved)&&m.then(d,v):u(m.component)&&(m.component.then(d,v),n(m.error)&&(e.errorComp=Bt(m.error,i)),n(m.loading)&&(e.loadingComp=Bt(m.loading,i),0===m.delay?e.loading=!0:l=setTimeout(function(){l=null,t(e.resolved)&&t(e.error)&&(e.loading=!0,p(!1))},m.delay||200)),n(m.timeout)&&(f=setTimeout(function(){f=null,t(e.resolved)&&v(null)},m.timeout)))),c=!1,e.loading?e.loadingComp:e.resolved}}(p=i,f)))return function(e,t,n,r,i){var o=ve();return o.asyncFactory=e,o.asyncMeta={data:t,context:n,children:r,tag:i},o}(p,a,s,c,l);a=a||{},$n(i),n(a.model)&&function(e,t){var r=e.model&&e.model.prop||"value",i=e.model&&e.model.event||"input";(t.attrs||(t.attrs={}))[r]=t.model.value;var o=t.on||(t.on={}),a=o[i],s=t.model.callback;n(a)?(Array.isArray(a)?-1===a.indexOf(s):a!==s)&&(o[i]=[s].concat(a)):o[i]=s}(i.options,a);var d=function(e,r,i){var o=r.options.props;if(!t(o)){var a={},s=e.attrs,c=e.props;if(n(s)||n(c))for(var u in o){var l=C(u);ot(a,c,u,l,!0)||ot(a,s,u,l,!1)}return a}}(a,i);if(r(i.options.functional))return function(t,r,i,o,a){var s=t.options,c={},u=s.props;if(n(u))for(var l in u)c[l]=Me(l,u,r||e);else n(i.attrs)&&Nt(c,i.attrs),n(i.props)&&Nt(c,i.props);var f=new Tt(i,c,a,o,t),p=s.render.call(null,f._c,f);if(p instanceof pe)return Et(p,i,f.parent,s);if(Array.isArray(p)){for(var d=at(p)||[],v=new Array(d.length),h=0;h<d.length;h++)v[h]=Et(d[h],i,f.parent,s);return v}}(i,d,a,s,c);var v=a.on;if(a.on=a.nativeOn,r(i.options.abstract)){var m=a.slot;a={},m&&(a.slot=m)}!function(e){for(var t=e.hook||(e.hook={}),n=0;n<Dt.length;n++){var r=Dt[n],i=t[r],o=jt[r];i===o||i&&i._merged||(t[r]=i?Mt(o,i):o)}}(a);var y=i.options.name||l;return new pe("vue-component-"+i.cid+(y?"-"+y:""),a,void 0,void 0,void 0,s,{Ctor:i,propsData:d,listeners:v,tag:l,children:c},p)}}}function Mt(e,t){var n=function(n,r){e(n,r),t(n,r)};return n._merged=!0,n}var It=1,Ft=2;function Pt(e,a,s,c,u,l){return(Array.isArray(s)||i(s))&&(u=c,c=s,s=void 0),r(l)&&(u=Ft),function(e,i,a,s,c){if(n(a)&&n(a.__ob__))return ve();n(a)&&n(a.is)&&(i=a.is);if(!i)return ve();Array.isArray(s)&&"function"==typeof s[0]&&((a=a||{}).scopedSlots={default:s[0]},s.length=0);c===Ft?s=at(s):c===It&&(s=function(e){for(var t=0;t<e.length;t++)if(Array.isArray(e[t]))return Array.prototype.concat.apply([],e);return e}(s));var u,l;if("string"==typeof i){var f;l=e.$vnode&&e.$vnode.ns||F.getTagNamespace(i),u=F.isReservedTag(i)?new pe(F.parsePlatformTagName(i),a,s,void 0,void 0,e):a&&a.pre||!n(f=Le(e.$options,"components",i))?new pe(i,a,s,void 0,void 0,e):Lt(f,a,e,s,i)}else u=Lt(i,a,e,s);return Array.isArray(u)?u:n(u)?(n(l)&&function e(i,o,a){i.ns=o;"foreignObject"===i.tag&&(o=void 0,a=!0);if(n(i.children))for(var s=0,c=i.children.length;s<c;s++){var u=i.children[s];n(u.tag)&&(t(u.ns)||r(a)&&"svg"!==u.tag)&&e(u,o,a)}}(u,l),n(a)&&function(e){o(e.style)&&et(e.style);o(e.class)&&et(e.class)}(a),u):ve()}(e,a,s,c,u)}var Rt,Ht=null;function Bt(e,t){return(e.__esModule||oe&&"Module"===e[Symbol.toStringTag])&&(e=e.default),o(e)?t.extend(e):e}function Ut(e){return e.isComment&&e.asyncFactory}function zt(e){if(Array.isArray(e))for(var t=0;t<e.length;t++){var r=e[t];if(n(r)&&(n(r.componentOptions)||Ut(r)))return r}}function Vt(e,t){Rt.$on(e,t)}function Kt(e,t){Rt.$off(e,t)}function Jt(e,t){var n=Rt;return function r(){null!==t.apply(null,arguments)&&n.$off(e,r)}}function qt(e,t,n){Rt=e,rt(t,n||{},Vt,Kt,Jt,e),Rt=void 0}var Wt=null;function Zt(e){var t=Wt;return Wt=e,function(){Wt=t}}function Gt(e){for(;e&&(e=e.$parent);)if(e._inactive)return!0;return!1}function Xt(e,t){if(t){if(e._directInactive=!1,Gt(e))return}else if(e._directInactive)return;if(e._inactive||null===e._inactive){e._inactive=!1;for(var n=0;n<e.$children.length;n++)Xt(e.$children[n]);Yt(e,"activated")}}function Yt(e,t){le();var n=e.$options[t],r=t+" hook";if(n)for(var i=0,o=n.length;i<o;i++)He(n[i],e,null,e,r);e._hasHookEvent&&e.$emit("hook:"+t),fe()}var Qt=[],en=[],tn={},nn=!1,rn=!1,on=0;var an=0,sn=Date.now;if(z&&!q){var cn=window.performance;cn&&"function"==typeof cn.now&&sn()>document.createEvent("Event").timeStamp&&(sn=function(){return cn.now()})}function un(){var e,t;for(an=sn(),rn=!0,Qt.sort(function(e,t){return e.id-t.id}),on=0;on<Qt.length;on++)(e=Qt[on]).before&&e.before(),t=e.id,tn[t]=null,e.run();var n=en.slice(),r=Qt.slice();on=Qt.length=en.length=0,tn={},nn=rn=!1,function(e){for(var t=0;t<e.length;t++)e[t]._inactive=!0,Xt(e[t],!0)}(n),function(e){var t=e.length;for(;t--;){var n=e[t],r=n.vm;r._watcher===n&&r._isMounted&&!r._isDestroyed&&Yt(r,"updated")}}(r),ne&&F.devtools&&ne.emit("flush")}var ln=0,fn=function(e,t,n,r,i){this.vm=e,i&&(e._watcher=this),e._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++ln,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new ie,this.newDepIds=new ie,this.expression="","function"==typeof t?this.getter=t:(this.getter=function(e){if(!H.test(e)){var t=e.split(".");return function(e){for(var n=0;n<t.length;n++){if(!e)return;e=e[t[n]]}return e}}}(t),this.getter||(this.getter=S)),this.value=this.lazy?void 0:this.get()};fn.prototype.get=function(){var e;le(this);var t=this.vm;try{e=this.getter.call(t,t)}catch(e){if(!this.user)throw e;Re(e,t,'getter for watcher "'+this.expression+'"')}finally{this.deep&&et(e),fe(),this.cleanupDeps()}return e},fn.prototype.addDep=function(e){var t=e.id;this.newDepIds.has(t)||(this.newDepIds.add(t),this.newDeps.push(e),this.depIds.has(t)||e.addSub(this))},fn.prototype.cleanupDeps=function(){for(var e=this.deps.length;e--;){var t=this.deps[e];this.newDepIds.has(t.id)||t.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},fn.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():function(e){var t=e.id;if(null==tn[t]){if(tn[t]=!0,rn){for(var n=Qt.length-1;n>on&&Qt[n].id>e.id;)n--;Qt.splice(n+1,0,e)}else Qt.push(e);nn||(nn=!0,Ye(un))}}(this)},fn.prototype.run=function(){if(this.active){var e=this.get();if(e!==this.value||o(e)||this.deep){var t=this.value;if(this.value=e,this.user)try{this.cb.call(this.vm,e,t)}catch(e){Re(e,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,e,t)}}},fn.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},fn.prototype.depend=function(){for(var e=this.deps.length;e--;)this.deps[e].depend()},fn.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var e=this.deps.length;e--;)this.deps[e].removeSub(this);this.active=!1}};var pn={enumerable:!0,configurable:!0,get:S,set:S};function dn(e,t,n){pn.get=function(){return this[t][n]},pn.set=function(e){this[t][n]=e},Object.defineProperty(e,n,pn)}function vn(e){e._watchers=[];var t=e.$options;t.props&&function(e,t){var n=e.$options.propsData||{},r=e._props={},i=e.$options._propKeys=[];e.$parent&&$e(!1);var o=function(o){i.push(o);var a=Me(o,t,n,e);xe(r,o,a),o in e||dn(e,"_props",o)};for(var a in t)o(a);$e(!0)}(e,t.props),t.methods&&function(e,t){e.$options.props;for(var n in t)e[n]="function"!=typeof t[n]?S:x(t[n],e)}(e,t.methods),t.data?function(e){var t=e.$options.data;s(t=e._data="function"==typeof t?function(e,t){le();try{return e.call(t,t)}catch(e){return Re(e,t,"data()"),{}}finally{fe()}}(t,e):t||{})||(t={});var n=Object.keys(t),r=e.$options.props,i=(e.$options.methods,n.length);for(;i--;){var o=n[i];r&&y(r,o)||(a=void 0,36!==(a=(o+"").charCodeAt(0))&&95!==a&&dn(e,"_data",o))}var a;Ce(t,!0)}(e):Ce(e._data={},!0),t.computed&&function(e,t){var n=e._computedWatchers=Object.create(null),r=te();for(var i in t){var o=t[i],a="function"==typeof o?o:o.get;r||(n[i]=new fn(e,a||S,S,hn)),i in e||mn(e,i,o)}}(e,t.computed),t.watch&&t.watch!==Y&&function(e,t){for(var n in t){var r=t[n];if(Array.isArray(r))for(var i=0;i<r.length;i++)_n(e,n,r[i]);else _n(e,n,r)}}(e,t.watch)}var hn={lazy:!0};function mn(e,t,n){var r=!te();"function"==typeof n?(pn.get=r?yn(t):gn(n),pn.set=S):(pn.get=n.get?r&&!1!==n.cache?yn(t):gn(n.get):S,pn.set=n.set||S),Object.defineProperty(e,t,pn)}function yn(e){return function(){var t=this._computedWatchers&&this._computedWatchers[e];if(t)return t.dirty&&t.evaluate(),ce.target&&t.depend(),t.value}}function gn(e){return function(){return e.call(this,this)}}function _n(e,t,n,r){return s(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=e[n]),e.$watch(t,n,r)}var bn=0;function $n(e){var t=e.options;if(e.super){var n=$n(e.super);if(n!==e.superOptions){e.superOptions=n;var r=function(e){var t,n=e.options,r=e.sealedOptions;for(var i in n)n[i]!==r[i]&&(t||(t={}),t[i]=n[i]);return t}(e);r&&A(e.extendOptions,r),(t=e.options=De(n,e.extendOptions)).name&&(t.components[t.name]=e)}}return t}function wn(e){this._init(e)}function Cn(e){e.cid=0;var t=1;e.extend=function(e){e=e||{};var n=this,r=n.cid,i=e._Ctor||(e._Ctor={});if(i[r])return i[r];var o=e.name||n.options.name,a=function(e){this._init(e)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=t++,a.options=De(n.options,e),a.super=n,a.options.props&&function(e){var t=e.options.props;for(var n in t)dn(e.prototype,"_props",n)}(a),a.options.computed&&function(e){var t=e.options.computed;for(var n in t)mn(e.prototype,n,t[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,M.forEach(function(e){a[e]=n[e]}),o&&(a.options.components[o]=a),a.superOptions=n.options,a.extendOptions=e,a.sealedOptions=A({},a.options),i[r]=a,a}}function xn(e){return e&&(e.Ctor.options.name||e.tag)}function kn(e,t){return Array.isArray(e)?e.indexOf(t)>-1:"string"==typeof e?e.split(",").indexOf(t)>-1:(n=e,"[object RegExp]"===a.call(n)&&e.test(t));var n}function An(e,t){var n=e.cache,r=e.keys,i=e._vnode;for(var o in n){var a=n[o];if(a){var s=xn(a.componentOptions);s&&!t(s)&&On(n,o,r,i)}}}function On(e,t,n,r){var i=e[t];!i||r&&i.tag===r.tag||i.componentInstance.$destroy(),e[t]=null,h(n,t)}!function(t){t.prototype._init=function(t){var n=this;n._uid=bn++,n._isVue=!0,t&&t._isComponent?function(e,t){var n=e.$options=Object.create(e.constructor.options),r=t._parentVnode;n.parent=t.parent,n._parentVnode=r;var i=r.componentOptions;n.propsData=i.propsData,n._parentListeners=i.listeners,n._renderChildren=i.children,n._componentTag=i.tag,t.render&&(n.render=t.render,n.staticRenderFns=t.staticRenderFns)}(n,t):n.$options=De($n(n.constructor),t||{},n),n._renderProxy=n,n._self=n,function(e){var t=e.$options,n=t.parent;if(n&&!t.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(e)}e.$parent=n,e.$root=n?n.$root:e,e.$children=[],e.$refs={},e._watcher=null,e._inactive=null,e._directInactive=!1,e._isMounted=!1,e._isDestroyed=!1,e._isBeingDestroyed=!1}(n),function(e){e._events=Object.create(null),e._hasHookEvent=!1;var t=e.$options._parentListeners;t&&qt(e,t)}(n),function(t){t._vnode=null,t._staticTrees=null;var n=t.$options,r=t.$vnode=n._parentVnode,i=r&&r.context;t.$slots=ut(n._renderChildren,i),t.$scopedSlots=e,t._c=function(e,n,r,i){return Pt(t,e,n,r,i,!1)},t.$createElement=function(e,n,r,i){return Pt(t,e,n,r,i,!0)};var o=r&&r.data;xe(t,"$attrs",o&&o.attrs||e,null,!0),xe(t,"$listeners",n._parentListeners||e,null,!0)}(n),Yt(n,"beforeCreate"),function(e){var t=ct(e.$options.inject,e);t&&($e(!1),Object.keys(t).forEach(function(n){xe(e,n,t[n])}),$e(!0))}(n),vn(n),function(e){var t=e.$options.provide;t&&(e._provided="function"==typeof t?t.call(e):t)}(n),Yt(n,"created"),n.$options.el&&n.$mount(n.$options.el)}}(wn),function(e){var t={get:function(){return this._data}},n={get:function(){return this._props}};Object.defineProperty(e.prototype,"$data",t),Object.defineProperty(e.prototype,"$props",n),e.prototype.$set=ke,e.prototype.$delete=Ae,e.prototype.$watch=function(e,t,n){if(s(t))return _n(this,e,t,n);(n=n||{}).user=!0;var r=new fn(this,e,t,n);if(n.immediate)try{t.call(this,r.value)}catch(e){Re(e,this,'callback for immediate watcher "'+r.expression+'"')}return function(){r.teardown()}}}(wn),function(e){var t=/^hook:/;e.prototype.$on=function(e,n){var r=this;if(Array.isArray(e))for(var i=0,o=e.length;i<o;i++)r.$on(e[i],n);else(r._events[e]||(r._events[e]=[])).push(n),t.test(e)&&(r._hasHookEvent=!0);return r},e.prototype.$once=function(e,t){var n=this;function r(){n.$off(e,r),t.apply(n,arguments)}return r.fn=t,n.$on(e,r),n},e.prototype.$off=function(e,t){var n=this;if(!arguments.length)return n._events=Object.create(null),n;if(Array.isArray(e)){for(var r=0,i=e.length;r<i;r++)n.$off(e[r],t);return n}var o,a=n._events[e];if(!a)return n;if(!t)return n._events[e]=null,n;for(var s=a.length;s--;)if((o=a[s])===t||o.fn===t){a.splice(s,1);break}return n},e.prototype.$emit=function(e){var t=this._events[e];if(t){t=t.length>1?k(t):t;for(var n=k(arguments,1),r='event handler for "'+e+'"',i=0,o=t.length;i<o;i++)He(t[i],this,n,this,r)}return this}}(wn),function(e){e.prototype._update=function(e,t){var n=this,r=n.$el,i=n._vnode,o=Zt(n);n._vnode=e,n.$el=i?n.__patch__(i,e):n.__patch__(n.$el,e,t,!1),o(),r&&(r.__vue__=null),n.$el&&(n.$el.__vue__=n),n.$vnode&&n.$parent&&n.$vnode===n.$parent._vnode&&(n.$parent.$el=n.$el)},e.prototype.$forceUpdate=function(){this._watcher&&this._watcher.update()},e.prototype.$destroy=function(){var e=this;if(!e._isBeingDestroyed){Yt(e,"beforeDestroy"),e._isBeingDestroyed=!0;var t=e.$parent;!t||t._isBeingDestroyed||e.$options.abstract||h(t.$children,e),e._watcher&&e._watcher.teardown();for(var n=e._watchers.length;n--;)e._watchers[n].teardown();e._data.__ob__&&e._data.__ob__.vmCount--,e._isDestroyed=!0,e.__patch__(e._vnode,null),Yt(e,"destroyed"),e.$off(),e.$el&&(e.$el.__vue__=null),e.$vnode&&(e.$vnode.parent=null)}}}(wn),function(e){St(e.prototype),e.prototype.$nextTick=function(e){return Ye(e,this)},e.prototype._render=function(){var e,t=this,n=t.$options,r=n.render,i=n._parentVnode;i&&(t.$scopedSlots=ft(i.data.scopedSlots,t.$slots,t.$scopedSlots)),t.$vnode=i;try{Ht=t,e=r.call(t._renderProxy,t.$createElement)}catch(n){Re(n,t,"render"),e=t._vnode}finally{Ht=null}return Array.isArray(e)&&1===e.length&&(e=e[0]),e instanceof pe||(e=ve()),e.parent=i,e}}(wn);var Sn=[String,RegExp,Array],Tn={KeepAlive:{name:"keep-alive",abstract:!0,props:{include:Sn,exclude:Sn,max:[String,Number]},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var e in this.cache)On(this.cache,e,this.keys)},mounted:function(){var e=this;this.$watch("include",function(t){An(e,function(e){return kn(t,e)})}),this.$watch("exclude",function(t){An(e,function(e){return!kn(t,e)})})},render:function(){var e=this.$slots.default,t=zt(e),n=t&&t.componentOptions;if(n){var r=xn(n),i=this.include,o=this.exclude;if(i&&(!r||!kn(i,r))||o&&r&&kn(o,r))return t;var a=this.cache,s=this.keys,c=null==t.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):t.key;a[c]?(t.componentInstance=a[c].componentInstance,h(s,c),s.push(c)):(a[c]=t,s.push(c),this.max&&s.length>parseInt(this.max)&&On(a,s[0],s,this._vnode)),t.data.keepAlive=!0}return t||e&&e[0]}}};!function(e){var t={get:function(){return F}};Object.defineProperty(e,"config",t),e.util={warn:ae,extend:A,mergeOptions:De,defineReactive:xe},e.set=ke,e.delete=Ae,e.nextTick=Ye,e.observable=function(e){return Ce(e),e},e.options=Object.create(null),M.forEach(function(t){e.options[t+"s"]=Object.create(null)}),e.options._base=e,A(e.options.components,Tn),function(e){e.use=function(e){var t=this._installedPlugins||(this._installedPlugins=[]);if(t.indexOf(e)>-1)return this;var n=k(arguments,1);return n.unshift(this),"function"==typeof e.install?e.install.apply(e,n):"function"==typeof e&&e.apply(null,n),t.push(e),this}}(e),function(e){e.mixin=function(e){return this.options=De(this.options,e),this}}(e),Cn(e),function(e){M.forEach(function(t){e[t]=function(e,n){return n?("component"===t&&s(n)&&(n.name=n.name||e,n=this.options._base.extend(n)),"directive"===t&&"function"==typeof n&&(n={bind:n,update:n}),this.options[t+"s"][e]=n,n):this.options[t+"s"][e]}})}(e)}(wn),Object.defineProperty(wn.prototype,"$isServer",{get:te}),Object.defineProperty(wn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(wn,"FunctionalRenderContext",{value:Tt}),wn.version="2.6.11";var En=p("style,class"),Nn=p("input,textarea,option,select,progress"),jn=function(e,t,n){return"value"===n&&Nn(e)&&"button"!==t||"selected"===n&&"option"===e||"checked"===n&&"input"===e||"muted"===n&&"video"===e},Dn=p("contenteditable,draggable,spellcheck"),Ln=p("events,caret,typing,plaintext-only"),Mn=function(e,t){return Hn(t)||"false"===t?"false":"contenteditable"===e&&Ln(t)?t:"true"},In=p("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Fn="http://www.w3.org/1999/xlink",Pn=function(e){return":"===e.charAt(5)&&"xlink"===e.slice(0,5)},Rn=function(e){return Pn(e)?e.slice(6,e.length):""},Hn=function(e){return null==e||!1===e};function Bn(e){for(var t=e.data,r=e,i=e;n(i.componentInstance);)(i=i.componentInstance._vnode)&&i.data&&(t=Un(i.data,t));for(;n(r=r.parent);)r&&r.data&&(t=Un(t,r.data));return function(e,t){if(n(e)||n(t))return zn(e,Vn(t));return""}(t.staticClass,t.class)}function Un(e,t){return{staticClass:zn(e.staticClass,t.staticClass),class:n(e.class)?[e.class,t.class]:t.class}}function zn(e,t){return e?t?e+" "+t:e:t||""}function Vn(e){return Array.isArray(e)?function(e){for(var t,r="",i=0,o=e.length;i<o;i++)n(t=Vn(e[i]))&&""!==t&&(r&&(r+=" "),r+=t);return r}(e):o(e)?function(e){var t="";for(var n in e)e[n]&&(t&&(t+=" "),t+=n);return t}(e):"string"==typeof e?e:""}var Kn={svg:"http://www.w3.org/2000/svg",math:"http://www.w3.org/1998/Math/MathML"},Jn=p("html,body,base,head,link,meta,style,title,address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,output,progress,select,textarea,details,dialog,menu,menuitem,summary,content,element,shadow,template,blockquote,iframe,tfoot"),qn=p("svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view",!0),Wn=function(e){return Jn(e)||qn(e)};function Zn(e){return qn(e)?"svg":"math"===e?"math":void 0}var Gn=Object.create(null);var Xn=p("text,number,password,search,email,tel,url");function Yn(e){if("string"==typeof e){var t=document.querySelector(e);return t||document.createElement("div")}return e}var Qn=Object.freeze({createElement:function(e,t){var n=document.createElement(e);return"select"!==e?n:(t.data&&t.data.attrs&&void 0!==t.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)},createElementNS:function(e,t){return document.createElementNS(Kn[e],t)},createTextNode:function(e){return document.createTextNode(e)},createComment:function(e){return document.createComment(e)},insertBefore:function(e,t,n){e.insertBefore(t,n)},removeChild:function(e,t){e.removeChild(t)},appendChild:function(e,t){e.appendChild(t)},parentNode:function(e){return e.parentNode},nextSibling:function(e){return e.nextSibling},tagName:function(e){return e.tagName},setTextContent:function(e,t){e.textContent=t},setStyleScope:function(e,t){e.setAttribute(t,"")}}),er={create:function(e,t){tr(t)},update:function(e,t){e.data.ref!==t.data.ref&&(tr(e,!0),tr(t))},destroy:function(e){tr(e,!0)}};function tr(e,t){var r=e.data.ref;if(n(r)){var i=e.context,o=e.componentInstance||e.elm,a=i.$refs;t?Array.isArray(a[r])?h(a[r],o):a[r]===o&&(a[r]=void 0):e.data.refInFor?Array.isArray(a[r])?a[r].indexOf(o)<0&&a[r].push(o):a[r]=[o]:a[r]=o}}var nr=new pe("",{},[]),rr=["create","activate","update","remove","destroy"];function ir(e,i){return e.key===i.key&&(e.tag===i.tag&&e.isComment===i.isComment&&n(e.data)===n(i.data)&&function(e,t){if("input"!==e.tag)return!0;var r,i=n(r=e.data)&&n(r=r.attrs)&&r.type,o=n(r=t.data)&&n(r=r.attrs)&&r.type;return i===o||Xn(i)&&Xn(o)}(e,i)||r(e.isAsyncPlaceholder)&&e.asyncFactory===i.asyncFactory&&t(i.asyncFactory.error))}function or(e,t,r){var i,o,a={};for(i=t;i<=r;++i)n(o=e[i].key)&&(a[o]=i);return a}var ar={create:sr,update:sr,destroy:function(e){sr(e,nr)}};function sr(e,t){(e.data.directives||t.data.directives)&&function(e,t){var n,r,i,o=e===nr,a=t===nr,s=ur(e.data.directives,e.context),c=ur(t.data.directives,t.context),u=[],l=[];for(n in c)r=s[n],i=c[n],r?(i.oldValue=r.value,i.oldArg=r.arg,fr(i,"update",t,e),i.def&&i.def.componentUpdated&&l.push(i)):(fr(i,"bind",t,e),i.def&&i.def.inserted&&u.push(i));if(u.length){var f=function(){for(var n=0;n<u.length;n++)fr(u[n],"inserted",t,e)};o?it(t,"insert",f):f()}l.length&&it(t,"postpatch",function(){for(var n=0;n<l.length;n++)fr(l[n],"componentUpdated",t,e)});if(!o)for(n in s)c[n]||fr(s[n],"unbind",e,e,a)}(e,t)}var cr=Object.create(null);function ur(e,t){var n,r,i=Object.create(null);if(!e)return i;for(n=0;n<e.length;n++)(r=e[n]).modifiers||(r.modifiers=cr),i[lr(r)]=r,r.def=Le(t.$options,"directives",r.name);return i}function lr(e){return e.rawName||e.name+"."+Object.keys(e.modifiers||{}).join(".")}function fr(e,t,n,r,i){var o=e.def&&e.def[t];if(o)try{o(n.elm,e,n,r,i)}catch(r){Re(r,n.context,"directive "+e.name+" "+t+" hook")}}var pr=[er,ar];function dr(e,r){var i=r.componentOptions;if(!(n(i)&&!1===i.Ctor.options.inheritAttrs||t(e.data.attrs)&&t(r.data.attrs))){var o,a,s=r.elm,c=e.data.attrs||{},u=r.data.attrs||{};for(o in n(u.__ob__)&&(u=r.data.attrs=A({},u)),u)a=u[o],c[o]!==a&&vr(s,o,a);for(o in(q||Z)&&u.value!==c.value&&vr(s,"value",u.value),c)t(u[o])&&(Pn(o)?s.removeAttributeNS(Fn,Rn(o)):Dn(o)||s.removeAttribute(o))}}function vr(e,t,n){e.tagName.indexOf("-")>-1?hr(e,t,n):In(t)?Hn(n)?e.removeAttribute(t):(n="allowfullscreen"===t&&"EMBED"===e.tagName?"true":t,e.setAttribute(t,n)):Dn(t)?e.setAttribute(t,Mn(t,n)):Pn(t)?Hn(n)?e.removeAttributeNS(Fn,Rn(t)):e.setAttributeNS(Fn,t,n):hr(e,t,n)}function hr(e,t,n){if(Hn(n))e.removeAttribute(t);else{if(q&&!W&&"TEXTAREA"===e.tagName&&"placeholder"===t&&""!==n&&!e.__ieph){var r=function(t){t.stopImmediatePropagation(),e.removeEventListener("input",r)};e.addEventListener("input",r),e.__ieph=!0}e.setAttribute(t,n)}}var mr={create:dr,update:dr};function yr(e,r){var i=r.elm,o=r.data,a=e.data;if(!(t(o.staticClass)&&t(o.class)&&(t(a)||t(a.staticClass)&&t(a.class)))){var s=Bn(r),c=i._transitionClasses;n(c)&&(s=zn(s,Vn(c))),s!==i._prevClass&&(i.setAttribute("class",s),i._prevClass=s)}}var gr,_r,br,$r,wr,Cr,xr={create:yr,update:yr},kr=/[\w).+\-_$\]]/;function Ar(e){var t,n,r,i,o,a=!1,s=!1,c=!1,u=!1,l=0,f=0,p=0,d=0;for(r=0;r<e.length;r++)if(n=t,t=e.charCodeAt(r),a)39===t&&92!==n&&(a=!1);else if(s)34===t&&92!==n&&(s=!1);else if(c)96===t&&92!==n&&(c=!1);else if(u)47===t&&92!==n&&(u=!1);else if(124!==t||124===e.charCodeAt(r+1)||124===e.charCodeAt(r-1)||l||f||p){switch(t){case 34:s=!0;break;case 39:a=!0;break;case 96:c=!0;break;case 40:p++;break;case 41:p--;break;case 91:f++;break;case 93:f--;break;case 123:l++;break;case 125:l--}if(47===t){for(var v=r-1,h=void 0;v>=0&&" "===(h=e.charAt(v));v--);h&&kr.test(h)||(u=!0)}}else void 0===i?(d=r+1,i=e.slice(0,r).trim()):m();function m(){(o||(o=[])).push(e.slice(d,r).trim()),d=r+1}if(void 0===i?i=e.slice(0,r).trim():0!==d&&m(),o)for(r=0;r<o.length;r++)i=Or(i,o[r]);return i}function Or(e,t){var n=t.indexOf("(");if(n<0)return'_f("'+t+'")('+e+")";var r=t.slice(0,n),i=t.slice(n+1);return'_f("'+r+'")('+e+(")"!==i?","+i:i)}function Sr(e,t){console.error("[Vue compiler]: "+e)}function Tr(e,t){return e?e.map(function(e){return e[t]}).filter(function(e){return e}):[]}function Er(e,t,n,r,i){(e.props||(e.props=[])).push(Rr({name:t,value:n,dynamic:i},r)),e.plain=!1}function Nr(e,t,n,r,i){(i?e.dynamicAttrs||(e.dynamicAttrs=[]):e.attrs||(e.attrs=[])).push(Rr({name:t,value:n,dynamic:i},r)),e.plain=!1}function jr(e,t,n,r){e.attrsMap[t]=n,e.attrsList.push(Rr({name:t,value:n},r))}function Dr(e,t,n,r,i,o,a,s){(e.directives||(e.directives=[])).push(Rr({name:t,rawName:n,value:r,arg:i,isDynamicArg:o,modifiers:a},s)),e.plain=!1}function Lr(e,t,n){return n?"_p("+t+',"'+e+'")':e+t}function Mr(t,n,r,i,o,a,s,c){var u;(i=i||e).right?c?n="("+n+")==='click'?'contextmenu':("+n+")":"click"===n&&(n="contextmenu",delete i.right):i.middle&&(c?n="("+n+")==='click'?'mouseup':("+n+")":"click"===n&&(n="mouseup")),i.capture&&(delete i.capture,n=Lr("!",n,c)),i.once&&(delete i.once,n=Lr("~",n,c)),i.passive&&(delete i.passive,n=Lr("&",n,c)),i.native?(delete i.native,u=t.nativeEvents||(t.nativeEvents={})):u=t.events||(t.events={});var l=Rr({value:r.trim(),dynamic:c},s);i!==e&&(l.modifiers=i);var f=u[n];Array.isArray(f)?o?f.unshift(l):f.push(l):u[n]=f?o?[l,f]:[f,l]:l,t.plain=!1}function Ir(e,t,n){var r=Fr(e,":"+t)||Fr(e,"v-bind:"+t);if(null!=r)return Ar(r);if(!1!==n){var i=Fr(e,t);if(null!=i)return JSON.stringify(i)}}function Fr(e,t,n){var r;if(null!=(r=e.attrsMap[t]))for(var i=e.attrsList,o=0,a=i.length;o<a;o++)if(i[o].name===t){i.splice(o,1);break}return n&&delete e.attrsMap[t],r}function Pr(e,t){for(var n=e.attrsList,r=0,i=n.length;r<i;r++){var o=n[r];if(t.test(o.name))return n.splice(r,1),o}}function Rr(e,t){return t&&(null!=t.start&&(e.start=t.start),null!=t.end&&(e.end=t.end)),e}function Hr(e,t,n){var r=n||{},i=r.number,o="$$v";r.trim&&(o="(typeof $$v === 'string'? $$v.trim(): $$v)"),i&&(o="_n("+o+")");var a=Br(t,o);e.model={value:"("+t+")",expression:JSON.stringify(t),callback:"function ($$v) {"+a+"}"}}function Br(e,t){var n=function(e){if(e=e.trim(),gr=e.length,e.indexOf("[")<0||e.lastIndexOf("]")<gr-1)return($r=e.lastIndexOf("."))>-1?{exp:e.slice(0,$r),key:'"'+e.slice($r+1)+'"'}:{exp:e,key:null};_r=e,$r=wr=Cr=0;for(;!zr();)Vr(br=Ur())?Jr(br):91===br&&Kr(br);return{exp:e.slice(0,wr),key:e.slice(wr+1,Cr)}}(e);return null===n.key?e+"="+t:"$set("+n.exp+", "+n.key+", "+t+")"}function Ur(){return _r.charCodeAt(++$r)}function zr(){return $r>=gr}function Vr(e){return 34===e||39===e}function Kr(e){var t=1;for(wr=$r;!zr();)if(Vr(e=Ur()))Jr(e);else if(91===e&&t++,93===e&&t--,0===t){Cr=$r;break}}function Jr(e){for(var t=e;!zr()&&(e=Ur())!==t;);}var qr,Wr="__r",Zr="__c";function Gr(e,t,n){var r=qr;return function i(){null!==t.apply(null,arguments)&&Qr(e,i,n,r)}}var Xr=Ve&&!(X&&Number(X[1])<=53);function Yr(e,t,n,r){if(Xr){var i=an,o=t;t=o._wrapper=function(e){if(e.target===e.currentTarget||e.timeStamp>=i||e.timeStamp<=0||e.target.ownerDocument!==document)return o.apply(this,arguments)}}qr.addEventListener(e,t,Q?{capture:n,passive:r}:n)}function Qr(e,t,n,r){(r||qr).removeEventListener(e,t._wrapper||t,n)}function ei(e,r){if(!t(e.data.on)||!t(r.data.on)){var i=r.data.on||{},o=e.data.on||{};qr=r.elm,function(e){if(n(e[Wr])){var t=q?"change":"input";e[t]=[].concat(e[Wr],e[t]||[]),delete e[Wr]}n(e[Zr])&&(e.change=[].concat(e[Zr],e.change||[]),delete e[Zr])}(i),rt(i,o,Yr,Qr,Gr,r.context),qr=void 0}}var ti,ni={create:ei,update:ei};function ri(e,r){if(!t(e.data.domProps)||!t(r.data.domProps)){var i,o,a=r.elm,s=e.data.domProps||{},c=r.data.domProps||{};for(i in n(c.__ob__)&&(c=r.data.domProps=A({},c)),s)i in c||(a[i]="");for(i in c){if(o=c[i],"textContent"===i||"innerHTML"===i){if(r.children&&(r.children.length=0),o===s[i])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===i&&"PROGRESS"!==a.tagName){a._value=o;var u=t(o)?"":String(o);ii(a,u)&&(a.value=u)}else if("innerHTML"===i&&qn(a.tagName)&&t(a.innerHTML)){(ti=ti||document.createElement("div")).innerHTML="<svg>"+o+"</svg>";for(var l=ti.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else if(o!==s[i])try{a[i]=o}catch(e){}}}}function ii(e,t){return!e.composing&&("OPTION"===e.tagName||function(e,t){var n=!0;try{n=document.activeElement!==e}catch(e){}return n&&e.value!==t}(e,t)||function(e,t){var r=e.value,i=e._vModifiers;if(n(i)){if(i.number)return f(r)!==f(t);if(i.trim)return r.trim()!==t.trim()}return r!==t}(e,t))}var oi={create:ri,update:ri},ai=g(function(e){var t={},n=/:(.+)/;return e.split(/;(?![^(]*\))/g).forEach(function(e){if(e){var r=e.split(n);r.length>1&&(t[r[0].trim()]=r[1].trim())}}),t});function si(e){var t=ci(e.style);return e.staticStyle?A(e.staticStyle,t):t}function ci(e){return Array.isArray(e)?O(e):"string"==typeof e?ai(e):e}var ui,li=/^--/,fi=/\s*!important$/,pi=function(e,t,n){if(li.test(t))e.style.setProperty(t,n);else if(fi.test(n))e.style.setProperty(C(t),n.replace(fi,""),"important");else{var r=vi(t);if(Array.isArray(n))for(var i=0,o=n.length;i<o;i++)e.style[r]=n[i];else e.style[r]=n}},di=["Webkit","Moz","ms"],vi=g(function(e){if(ui=ui||document.createElement("div").style,"filter"!==(e=b(e))&&e in ui)return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=0;n<di.length;n++){var r=di[n]+t;if(r in ui)return r}});function hi(e,r){var i=r.data,o=e.data;if(!(t(i.staticStyle)&&t(i.style)&&t(o.staticStyle)&&t(o.style))){var a,s,c=r.elm,u=o.staticStyle,l=o.normalizedStyle||o.style||{},f=u||l,p=ci(r.data.style)||{};r.data.normalizedStyle=n(p.__ob__)?A({},p):p;var d=function(e,t){var n,r={};if(t)for(var i=e;i.componentInstance;)(i=i.componentInstance._vnode)&&i.data&&(n=si(i.data))&&A(r,n);(n=si(e.data))&&A(r,n);for(var o=e;o=o.parent;)o.data&&(n=si(o.data))&&A(r,n);return r}(r,!0);for(s in f)t(d[s])&&pi(c,s,"");for(s in d)(a=d[s])!==f[s]&&pi(c,s,null==a?"":a)}}var mi={create:hi,update:hi},yi=/\s+/;function gi(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(yi).forEach(function(t){return e.classList.add(t)}):e.classList.add(t);else{var n=" "+(e.getAttribute("class")||"")+" ";n.indexOf(" "+t+" ")<0&&e.setAttribute("class",(n+t).trim())}}function _i(e,t){if(t&&(t=t.trim()))if(e.classList)t.indexOf(" ")>-1?t.split(yi).forEach(function(t){return e.classList.remove(t)}):e.classList.remove(t),e.classList.length||e.removeAttribute("class");else{for(var n=" "+(e.getAttribute("class")||"")+" ",r=" "+t+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?e.setAttribute("class",n):e.removeAttribute("class")}}function bi(e){if(e){if("object"==typeof e){var t={};return!1!==e.css&&A(t,$i(e.name||"v")),A(t,e),t}return"string"==typeof e?$i(e):void 0}}var $i=g(function(e){return{enterClass:e+"-enter",enterToClass:e+"-enter-to",enterActiveClass:e+"-enter-active",leaveClass:e+"-leave",leaveToClass:e+"-leave-to",leaveActiveClass:e+"-leave-active"}}),wi=z&&!W,Ci="transition",xi="animation",ki="transition",Ai="transitionend",Oi="animation",Si="animationend";wi&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(ki="WebkitTransition",Ai="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Oi="WebkitAnimation",Si="webkitAnimationEnd"));var Ti=z?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(e){return e()};function Ei(e){Ti(function(){Ti(e)})}function Ni(e,t){var n=e._transitionClasses||(e._transitionClasses=[]);n.indexOf(t)<0&&(n.push(t),gi(e,t))}function ji(e,t){e._transitionClasses&&h(e._transitionClasses,t),_i(e,t)}function Di(e,t,n){var r=Mi(e,t),i=r.type,o=r.timeout,a=r.propCount;if(!i)return n();var s=i===Ci?Ai:Si,c=0,u=function(){e.removeEventListener(s,l),n()},l=function(t){t.target===e&&++c>=a&&u()};setTimeout(function(){c<a&&u()},o+1),e.addEventListener(s,l)}var Li=/\b(transform|all)(,|$)/;function Mi(e,t){var n,r=window.getComputedStyle(e),i=(r[ki+"Delay"]||"").split(", "),o=(r[ki+"Duration"]||"").split(", "),a=Ii(i,o),s=(r[Oi+"Delay"]||"").split(", "),c=(r[Oi+"Duration"]||"").split(", "),u=Ii(s,c),l=0,f=0;return t===Ci?a>0&&(n=Ci,l=a,f=o.length):t===xi?u>0&&(n=xi,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?Ci:xi:null)?n===Ci?o.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===Ci&&Li.test(r[ki+"Property"])}}function Ii(e,t){for(;e.length<t.length;)e=e.concat(e);return Math.max.apply(null,t.map(function(t,n){return Fi(t)+Fi(e[n])}))}function Fi(e){return 1e3*Number(e.slice(0,-1).replace(",","."))}function Pi(e,r){var i=e.elm;n(i._leaveCb)&&(i._leaveCb.cancelled=!0,i._leaveCb());var a=bi(e.data.transition);if(!t(a)&&!n(i._enterCb)&&1===i.nodeType){for(var s=a.css,c=a.type,u=a.enterClass,l=a.enterToClass,p=a.enterActiveClass,d=a.appearClass,v=a.appearToClass,h=a.appearActiveClass,m=a.beforeEnter,y=a.enter,g=a.afterEnter,_=a.enterCancelled,b=a.beforeAppear,$=a.appear,w=a.afterAppear,C=a.appearCancelled,x=a.duration,k=Wt,A=Wt.$vnode;A&&A.parent;)k=A.context,A=A.parent;var O=!k._isMounted||!e.isRootInsert;if(!O||$||""===$){var S=O&&d?d:u,T=O&&h?h:p,E=O&&v?v:l,N=O&&b||m,j=O&&"function"==typeof $?$:y,L=O&&w||g,M=O&&C||_,I=f(o(x)?x.enter:x),F=!1!==s&&!W,P=Bi(j),R=i._enterCb=D(function(){F&&(ji(i,E),ji(i,T)),R.cancelled?(F&&ji(i,S),M&&M(i)):L&&L(i),i._enterCb=null});e.data.show||it(e,"insert",function(){var t=i.parentNode,n=t&&t._pending&&t._pending[e.key];n&&n.tag===e.tag&&n.elm._leaveCb&&n.elm._leaveCb(),j&&j(i,R)}),N&&N(i),F&&(Ni(i,S),Ni(i,T),Ei(function(){ji(i,S),R.cancelled||(Ni(i,E),P||(Hi(I)?setTimeout(R,I):Di(i,c,R)))})),e.data.show&&(r&&r(),j&&j(i,R)),F||P||R()}}}function Ri(e,r){var i=e.elm;n(i._enterCb)&&(i._enterCb.cancelled=!0,i._enterCb());var a=bi(e.data.transition);if(t(a)||1!==i.nodeType)return r();if(!n(i._leaveCb)){var s=a.css,c=a.type,u=a.leaveClass,l=a.leaveToClass,p=a.leaveActiveClass,d=a.beforeLeave,v=a.leave,h=a.afterLeave,m=a.leaveCancelled,y=a.delayLeave,g=a.duration,_=!1!==s&&!W,b=Bi(v),$=f(o(g)?g.leave:g),w=i._leaveCb=D(function(){i.parentNode&&i.parentNode._pending&&(i.parentNode._pending[e.key]=null),_&&(ji(i,l),ji(i,p)),w.cancelled?(_&&ji(i,u),m&&m(i)):(r(),h&&h(i)),i._leaveCb=null});y?y(C):C()}function C(){w.cancelled||(!e.data.show&&i.parentNode&&((i.parentNode._pending||(i.parentNode._pending={}))[e.key]=e),d&&d(i),_&&(Ni(i,u),Ni(i,p),Ei(function(){ji(i,u),w.cancelled||(Ni(i,l),b||(Hi($)?setTimeout(w,$):Di(i,c,w)))})),v&&v(i,w),_||b||w())}}function Hi(e){return"number"==typeof e&&!isNaN(e)}function Bi(e){if(t(e))return!1;var r=e.fns;return n(r)?Bi(Array.isArray(r)?r[0]:r):(e._length||e.length)>1}function Ui(e,t){!0!==t.data.show&&Pi(t)}var zi=function(e){var o,a,s={},c=e.modules,u=e.nodeOps;for(o=0;o<rr.length;++o)for(s[rr[o]]=[],a=0;a<c.length;++a)n(c[a][rr[o]])&&s[rr[o]].push(c[a][rr[o]]);function l(e){var t=u.parentNode(e);n(t)&&u.removeChild(t,e)}function f(e,t,i,o,a,c,l){if(n(e.elm)&&n(c)&&(e=c[l]=me(e)),e.isRootInsert=!a,!function(e,t,i,o){var a=e.data;if(n(a)){var c=n(e.componentInstance)&&a.keepAlive;if(n(a=a.hook)&&n(a=a.init)&&a(e,!1),n(e.componentInstance))return d(e,t),v(i,e.elm,o),r(c)&&function(e,t,r,i){for(var o,a=e;a.componentInstance;)if(a=a.componentInstance._vnode,n(o=a.data)&&n(o=o.transition)){for(o=0;o<s.activate.length;++o)s.activate[o](nr,a);t.push(a);break}v(r,e.elm,i)}(e,t,i,o),!0}}(e,t,i,o)){var f=e.data,p=e.children,m=e.tag;n(m)?(e.elm=e.ns?u.createElementNS(e.ns,m):u.createElement(m,e),g(e),h(e,p,t),n(f)&&y(e,t),v(i,e.elm,o)):r(e.isComment)?(e.elm=u.createComment(e.text),v(i,e.elm,o)):(e.elm=u.createTextNode(e.text),v(i,e.elm,o))}}function d(e,t){n(e.data.pendingInsert)&&(t.push.apply(t,e.data.pendingInsert),e.data.pendingInsert=null),e.elm=e.componentInstance.$el,m(e)?(y(e,t),g(e)):(tr(e),t.push(e))}function v(e,t,r){n(e)&&(n(r)?u.parentNode(r)===e&&u.insertBefore(e,t,r):u.appendChild(e,t))}function h(e,t,n){if(Array.isArray(t))for(var r=0;r<t.length;++r)f(t[r],n,e.elm,null,!0,t,r);else i(e.text)&&u.appendChild(e.elm,u.createTextNode(String(e.text)))}function m(e){for(;e.componentInstance;)e=e.componentInstance._vnode;return n(e.tag)}function y(e,t){for(var r=0;r<s.create.length;++r)s.create[r](nr,e);n(o=e.data.hook)&&(n(o.create)&&o.create(nr,e),n(o.insert)&&t.push(e))}function g(e){var t;if(n(t=e.fnScopeId))u.setStyleScope(e.elm,t);else for(var r=e;r;)n(t=r.context)&&n(t=t.$options._scopeId)&&u.setStyleScope(e.elm,t),r=r.parent;n(t=Wt)&&t!==e.context&&t!==e.fnContext&&n(t=t.$options._scopeId)&&u.setStyleScope(e.elm,t)}function _(e,t,n,r,i,o){for(;r<=i;++r)f(n[r],o,e,t,!1,n,r)}function b(e){var t,r,i=e.data;if(n(i))for(n(t=i.hook)&&n(t=t.destroy)&&t(e),t=0;t<s.destroy.length;++t)s.destroy[t](e);if(n(t=e.children))for(r=0;r<e.children.length;++r)b(e.children[r])}function $(e,t,r){for(;t<=r;++t){var i=e[t];n(i)&&(n(i.tag)?(w(i),b(i)):l(i.elm))}}function w(e,t){if(n(t)||n(e.data)){var r,i=s.remove.length+1;for(n(t)?t.listeners+=i:t=function(e,t){function n(){0==--n.listeners&&l(e)}return n.listeners=t,n}(e.elm,i),n(r=e.componentInstance)&&n(r=r._vnode)&&n(r.data)&&w(r,t),r=0;r<s.remove.length;++r)s.remove[r](e,t);n(r=e.data.hook)&&n(r=r.remove)?r(e,t):t()}else l(e.elm)}function C(e,t,r,i){for(var o=r;o<i;o++){var a=t[o];if(n(a)&&ir(e,a))return o}}function x(e,i,o,a,c,l){if(e!==i){n(i.elm)&&n(a)&&(i=a[c]=me(i));var p=i.elm=e.elm;if(r(e.isAsyncPlaceholder))n(i.asyncFactory.resolved)?O(e.elm,i,o):i.isAsyncPlaceholder=!0;else if(r(i.isStatic)&&r(e.isStatic)&&i.key===e.key&&(r(i.isCloned)||r(i.isOnce)))i.componentInstance=e.componentInstance;else{var d,v=i.data;n(v)&&n(d=v.hook)&&n(d=d.prepatch)&&d(e,i);var h=e.children,y=i.children;if(n(v)&&m(i)){for(d=0;d<s.update.length;++d)s.update[d](e,i);n(d=v.hook)&&n(d=d.update)&&d(e,i)}t(i.text)?n(h)&&n(y)?h!==y&&function(e,r,i,o,a){for(var s,c,l,p=0,d=0,v=r.length-1,h=r[0],m=r[v],y=i.length-1,g=i[0],b=i[y],w=!a;p<=v&&d<=y;)t(h)?h=r[++p]:t(m)?m=r[--v]:ir(h,g)?(x(h,g,o,i,d),h=r[++p],g=i[++d]):ir(m,b)?(x(m,b,o,i,y),m=r[--v],b=i[--y]):ir(h,b)?(x(h,b,o,i,y),w&&u.insertBefore(e,h.elm,u.nextSibling(m.elm)),h=r[++p],b=i[--y]):ir(m,g)?(x(m,g,o,i,d),w&&u.insertBefore(e,m.elm,h.elm),m=r[--v],g=i[++d]):(t(s)&&(s=or(r,p,v)),t(c=n(g.key)?s[g.key]:C(g,r,p,v))?f(g,o,e,h.elm,!1,i,d):ir(l=r[c],g)?(x(l,g,o,i,d),r[c]=void 0,w&&u.insertBefore(e,l.elm,h.elm)):f(g,o,e,h.elm,!1,i,d),g=i[++d]);p>v?_(e,t(i[y+1])?null:i[y+1].elm,i,d,y,o):d>y&&$(r,p,v)}(p,h,y,o,l):n(y)?(n(e.text)&&u.setTextContent(p,""),_(p,null,y,0,y.length-1,o)):n(h)?$(h,0,h.length-1):n(e.text)&&u.setTextContent(p,""):e.text!==i.text&&u.setTextContent(p,i.text),n(v)&&n(d=v.hook)&&n(d=d.postpatch)&&d(e,i)}}}function k(e,t,i){if(r(i)&&n(e.parent))e.parent.data.pendingInsert=t;else for(var o=0;o<t.length;++o)t[o].data.hook.insert(t[o])}var A=p("attrs,class,staticClass,staticStyle,key");function O(e,t,i,o){var a,s=t.tag,c=t.data,u=t.children;if(o=o||c&&c.pre,t.elm=e,r(t.isComment)&&n(t.asyncFactory))return t.isAsyncPlaceholder=!0,!0;if(n(c)&&(n(a=c.hook)&&n(a=a.init)&&a(t,!0),n(a=t.componentInstance)))return d(t,i),!0;if(n(s)){if(n(u))if(e.hasChildNodes())if(n(a=c)&&n(a=a.domProps)&&n(a=a.innerHTML)){if(a!==e.innerHTML)return!1}else{for(var l=!0,f=e.firstChild,p=0;p<u.length;p++){if(!f||!O(f,u[p],i,o)){l=!1;break}f=f.nextSibling}if(!l||f)return!1}else h(t,u,i);if(n(c)){var v=!1;for(var m in c)if(!A(m)){v=!0,y(t,i);break}!v&&c.class&&et(c.class)}}else e.data!==t.text&&(e.data=t.text);return!0}return function(e,i,o,a){if(!t(i)){var c,l=!1,p=[];if(t(e))l=!0,f(i,p);else{var d=n(e.nodeType);if(!d&&ir(e,i))x(e,i,p,null,null,a);else{if(d){if(1===e.nodeType&&e.hasAttribute(L)&&(e.removeAttribute(L),o=!0),r(o)&&O(e,i,p))return k(i,p,!0),e;c=e,e=new pe(u.tagName(c).toLowerCase(),{},[],void 0,c)}var v=e.elm,h=u.parentNode(v);if(f(i,p,v._leaveCb?null:h,u.nextSibling(v)),n(i.parent))for(var y=i.parent,g=m(i);y;){for(var _=0;_<s.destroy.length;++_)s.destroy[_](y);if(y.elm=i.elm,g){for(var w=0;w<s.create.length;++w)s.create[w](nr,y);var C=y.data.hook.insert;if(C.merged)for(var A=1;A<C.fns.length;A++)C.fns[A]()}else tr(y);y=y.parent}n(h)?$([e],0,0):n(e.tag)&&b(e)}}return k(i,p,l),i.elm}n(e)&&b(e)}}({nodeOps:Qn,modules:[mr,xr,ni,oi,mi,z?{create:Ui,activate:Ui,remove:function(e,t){!0!==e.data.show?Ri(e,t):t()}}:{}].concat(pr)});W&&document.addEventListener("selectionchange",function(){var e=document.activeElement;e&&e.vmodel&&Xi(e,"input")});var Vi={inserted:function(e,t,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?it(n,"postpatch",function(){Vi.componentUpdated(e,t,n)}):Ki(e,t,n.context),e._vOptions=[].map.call(e.options,Wi)):("textarea"===n.tag||Xn(e.type))&&(e._vModifiers=t.modifiers,t.modifiers.lazy||(e.addEventListener("compositionstart",Zi),e.addEventListener("compositionend",Gi),e.addEventListener("change",Gi),W&&(e.vmodel=!0)))},componentUpdated:function(e,t,n){if("select"===n.tag){Ki(e,t,n.context);var r=e._vOptions,i=e._vOptions=[].map.call(e.options,Wi);if(i.some(function(e,t){return!N(e,r[t])}))(e.multiple?t.value.some(function(e){return qi(e,i)}):t.value!==t.oldValue&&qi(t.value,i))&&Xi(e,"change")}}};function Ki(e,t,n){Ji(e,t,n),(q||Z)&&setTimeout(function(){Ji(e,t,n)},0)}function Ji(e,t,n){var r=t.value,i=e.multiple;if(!i||Array.isArray(r)){for(var o,a,s=0,c=e.options.length;s<c;s++)if(a=e.options[s],i)o=j(r,Wi(a))>-1,a.selected!==o&&(a.selected=o);else if(N(Wi(a),r))return void(e.selectedIndex!==s&&(e.selectedIndex=s));i||(e.selectedIndex=-1)}}function qi(e,t){return t.every(function(t){return!N(t,e)})}function Wi(e){return"_value"in e?e._value:e.value}function Zi(e){e.target.composing=!0}function Gi(e){e.target.composing&&(e.target.composing=!1,Xi(e.target,"input"))}function Xi(e,t){var n=document.createEvent("HTMLEvents");n.initEvent(t,!0,!0),e.dispatchEvent(n)}function Yi(e){return!e.componentInstance||e.data&&e.data.transition?e:Yi(e.componentInstance._vnode)}var Qi={model:Vi,show:{bind:function(e,t,n){var r=t.value,i=(n=Yi(n)).data&&n.data.transition,o=e.__vOriginalDisplay="none"===e.style.display?"":e.style.display;r&&i?(n.data.show=!0,Pi(n,function(){e.style.display=o})):e.style.display=r?o:"none"},update:function(e,t,n){var r=t.value;!r!=!t.oldValue&&((n=Yi(n)).data&&n.data.transition?(n.data.show=!0,r?Pi(n,function(){e.style.display=e.__vOriginalDisplay}):Ri(n,function(){e.style.display="none"})):e.style.display=r?e.__vOriginalDisplay:"none")},unbind:function(e,t,n,r,i){i||(e.style.display=e.__vOriginalDisplay)}}},eo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function to(e){var t=e&&e.componentOptions;return t&&t.Ctor.options.abstract?to(zt(t.children)):e}function no(e){var t={},n=e.$options;for(var r in n.propsData)t[r]=e[r];var i=n._parentListeners;for(var o in i)t[b(o)]=i[o];return t}function ro(e,t){if(/\d-keep-alive$/.test(t.tag))return e("keep-alive",{props:t.componentOptions.propsData})}var io=function(e){return e.tag||Ut(e)},oo=function(e){return"show"===e.name},ao={name:"transition",props:eo,abstract:!0,render:function(e){var t=this,n=this.$slots.default;if(n&&(n=n.filter(io)).length){var r=this.mode,o=n[0];if(function(e){for(;e=e.parent;)if(e.data.transition)return!0}(this.$vnode))return o;var a=to(o);if(!a)return o;if(this._leaving)return ro(e,o);var s="__transition-"+this._uid+"-";a.key=null==a.key?a.isComment?s+"comment":s+a.tag:i(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key;var c=(a.data||(a.data={})).transition=no(this),u=this._vnode,l=to(u);if(a.data.directives&&a.data.directives.some(oo)&&(a.data.show=!0),l&&l.data&&!function(e,t){return t.key===e.key&&t.tag===e.tag}(a,l)&&!Ut(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=A({},c);if("out-in"===r)return this._leaving=!0,it(f,"afterLeave",function(){t._leaving=!1,t.$forceUpdate()}),ro(e,o);if("in-out"===r){if(Ut(a))return u;var p,d=function(){p()};it(c,"afterEnter",d),it(c,"enterCancelled",d),it(f,"delayLeave",function(e){p=e})}}return o}}},so=A({tag:String,moveClass:String},eo);function co(e){e.elm._moveCb&&e.elm._moveCb(),e.elm._enterCb&&e.elm._enterCb()}function uo(e){e.data.newPos=e.elm.getBoundingClientRect()}function lo(e){var t=e.data.pos,n=e.data.newPos,r=t.left-n.left,i=t.top-n.top;if(r||i){e.data.moved=!0;var o=e.elm.style;o.transform=o.WebkitTransform="translate("+r+"px,"+i+"px)",o.transitionDuration="0s"}}delete so.mode;var fo={Transition:ao,TransitionGroup:{props:so,beforeMount:function(){var e=this,t=this._update;this._update=function(n,r){var i=Zt(e);e.__patch__(e._vnode,e.kept,!1,!0),e._vnode=e.kept,i(),t.call(e,n,r)}},render:function(e){for(var t=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,i=this.$slots.default||[],o=this.children=[],a=no(this),s=0;s<i.length;s++){var c=i[s];c.tag&&null!=c.key&&0!==String(c.key).indexOf("__vlist")&&(o.push(c),n[c.key]=c,(c.data||(c.data={})).transition=a)}if(r){for(var u=[],l=[],f=0;f<r.length;f++){var p=r[f];p.data.transition=a,p.data.pos=p.elm.getBoundingClientRect(),n[p.key]?u.push(p):l.push(p)}this.kept=e(t,null,u),this.removed=l}return e(t,null,o)},updated:function(){var e=this.prevChildren,t=this.moveClass||(this.name||"v")+"-move";e.length&&this.hasMove(e[0].elm,t)&&(e.forEach(co),e.forEach(uo),e.forEach(lo),this._reflow=document.body.offsetHeight,e.forEach(function(e){if(e.data.moved){var n=e.elm,r=n.style;Ni(n,t),r.transform=r.WebkitTransform=r.transitionDuration="",n.addEventListener(Ai,n._moveCb=function e(r){r&&r.target!==n||r&&!/transform$/.test(r.propertyName)||(n.removeEventListener(Ai,e),n._moveCb=null,ji(n,t))})}}))},methods:{hasMove:function(e,t){if(!wi)return!1;if(this._hasMove)return this._hasMove;var n=e.cloneNode();e._transitionClasses&&e._transitionClasses.forEach(function(e){_i(n,e)}),gi(n,t),n.style.display="none",this.$el.appendChild(n);var r=Mi(n);return this.$el.removeChild(n),this._hasMove=r.hasTransform}}}};wn.config.mustUseProp=jn,wn.config.isReservedTag=Wn,wn.config.isReservedAttr=En,wn.config.getTagNamespace=Zn,wn.config.isUnknownElement=function(e){if(!z)return!0;if(Wn(e))return!1;if(e=e.toLowerCase(),null!=Gn[e])return Gn[e];var t=document.createElement(e);return e.indexOf("-")>-1?Gn[e]=t.constructor===window.HTMLUnknownElement||t.constructor===window.HTMLElement:Gn[e]=/HTMLUnknownElement/.test(t.toString())},A(wn.options.directives,Qi),A(wn.options.components,fo),wn.prototype.__patch__=z?zi:S,wn.prototype.$mount=function(e,t){return function(e,t,n){var r;return e.$el=t,e.$options.render||(e.$options.render=ve),Yt(e,"beforeMount"),r=function(){e._update(e._render(),n)},new fn(e,r,S,{before:function(){e._isMounted&&!e._isDestroyed&&Yt(e,"beforeUpdate")}},!0),n=!1,null==e.$vnode&&(e._isMounted=!0,Yt(e,"mounted")),e}(this,e=e&&z?Yn(e):void 0,t)},z&&setTimeout(function(){F.devtools&&ne&&ne.emit("init",wn)},0);var po=/\{\{((?:.|\r?\n)+?)\}\}/g,vo=/[-.*+?^${}()|[\]\/\\]/g,ho=g(function(e){var t=e[0].replace(vo,"\\$&"),n=e[1].replace(vo,"\\$&");return new RegExp(t+"((?:.|\\n)+?)"+n,"g")});var mo={staticKeys:["staticClass"],transformNode:function(e,t){t.warn;var n=Fr(e,"class");n&&(e.staticClass=JSON.stringify(n));var r=Ir(e,"class",!1);r&&(e.classBinding=r)},genData:function(e){var t="";return e.staticClass&&(t+="staticClass:"+e.staticClass+","),e.classBinding&&(t+="class:"+e.classBinding+","),t}};var yo,go={staticKeys:["staticStyle"],transformNode:function(e,t){t.warn;var n=Fr(e,"style");n&&(e.staticStyle=JSON.stringify(ai(n)));var r=Ir(e,"style",!1);r&&(e.styleBinding=r)},genData:function(e){var t="";return e.staticStyle&&(t+="staticStyle:"+e.staticStyle+","),e.styleBinding&&(t+="style:("+e.styleBinding+"),"),t}},_o=function(e){return(yo=yo||document.createElement("div")).innerHTML=e,yo.textContent},bo=p("area,base,br,col,embed,frame,hr,img,input,isindex,keygen,link,meta,param,source,track,wbr"),$o=p("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr,source"),wo=p("address,article,aside,base,blockquote,body,caption,col,colgroup,dd,details,dialog,div,dl,dt,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,legend,li,menuitem,meta,optgroup,option,param,rp,rt,source,style,summary,tbody,td,tfoot,th,thead,title,tr,track"),Co=/^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,xo=/^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/,ko="[a-zA-Z_][\\-\\.0-9_a-zA-Z"+P.source+"]*",Ao="((?:"+ko+"\\:)?"+ko+")",Oo=new RegExp("^<"+Ao),So=/^\s*(\/?)>/,To=new RegExp("^<\\/"+Ao+"[^>]*>"),Eo=/^<!DOCTYPE [^>]+>/i,No=/^<!\--/,jo=/^<!\[/,Do=p("script,style,textarea",!0),Lo={},Mo={"&lt;":"<","&gt;":">","&quot;":'"',"&amp;":"&","&#10;":"\n","&#9;":"\t","&#39;":"'"},Io=/&(?:lt|gt|quot|amp|#39);/g,Fo=/&(?:lt|gt|quot|amp|#39|#10|#9);/g,Po=p("pre,textarea",!0),Ro=function(e,t){return e&&Po(e)&&"\n"===t[0]};function Ho(e,t){var n=t?Fo:Io;return e.replace(n,function(e){return Mo[e]})}var Bo,Uo,zo,Vo,Ko,Jo,qo,Wo,Zo=/^@|^v-on:/,Go=/^v-|^@|^:|^#/,Xo=/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/,Yo=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,Qo=/^\(|\)$/g,ea=/^\[.*\]$/,ta=/:(.*)$/,na=/^:|^\.|^v-bind:/,ra=/\.[^.\]]+(?=[^\]]*$)/g,ia=/^v-slot(:|$)|^#/,oa=/[\r\n]/,aa=/\s+/g,sa=g(_o),ca="_empty_";function ua(e,t,n){return{type:1,tag:e,attrsList:t,attrsMap:ma(t),rawAttrsMap:{},parent:n,children:[]}}function la(e,t){Bo=t.warn||Sr,Jo=t.isPreTag||T,qo=t.mustUseProp||T,Wo=t.getTagNamespace||T;t.isReservedTag;zo=Tr(t.modules,"transformNode"),Vo=Tr(t.modules,"preTransformNode"),Ko=Tr(t.modules,"postTransformNode"),Uo=t.delimiters;var n,r,i=[],o=!1!==t.preserveWhitespace,a=t.whitespace,s=!1,c=!1;function u(e){if(l(e),s||e.processed||(e=fa(e,t)),i.length||e===n||n.if&&(e.elseif||e.else)&&da(n,{exp:e.elseif,block:e}),r&&!e.forbidden)if(e.elseif||e.else)a=e,(u=function(e){var t=e.length;for(;t--;){if(1===e[t].type)return e[t];e.pop()}}(r.children))&&u.if&&da(u,{exp:a.elseif,block:a});else{if(e.slotScope){var o=e.slotTarget||'"default"';(r.scopedSlots||(r.scopedSlots={}))[o]=e}r.children.push(e),e.parent=r}var a,u;e.children=e.children.filter(function(e){return!e.slotScope}),l(e),e.pre&&(s=!1),Jo(e.tag)&&(c=!1);for(var f=0;f<Ko.length;f++)Ko[f](e,t)}function l(e){if(!c)for(var t;(t=e.children[e.children.length-1])&&3===t.type&&" "===t.text;)e.children.pop()}return function(e,t){for(var n,r,i=[],o=t.expectHTML,a=t.isUnaryTag||T,s=t.canBeLeftOpenTag||T,c=0;e;){if(n=e,r&&Do(r)){var u=0,l=r.toLowerCase(),f=Lo[l]||(Lo[l]=new RegExp("([\\s\\S]*?)(</"+l+"[^>]*>)","i")),p=e.replace(f,function(e,n,r){return u=r.length,Do(l)||"noscript"===l||(n=n.replace(/<!\--([\s\S]*?)-->/g,"$1").replace(/<!\[CDATA\[([\s\S]*?)]]>/g,"$1")),Ro(l,n)&&(n=n.slice(1)),t.chars&&t.chars(n),""});c+=e.length-p.length,e=p,A(l,c-u,c)}else{var d=e.indexOf("<");if(0===d){if(No.test(e)){var v=e.indexOf("--\x3e");if(v>=0){t.shouldKeepComment&&t.comment(e.substring(4,v),c,c+v+3),C(v+3);continue}}if(jo.test(e)){var h=e.indexOf("]>");if(h>=0){C(h+2);continue}}var m=e.match(Eo);if(m){C(m[0].length);continue}var y=e.match(To);if(y){var g=c;C(y[0].length),A(y[1],g,c);continue}var _=x();if(_){k(_),Ro(_.tagName,e)&&C(1);continue}}var b=void 0,$=void 0,w=void 0;if(d>=0){for($=e.slice(d);!(To.test($)||Oo.test($)||No.test($)||jo.test($)||(w=$.indexOf("<",1))<0);)d+=w,$=e.slice(d);b=e.substring(0,d)}d<0&&(b=e),b&&C(b.length),t.chars&&b&&t.chars(b,c-b.length,c)}if(e===n){t.chars&&t.chars(e);break}}function C(t){c+=t,e=e.substring(t)}function x(){var t=e.match(Oo);if(t){var n,r,i={tagName:t[1],attrs:[],start:c};for(C(t[0].length);!(n=e.match(So))&&(r=e.match(xo)||e.match(Co));)r.start=c,C(r[0].length),r.end=c,i.attrs.push(r);if(n)return i.unarySlash=n[1],C(n[0].length),i.end=c,i}}function k(e){var n=e.tagName,c=e.unarySlash;o&&("p"===r&&wo(n)&&A(r),s(n)&&r===n&&A(n));for(var u=a(n)||!!c,l=e.attrs.length,f=new Array(l),p=0;p<l;p++){var d=e.attrs[p],v=d[3]||d[4]||d[5]||"",h="a"===n&&"href"===d[1]?t.shouldDecodeNewlinesForHref:t.shouldDecodeNewlines;f[p]={name:d[1],value:Ho(v,h)}}u||(i.push({tag:n,lowerCasedTag:n.toLowerCase(),attrs:f,start:e.start,end:e.end}),r=n),t.start&&t.start(n,f,u,e.start,e.end)}function A(e,n,o){var a,s;if(null==n&&(n=c),null==o&&(o=c),e)for(s=e.toLowerCase(),a=i.length-1;a>=0&&i[a].lowerCasedTag!==s;a--);else a=0;if(a>=0){for(var u=i.length-1;u>=a;u--)t.end&&t.end(i[u].tag,n,o);i.length=a,r=a&&i[a-1].tag}else"br"===s?t.start&&t.start(e,[],!0,n,o):"p"===s&&(t.start&&t.start(e,[],!1,n,o),t.end&&t.end(e,n,o))}A()}(e,{warn:Bo,expectHTML:t.expectHTML,isUnaryTag:t.isUnaryTag,canBeLeftOpenTag:t.canBeLeftOpenTag,shouldDecodeNewlines:t.shouldDecodeNewlines,shouldDecodeNewlinesForHref:t.shouldDecodeNewlinesForHref,shouldKeepComment:t.comments,outputSourceRange:t.outputSourceRange,start:function(e,o,a,l,f){var p=r&&r.ns||Wo(e);q&&"svg"===p&&(o=function(e){for(var t=[],n=0;n<e.length;n++){var r=e[n];ya.test(r.name)||(r.name=r.name.replace(ga,""),t.push(r))}return t}(o));var d,v=ua(e,o,r);p&&(v.ns=p),"style"!==(d=v).tag&&("script"!==d.tag||d.attrsMap.type&&"text/javascript"!==d.attrsMap.type)||te()||(v.forbidden=!0);for(var h=0;h<Vo.length;h++)v=Vo[h](v,t)||v;s||(!function(e){null!=Fr(e,"v-pre")&&(e.pre=!0)}(v),v.pre&&(s=!0)),Jo(v.tag)&&(c=!0),s?function(e){var t=e.attrsList,n=t.length;if(n)for(var r=e.attrs=new Array(n),i=0;i<n;i++)r[i]={name:t[i].name,value:JSON.stringify(t[i].value)},null!=t[i].start&&(r[i].start=t[i].start,r[i].end=t[i].end);else e.pre||(e.plain=!0)}(v):v.processed||(pa(v),function(e){var t=Fr(e,"v-if");if(t)e.if=t,da(e,{exp:t,block:e});else{null!=Fr(e,"v-else")&&(e.else=!0);var n=Fr(e,"v-else-if");n&&(e.elseif=n)}}(v),function(e){null!=Fr(e,"v-once")&&(e.once=!0)}(v)),n||(n=v),a?u(v):(r=v,i.push(v))},end:function(e,t,n){var o=i[i.length-1];i.length-=1,r=i[i.length-1],u(o)},chars:function(e,t,n){if(r&&(!q||"textarea"!==r.tag||r.attrsMap.placeholder!==e)){var i,u,l,f=r.children;if(e=c||e.trim()?"script"===(i=r).tag||"style"===i.tag?e:sa(e):f.length?a?"condense"===a&&oa.test(e)?"":" ":o?" ":"":"")c||"condense"!==a||(e=e.replace(aa," ")),!s&&" "!==e&&(u=function(e,t){var n=t?ho(t):po;if(n.test(e)){for(var r,i,o,a=[],s=[],c=n.lastIndex=0;r=n.exec(e);){(i=r.index)>c&&(s.push(o=e.slice(c,i)),a.push(JSON.stringify(o)));var u=Ar(r[1].trim());a.push("_s("+u+")"),s.push({"@binding":u}),c=i+r[0].length}return c<e.length&&(s.push(o=e.slice(c)),a.push(JSON.stringify(o))),{expression:a.join("+"),tokens:s}}}(e,Uo))?l={type:2,expression:u.expression,tokens:u.tokens,text:e}:" "===e&&f.length&&" "===f[f.length-1].text||(l={type:3,text:e}),l&&f.push(l)}},comment:function(e,t,n){if(r){var i={type:3,text:e,isComment:!0};r.children.push(i)}}}),n}function fa(e,t){var n,r;(r=Ir(n=e,"key"))&&(n.key=r),e.plain=!e.key&&!e.scopedSlots&&!e.attrsList.length,function(e){var t=Ir(e,"ref");t&&(e.ref=t,e.refInFor=function(e){var t=e;for(;t;){if(void 0!==t.for)return!0;t=t.parent}return!1}(e))}(e),function(e){var t;"template"===e.tag?(t=Fr(e,"scope"),e.slotScope=t||Fr(e,"slot-scope")):(t=Fr(e,"slot-scope"))&&(e.slotScope=t);var n=Ir(e,"slot");n&&(e.slotTarget='""'===n?'"default"':n,e.slotTargetDynamic=!(!e.attrsMap[":slot"]&&!e.attrsMap["v-bind:slot"]),"template"===e.tag||e.slotScope||Nr(e,"slot",n,function(e,t){return e.rawAttrsMap[":"+t]||e.rawAttrsMap["v-bind:"+t]||e.rawAttrsMap[t]}(e,"slot")));if("template"===e.tag){var r=Pr(e,ia);if(r){var i=va(r),o=i.name,a=i.dynamic;e.slotTarget=o,e.slotTargetDynamic=a,e.slotScope=r.value||ca}}else{var s=Pr(e,ia);if(s){var c=e.scopedSlots||(e.scopedSlots={}),u=va(s),l=u.name,f=u.dynamic,p=c[l]=ua("template",[],e);p.slotTarget=l,p.slotTargetDynamic=f,p.children=e.children.filter(function(e){if(!e.slotScope)return e.parent=p,!0}),p.slotScope=s.value||ca,e.children=[],e.plain=!1}}}(e),function(e){"slot"===e.tag&&(e.slotName=Ir(e,"name"))}(e),function(e){var t;(t=Ir(e,"is"))&&(e.component=t);null!=Fr(e,"inline-template")&&(e.inlineTemplate=!0)}(e);for(var i=0;i<zo.length;i++)e=zo[i](e,t)||e;return function(e){var t,n,r,i,o,a,s,c,u=e.attrsList;for(t=0,n=u.length;t<n;t++)if(r=i=u[t].name,o=u[t].value,Go.test(r))if(e.hasBindings=!0,(a=ha(r.replace(Go,"")))&&(r=r.replace(ra,"")),na.test(r))r=r.replace(na,""),o=Ar(o),(c=ea.test(r))&&(r=r.slice(1,-1)),a&&(a.prop&&!c&&"innerHtml"===(r=b(r))&&(r="innerHTML"),a.camel&&!c&&(r=b(r)),a.sync&&(s=Br(o,"$event"),c?Mr(e,'"update:"+('+r+")",s,null,!1,0,u[t],!0):(Mr(e,"update:"+b(r),s,null,!1,0,u[t]),C(r)!==b(r)&&Mr(e,"update:"+C(r),s,null,!1,0,u[t])))),a&&a.prop||!e.component&&qo(e.tag,e.attrsMap.type,r)?Er(e,r,o,u[t],c):Nr(e,r,o,u[t],c);else if(Zo.test(r))r=r.replace(Zo,""),(c=ea.test(r))&&(r=r.slice(1,-1)),Mr(e,r,o,a,!1,0,u[t],c);else{var l=(r=r.replace(Go,"")).match(ta),f=l&&l[1];c=!1,f&&(r=r.slice(0,-(f.length+1)),ea.test(f)&&(f=f.slice(1,-1),c=!0)),Dr(e,r,i,o,f,c,a,u[t])}else Nr(e,r,JSON.stringify(o),u[t]),!e.component&&"muted"===r&&qo(e.tag,e.attrsMap.type,r)&&Er(e,r,"true",u[t])}(e),e}function pa(e){var t;if(t=Fr(e,"v-for")){var n=function(e){var t=e.match(Xo);if(!t)return;var n={};n.for=t[2].trim();var r=t[1].trim().replace(Qo,""),i=r.match(Yo);i?(n.alias=r.replace(Yo,"").trim(),n.iterator1=i[1].trim(),i[2]&&(n.iterator2=i[2].trim())):n.alias=r;return n}(t);n&&A(e,n)}}function da(e,t){e.ifConditions||(e.ifConditions=[]),e.ifConditions.push(t)}function va(e){var t=e.name.replace(ia,"");return t||"#"!==e.name[0]&&(t="default"),ea.test(t)?{name:t.slice(1,-1),dynamic:!0}:{name:'"'+t+'"',dynamic:!1}}function ha(e){var t=e.match(ra);if(t){var n={};return t.forEach(function(e){n[e.slice(1)]=!0}),n}}function ma(e){for(var t={},n=0,r=e.length;n<r;n++)t[e[n].name]=e[n].value;return t}var ya=/^xmlns:NS\d+/,ga=/^NS\d+:/;function _a(e){return ua(e.tag,e.attrsList.slice(),e.parent)}var ba=[mo,go,{preTransformNode:function(e,t){if("input"===e.tag){var n,r=e.attrsMap;if(!r["v-model"])return;if((r[":type"]||r["v-bind:type"])&&(n=Ir(e,"type")),r.type||n||!r["v-bind"]||(n="("+r["v-bind"]+").type"),n){var i=Fr(e,"v-if",!0),o=i?"&&("+i+")":"",a=null!=Fr(e,"v-else",!0),s=Fr(e,"v-else-if",!0),c=_a(e);pa(c),jr(c,"type","checkbox"),fa(c,t),c.processed=!0,c.if="("+n+")==='checkbox'"+o,da(c,{exp:c.if,block:c});var u=_a(e);Fr(u,"v-for",!0),jr(u,"type","radio"),fa(u,t),da(c,{exp:"("+n+")==='radio'"+o,block:u});var l=_a(e);return Fr(l,"v-for",!0),jr(l,":type",n),fa(l,t),da(c,{exp:i,block:l}),a?c.else=!0:s&&(c.elseif=s),c}}}}];var $a,wa,Ca={expectHTML:!0,modules:ba,directives:{model:function(e,t,n){var r=t.value,i=t.modifiers,o=e.tag,a=e.attrsMap.type;if(e.component)return Hr(e,r,i),!1;if("select"===o)!function(e,t,n){var r='var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = "_value" in o ? o._value : o.value;return '+(n&&n.number?"_n(val)":"val")+"});";r=r+" "+Br(t,"$event.target.multiple ? $$selectedVal : $$selectedVal[0]"),Mr(e,"change",r,null,!0)}(e,r,i);else if("input"===o&&"checkbox"===a)!function(e,t,n){var r=n&&n.number,i=Ir(e,"value")||"null",o=Ir(e,"true-value")||"true",a=Ir(e,"false-value")||"false";Er(e,"checked","Array.isArray("+t+")?_i("+t+","+i+")>-1"+("true"===o?":("+t+")":":_q("+t+","+o+")")),Mr(e,"change","var $$a="+t+",$$el=$event.target,$$c=$$el.checked?("+o+"):("+a+");if(Array.isArray($$a)){var $$v="+(r?"_n("+i+")":i)+",$$i=_i($$a,$$v);if($$el.checked){$$i<0&&("+Br(t,"$$a.concat([$$v])")+")}else{$$i>-1&&("+Br(t,"$$a.slice(0,$$i).concat($$a.slice($$i+1))")+")}}else{"+Br(t,"$$c")+"}",null,!0)}(e,r,i);else if("input"===o&&"radio"===a)!function(e,t,n){var r=n&&n.number,i=Ir(e,"value")||"null";Er(e,"checked","_q("+t+","+(i=r?"_n("+i+")":i)+")"),Mr(e,"change",Br(t,i),null,!0)}(e,r,i);else if("input"===o||"textarea"===o)!function(e,t,n){var r=e.attrsMap.type,i=n||{},o=i.lazy,a=i.number,s=i.trim,c=!o&&"range"!==r,u=o?"change":"range"===r?Wr:"input",l="$event.target.value";s&&(l="$event.target.value.trim()"),a&&(l="_n("+l+")");var f=Br(t,l);c&&(f="if($event.target.composing)return;"+f),Er(e,"value","("+t+")"),Mr(e,u,f,null,!0),(s||a)&&Mr(e,"blur","$forceUpdate()")}(e,r,i);else if(!F.isReservedTag(o))return Hr(e,r,i),!1;return!0},text:function(e,t){t.value&&Er(e,"textContent","_s("+t.value+")",t)},html:function(e,t){t.value&&Er(e,"innerHTML","_s("+t.value+")",t)}},isPreTag:function(e){return"pre"===e},isUnaryTag:bo,mustUseProp:jn,canBeLeftOpenTag:$o,isReservedTag:Wn,getTagNamespace:Zn,staticKeys:function(e){return e.reduce(function(e,t){return e.concat(t.staticKeys||[])},[]).join(",")}(ba)},xa=g(function(e){return p("type,tag,attrsList,attrsMap,plain,parent,children,attrs,start,end,rawAttrsMap"+(e?","+e:""))});function ka(e,t){e&&($a=xa(t.staticKeys||""),wa=t.isReservedTag||T,function e(t){t.static=function(e){if(2===e.type)return!1;if(3===e.type)return!0;return!(!e.pre&&(e.hasBindings||e.if||e.for||d(e.tag)||!wa(e.tag)||function(e){for(;e.parent;){if("template"!==(e=e.parent).tag)return!1;if(e.for)return!0}return!1}(e)||!Object.keys(e).every($a)))}(t);if(1===t.type){if(!wa(t.tag)&&"slot"!==t.tag&&null==t.attrsMap["inline-template"])return;for(var n=0,r=t.children.length;n<r;n++){var i=t.children[n];e(i),i.static||(t.static=!1)}if(t.ifConditions)for(var o=1,a=t.ifConditions.length;o<a;o++){var s=t.ifConditions[o].block;e(s),s.static||(t.static=!1)}}}(e),function e(t,n){if(1===t.type){if((t.static||t.once)&&(t.staticInFor=n),t.static&&t.children.length&&(1!==t.children.length||3!==t.children[0].type))return void(t.staticRoot=!0);if(t.staticRoot=!1,t.children)for(var r=0,i=t.children.length;r<i;r++)e(t.children[r],n||!!t.for);if(t.ifConditions)for(var o=1,a=t.ifConditions.length;o<a;o++)e(t.ifConditions[o].block,n)}}(e,!1))}var Aa=/^([\w$_]+|\([^)]*?\))\s*=>|^function(?:\s+[\w$]+)?\s*\(/,Oa=/\([^)]*?\);*$/,Sa=/^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/,Ta={esc:27,tab:9,enter:13,space:32,up:38,left:37,right:39,down:40,delete:[8,46]},Ea={esc:["Esc","Escape"],tab:"Tab",enter:"Enter",space:[" ","Spacebar"],up:["Up","ArrowUp"],left:["Left","ArrowLeft"],right:["Right","ArrowRight"],down:["Down","ArrowDown"],delete:["Backspace","Delete","Del"]},Na=function(e){return"if("+e+")return null;"},ja={stop:"$event.stopPropagation();",prevent:"$event.preventDefault();",self:Na("$event.target !== $event.currentTarget"),ctrl:Na("!$event.ctrlKey"),shift:Na("!$event.shiftKey"),alt:Na("!$event.altKey"),meta:Na("!$event.metaKey"),left:Na("'button' in $event && $event.button !== 0"),middle:Na("'button' in $event && $event.button !== 1"),right:Na("'button' in $event && $event.button !== 2")};function Da(e,t){var n=t?"nativeOn:":"on:",r="",i="";for(var o in e){var a=La(e[o]);e[o]&&e[o].dynamic?i+=o+","+a+",":r+='"'+o+'":'+a+","}return r="{"+r.slice(0,-1)+"}",i?n+"_d("+r+",["+i.slice(0,-1)+"])":n+r}function La(e){if(!e)return"function(){}";if(Array.isArray(e))return"["+e.map(function(e){return La(e)}).join(",")+"]";var t=Sa.test(e.value),n=Aa.test(e.value),r=Sa.test(e.value.replace(Oa,""));if(e.modifiers){var i="",o="",a=[];for(var s in e.modifiers)if(ja[s])o+=ja[s],Ta[s]&&a.push(s);else if("exact"===s){var c=e.modifiers;o+=Na(["ctrl","shift","alt","meta"].filter(function(e){return!c[e]}).map(function(e){return"$event."+e+"Key"}).join("||"))}else a.push(s);return a.length&&(i+=function(e){return"if(!$event.type.indexOf('key')&&"+e.map(Ma).join("&&")+")return null;"}(a)),o&&(i+=o),"function($event){"+i+(t?"return "+e.value+"($event)":n?"return ("+e.value+")($event)":r?"return "+e.value:e.value)+"}"}return t||n?e.value:"function($event){"+(r?"return "+e.value:e.value)+"}"}function Ma(e){var t=parseInt(e,10);if(t)return"$event.keyCode!=="+t;var n=Ta[e],r=Ea[e];return"_k($event.keyCode,"+JSON.stringify(e)+","+JSON.stringify(n)+",$event.key,"+JSON.stringify(r)+")"}var Ia={on:function(e,t){e.wrapListeners=function(e){return"_g("+e+","+t.value+")"}},bind:function(e,t){e.wrapData=function(n){return"_b("+n+",'"+e.tag+"',"+t.value+","+(t.modifiers&&t.modifiers.prop?"true":"false")+(t.modifiers&&t.modifiers.sync?",true":"")+")"}},cloak:S},Fa=function(e){this.options=e,this.warn=e.warn||Sr,this.transforms=Tr(e.modules,"transformCode"),this.dataGenFns=Tr(e.modules,"genData"),this.directives=A(A({},Ia),e.directives);var t=e.isReservedTag||T;this.maybeComponent=function(e){return!!e.component||!t(e.tag)},this.onceId=0,this.staticRenderFns=[],this.pre=!1};function Pa(e,t){var n=new Fa(t);return{render:"with(this){return "+(e?Ra(e,n):'_c("div")')+"}",staticRenderFns:n.staticRenderFns}}function Ra(e,t){if(e.parent&&(e.pre=e.pre||e.parent.pre),e.staticRoot&&!e.staticProcessed)return Ha(e,t);if(e.once&&!e.onceProcessed)return Ba(e,t);if(e.for&&!e.forProcessed)return za(e,t);if(e.if&&!e.ifProcessed)return Ua(e,t);if("template"!==e.tag||e.slotTarget||t.pre){if("slot"===e.tag)return function(e,t){var n=e.slotName||'"default"',r=qa(e,t),i="_t("+n+(r?","+r:""),o=e.attrs||e.dynamicAttrs?Ga((e.attrs||[]).concat(e.dynamicAttrs||[]).map(function(e){return{name:b(e.name),value:e.value,dynamic:e.dynamic}})):null,a=e.attrsMap["v-bind"];!o&&!a||r||(i+=",null");o&&(i+=","+o);a&&(i+=(o?"":",null")+","+a);return i+")"}(e,t);var n;if(e.component)n=function(e,t,n){var r=t.inlineTemplate?null:qa(t,n,!0);return"_c("+e+","+Va(t,n)+(r?","+r:"")+")"}(e.component,e,t);else{var r;(!e.plain||e.pre&&t.maybeComponent(e))&&(r=Va(e,t));var i=e.inlineTemplate?null:qa(e,t,!0);n="_c('"+e.tag+"'"+(r?","+r:"")+(i?","+i:"")+")"}for(var o=0;o<t.transforms.length;o++)n=t.transforms[o](e,n);return n}return qa(e,t)||"void 0"}function Ha(e,t){e.staticProcessed=!0;var n=t.pre;return e.pre&&(t.pre=e.pre),t.staticRenderFns.push("with(this){return "+Ra(e,t)+"}"),t.pre=n,"_m("+(t.staticRenderFns.length-1)+(e.staticInFor?",true":"")+")"}function Ba(e,t){if(e.onceProcessed=!0,e.if&&!e.ifProcessed)return Ua(e,t);if(e.staticInFor){for(var n="",r=e.parent;r;){if(r.for){n=r.key;break}r=r.parent}return n?"_o("+Ra(e,t)+","+t.onceId+++","+n+")":Ra(e,t)}return Ha(e,t)}function Ua(e,t,n,r){return e.ifProcessed=!0,function e(t,n,r,i){if(!t.length)return i||"_e()";var o=t.shift();return o.exp?"("+o.exp+")?"+a(o.block)+":"+e(t,n,r,i):""+a(o.block);function a(e){return r?r(e,n):e.once?Ba(e,n):Ra(e,n)}}(e.ifConditions.slice(),t,n,r)}function za(e,t,n,r){var i=e.for,o=e.alias,a=e.iterator1?","+e.iterator1:"",s=e.iterator2?","+e.iterator2:"";return e.forProcessed=!0,(r||"_l")+"(("+i+"),function("+o+a+s+"){return "+(n||Ra)(e,t)+"})"}function Va(e,t){var n="{",r=function(e,t){var n=e.directives;if(!n)return;var r,i,o,a,s="directives:[",c=!1;for(r=0,i=n.length;r<i;r++){o=n[r],a=!0;var u=t.directives[o.name];u&&(a=!!u(e,o,t.warn)),a&&(c=!0,s+='{name:"'+o.name+'",rawName:"'+o.rawName+'"'+(o.value?",value:("+o.value+"),expression:"+JSON.stringify(o.value):"")+(o.arg?",arg:"+(o.isDynamicArg?o.arg:'"'+o.arg+'"'):"")+(o.modifiers?",modifiers:"+JSON.stringify(o.modifiers):"")+"},")}if(c)return s.slice(0,-1)+"]"}(e,t);r&&(n+=r+","),e.key&&(n+="key:"+e.key+","),e.ref&&(n+="ref:"+e.ref+","),e.refInFor&&(n+="refInFor:true,"),e.pre&&(n+="pre:true,"),e.component&&(n+='tag:"'+e.tag+'",');for(var i=0;i<t.dataGenFns.length;i++)n+=t.dataGenFns[i](e);if(e.attrs&&(n+="attrs:"+Ga(e.attrs)+","),e.props&&(n+="domProps:"+Ga(e.props)+","),e.events&&(n+=Da(e.events,!1)+","),e.nativeEvents&&(n+=Da(e.nativeEvents,!0)+","),e.slotTarget&&!e.slotScope&&(n+="slot:"+e.slotTarget+","),e.scopedSlots&&(n+=function(e,t,n){var r=e.for||Object.keys(t).some(function(e){var n=t[e];return n.slotTargetDynamic||n.if||n.for||Ka(n)}),i=!!e.if;if(!r)for(var o=e.parent;o;){if(o.slotScope&&o.slotScope!==ca||o.for){r=!0;break}o.if&&(i=!0),o=o.parent}var a=Object.keys(t).map(function(e){return Ja(t[e],n)}).join(",");return"scopedSlots:_u(["+a+"]"+(r?",null,true":"")+(!r&&i?",null,false,"+function(e){var t=5381,n=e.length;for(;n;)t=33*t^e.charCodeAt(--n);return t>>>0}(a):"")+")"}(e,e.scopedSlots,t)+","),e.model&&(n+="model:{value:"+e.model.value+",callback:"+e.model.callback+",expression:"+e.model.expression+"},"),e.inlineTemplate){var o=function(e,t){var n=e.children[0];if(n&&1===n.type){var r=Pa(n,t.options);return"inlineTemplate:{render:function(){"+r.render+"},staticRenderFns:["+r.staticRenderFns.map(function(e){return"function(){"+e+"}"}).join(",")+"]}"}}(e,t);o&&(n+=o+",")}return n=n.replace(/,$/,"")+"}",e.dynamicAttrs&&(n="_b("+n+',"'+e.tag+'",'+Ga(e.dynamicAttrs)+")"),e.wrapData&&(n=e.wrapData(n)),e.wrapListeners&&(n=e.wrapListeners(n)),n}function Ka(e){return 1===e.type&&("slot"===e.tag||e.children.some(Ka))}function Ja(e,t){var n=e.attrsMap["slot-scope"];if(e.if&&!e.ifProcessed&&!n)return Ua(e,t,Ja,"null");if(e.for&&!e.forProcessed)return za(e,t,Ja);var r=e.slotScope===ca?"":String(e.slotScope),i="function("+r+"){return "+("template"===e.tag?e.if&&n?"("+e.if+")?"+(qa(e,t)||"undefined")+":undefined":qa(e,t)||"undefined":Ra(e,t))+"}",o=r?"":",proxy:true";return"{key:"+(e.slotTarget||'"default"')+",fn:"+i+o+"}"}function qa(e,t,n,r,i){var o=e.children;if(o.length){var a=o[0];if(1===o.length&&a.for&&"template"!==a.tag&&"slot"!==a.tag){var s=n?t.maybeComponent(a)?",1":",0":"";return""+(r||Ra)(a,t)+s}var c=n?function(e,t){for(var n=0,r=0;r<e.length;r++){var i=e[r];if(1===i.type){if(Wa(i)||i.ifConditions&&i.ifConditions.some(function(e){return Wa(e.block)})){n=2;break}(t(i)||i.ifConditions&&i.ifConditions.some(function(e){return t(e.block)}))&&(n=1)}}return n}(o,t.maybeComponent):0,u=i||Za;return"["+o.map(function(e){return u(e,t)}).join(",")+"]"+(c?","+c:"")}}function Wa(e){return void 0!==e.for||"template"===e.tag||"slot"===e.tag}function Za(e,t){return 1===e.type?Ra(e,t):3===e.type&&e.isComment?(r=e,"_e("+JSON.stringify(r.text)+")"):"_v("+(2===(n=e).type?n.expression:Xa(JSON.stringify(n.text)))+")";var n,r}function Ga(e){for(var t="",n="",r=0;r<e.length;r++){var i=e[r],o=Xa(i.value);i.dynamic?n+=i.name+","+o+",":t+='"'+i.name+'":'+o+","}return t="{"+t.slice(0,-1)+"}",n?"_d("+t+",["+n.slice(0,-1)+"])":t}function Xa(e){return e.replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}new RegExp("\\b"+"do,if,for,let,new,try,var,case,else,with,await,break,catch,class,const,super,throw,while,yield,delete,export,import,return,switch,default,extends,finally,continue,debugger,function,arguments".split(",").join("\\b|\\b")+"\\b");function Ya(e,t){try{return new Function(e)}catch(n){return t.push({err:n,code:e}),S}}function Qa(e){var t=Object.create(null);return function(n,r,i){(r=A({},r)).warn;delete r.warn;var o=r.delimiters?String(r.delimiters)+n:n;if(t[o])return t[o];var a=e(n,r),s={},c=[];return s.render=Ya(a.render,c),s.staticRenderFns=a.staticRenderFns.map(function(e){return Ya(e,c)}),t[o]=s}}var es,ts,ns=(es=function(e,t){var n=la(e.trim(),t);!1!==t.optimize&&ka(n,t);var r=Pa(n,t);return{ast:n,render:r.render,staticRenderFns:r.staticRenderFns}},function(e){function t(t,n){var r=Object.create(e),i=[],o=[];if(n)for(var a in n.modules&&(r.modules=(e.modules||[]).concat(n.modules)),n.directives&&(r.directives=A(Object.create(e.directives||null),n.directives)),n)"modules"!==a&&"directives"!==a&&(r[a]=n[a]);r.warn=function(e,t,n){(n?o:i).push(e)};var s=es(t.trim(),r);return s.errors=i,s.tips=o,s}return{compile:t,compileToFunctions:Qa(t)}})(Ca),rs=(ns.compile,ns.compileToFunctions);function is(e){return(ts=ts||document.createElement("div")).innerHTML=e?'<a href="\n"/>':'<div a="\n"/>',ts.innerHTML.indexOf("&#10;")>0}var os=!!z&&is(!1),as=!!z&&is(!0),ss=g(function(e){var t=Yn(e);return t&&t.innerHTML}),cs=wn.prototype.$mount;return wn.prototype.$mount=function(e,t){if((e=e&&Yn(e))===document.body||e===document.documentElement)return this;var n=this.$options;if(!n.render){var r=n.template;if(r)if("string"==typeof r)"#"===r.charAt(0)&&(r=ss(r));else{if(!r.nodeType)return this;r=r.innerHTML}else e&&(r=function(e){if(e.outerHTML)return e.outerHTML;var t=document.createElement("div");return t.appendChild(e.cloneNode(!0)),t.innerHTML}(e));if(r){var i=rs(r,{outputSourceRange:!1,shouldDecodeNewlines:os,shouldDecodeNewlinesForHref:as,delimiters:n.delimiters,comments:n.comments},this),o=i.render,a=i.staticRenderFns;n.render=o,n.staticRenderFns=a}}return cs.call(this,e,t)},wn.compile=rs,wn});
\ No newline at end of file
<?php
/**
* Copyright © Customily. All rights reserved.
*/
use Magento\Catalog\Model\Product\Option;
/**
* @var \Customily\Categories\Block\Product\View\Options\Type\Select\Checkable $block
*/
$option = $block->getOption();
if ($option) : ?>
<?php
$configValue = $block->getPreconfiguredValue($option);
$optionType = $option->getType();
$arraySign = $optionType === Option::OPTION_TYPE_CHECKBOX ? '[]' : '';
$count = 1;
?>
<div class="options-list nested" id="options-<?= $block->escapeHtmlAttr($option->getId()) ?>-list">
<?php if ($optionType === Option::OPTION_TYPE_RADIO && !$option->getIsRequire()) :?>
<div class="field choice admin__field admin__field-option">
<input type="radio"
id="options_<?= $block->escapeHtmlAttr($option->getId()) ?>"
class="radio admin__control-radio product-custom-option"
name="options[<?= $block->escapeHtmlAttr($option->getId()) ?>]"
data-selector="options[<?= $block->escapeHtmlAttr($option->getId()) ?>]"
onclick="<?= $block->getSkipJsReloadPrice() ? '' : 'opConfig.reloadPrice()' ?>"
value=""
checked="checked"
/>
<label class="label admin__field-label" for="options_<?= $block->escapeHtmlAttr($option->getId()) ?>">
<span><?= $block->escapeHtml(__('None')) ?></span>
</label>
</div>
<?php endif; ?>
<?php foreach ($option->getValues() as $value) : ?>
<?php
$checked = '';
$count++;
if ($arraySign) {
$checked = is_array($configValue) && in_array($value->getOptionTypeId(), $configValue) ? 'checked' : '';
} else {
$checked = $configValue == $value->getOptionTypeId() ? 'checked' : '';
}
if (!$configValue && $value->getData('customily_is_default')) {
$checked = 'checked';
}
$dataSelector = 'options[' . $option->getId() . ']';
if ($arraySign) {
$dataSelector .= '[' . $value->getOptionTypeId() . ']';
}
?>
<div class="field choice admin__field admin__field-option <?= /* @noEscape */ $option->getIsRequire() ? 'required': '' ?>">
<input type="<?= $block->escapeHtmlAttr($optionType) ?>"
class="<?= /* @noEscape */ $optionType === Option::OPTION_TYPE_RADIO
? 'radio admin__control-radio'
: 'checkbox admin__control-checkbox' ?> <?= $option->getIsRequire()
? 'required': '' ?>
product-custom-option
<?= $block->getSkipJsReloadPrice() ? '' : 'opConfig.reloadPrice()' ?>"
name="options[<?= $block->escapeHtmlAttr($option->getId()) ?>]<?= /* @noEscape */ $arraySign ?>"
id="options_<?= $block->escapeHtmlAttr($option->getId() . '_' . $count) ?>"
value="<?= $block->escapeHtmlAttr($value->getOptionTypeId()) ?>"
<?= $block->escapeHtml($checked) ?>
data-selector="<?= $block->escapeHtmlAttr($dataSelector) ?>"
price="<?= $block->escapeHtmlAttr($block->getCurrencyByStore($value)) ?>"
/>
<label class="label admin__field-label"
for="options_<?= $block->escapeHtmlAttr($option->getId() . '_' . $count) ?>">
<span>
<?= $block->escapeHtml($value->getTitle()) ?>
</span>
<?= /* @noEscape */ $block->formatPrice($value) ?>
</label>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
\ No newline at end of file
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.options">
<action method="setTemplate">
<argument name="template" xsi:type="string">Customily_Categories::product/view/options.phtml</argument>
</action>
</referenceBlock>
<referenceBlock name="product.info.options.file">
<action method="setTemplate">
<argument name="template" xsi:type="string">Customily_Categories::product/view/options/type/file.phtml</argument>
</action>
</referenceBlock>
</body>
</page>
<?xml version="1.0"?>
<!--
/**
* Copyright © Customily. All rights reserved.
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.options">
<action method="setTemplate">
<argument name="template" xsi:type="string">Customily_Categories::product/view/options.phtml</argument>
</action>
</referenceBlock>
<referenceBlock name="product.info.options.file">
<action method="setTemplate">
<argument name="template" xsi:type="string">Customily_Categories::product/view/options/type/file.phtml</argument>
</action>
</referenceBlock>
</body>
</page>
/**
* Copyright © Customily, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
var config = {
config: {
mixins: {
'Magento_Catalog/js/price-options': {
'Customily_Categories/js/price-options': true
}
}
}
};
This source diff could not be displayed because it is too large. You can view the blob instead.
<?php
/**
* Copyright © Customily. All rights reserved.
*/
?>
<?php
$_option = $block->getOption();
$_fileInfo = $block->getFileInfo();
$_fileExists = $_fileInfo->hasData();
$_fileName = 'options_' . $block->escapeHtmlAttr($_option->getId()) . '_file';
$_fieldNameAction = $_fileName . '_action';
$_fieldValueAction = $_fileExists ? 'save_old' : 'save_new';
$_fileNamed = $_fileName . '_name';
$class = $_option->getIsRequire() ? ' required' : '';
/* @var \Customily\Categories\Helper\CustomilyHelper $customilyHelper */
$customilyHelper = $this->helper('Customily\Categories\Helper\CustomilyHelper');
$settings = $customilyHelper->getCustomilyConfig();
$isCustomlyEnabled = $settings['enable'] ?? false;
$isCustomilyProduct = $this->getProduct()->getCustomProduct();
$isCustomilyProduct = $isCustomilyProduct ?? false;
$customilyProductId = $this->getProduct()->getProductCustomizationId();
$isValidCustomilyProductId = isset($customilyProductId) && $customilyHelper->validateGuid(trim($customilyProductId));
$isCustomilyAvailable = $isCustomlyEnabled === '1' && $isCustomilyProduct === '1' && $isValidCustomilyProductId;
?>
<div class="field file<?= /* @escapeNotVerified */ $class ?> customily-file-field" style="<?= $isCustomilyAvailable ? 'visibility: hidden' : 'visibility: visible' ?>">
<?php
if ($isCustomilyAvailable) {
?>
<label class="label" id="<?= /* @noEscape */ $_fileName ?>-label">
<span><?= $block->escapeHtml($_option->getTitle()) ?></span>
</label>
<div class="control visible" id="input-box-<?= /* @escapeNotVerified */ $_fileName ?>"
data-mage-init='{"priceOptionFile":{
"fileName":"<?= /* @noEscape */ $_fileName ?>",
"fileNamed":"<?= /* @noEscape */ $_fileNamed ?>",
"fieldNameAction":"<?= /* @escapeNotVerified */ $_fieldNameAction ?>",
"changeFileSelector":"#change-<?= /* @noEscape */ $_fileName ?>",
"deleteFileSelector":"#delete-<?= /* @noEscape */ $_fileName ?>"
}
}'>
<div class="upload-button-group">
<input type="file"
id="<?= /* @escapeNotVerified */ $_fileName ?>"
name="<?= /* @noEscape */ $_fileName ?>"
data-option-id="<?php echo $_option->getId();?>"
class="input-file product-custom-option<?= $_option->getCustomilyIsRequired() ? ' required' : '' ?>"
data-option-name="options[<?= /* @escapeNotVerified */ $_option->getId() ?>]"
<?= $_fileExists ? 'disabled="disabled"' : '' ?> />
<input type="hidden" class="file-action" name="<?= /* @noEscape */ $_fieldNameAction ?>" value="<?= /* @noEscape */ $_fieldValueAction ?>" />
<button id="change-<?= /* @noEscape */ $_fileName ?>" type="button" class="upload-button">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17">
<path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"/>
</svg>
<span><?= /* @escapeNotVerified */ __('Upload file') ?></span>
</button>
<button id="delete-<?= /* @noEscape */ $_fileName ?>" type="button" class="hidden remove-image" data-option-id="<?php echo $_option->getId();?>"> X </button>
</div>
<p class="customily-file-name hidden"></p>
<?php if ($_option['customily_image_min_size_x'] > 0 || $_option['customily_image_min_size_y'] > 0 || $_option->getImageSizeX() > 0 || $_option->getImageSizeY() > 0): ?>
<small class="customily-invalid-size-error hidden">
<?= /* @escapeNotVerified */ __('* Your image does not meet the resolution requirements.') ?>
</small>
<?php endif; ?>
<?php if ($_option->getFileExtension()): ?>
<p class="note">
<?= /* @escapeNotVerified */ __('Compatible file extensions to upload') ?>: <strong><?= /* @escapeNotVerified */ $_option->getFileExtension() ?></strong>
</p>
<?php endif; ?>
<?php if ($_option['customily_image_min_size_x'] > 0 || $_option['customily_image_min_size_y'] > 0): ?>
<p class="note">
<?= /* @escapeNotVerified */ __('Minimum image width') ?>: <strong><?= /* @escapeNotVerified */ $_option['customily_image_min_size_x'] ?> <?= /* @escapeNotVerified */ __('px. ') ?></strong>
<?= /* @escapeNotVerified */ __('Minimum image height') ?>: <strong><?= /* @escapeNotVerified */ $_option['customily_image_min_size_y'] ?> <?= /* @escapeNotVerified */ __('px.') ?></strong>
</p>
<?php endif; ?>
<?php if ($_option->getImageSizeX() > 0 || $_option->getImageSizeY() > 0): ?>
<p class="note">
<?= /* @escapeNotVerified */ __('Maximum image width') ?>: <strong><?= /* @escapeNotVerified */ $_option->getImageSizeX() ?> <?= /* @escapeNotVerified */ __('px. ') ?></strong>
<?= /* @escapeNotVerified */ __('Maximum image height') ?>: <strong><?= /* @escapeNotVerified */ $_option->getImageSizeY() ?> <?= /* @escapeNotVerified */ __('px.') ?></strong>
</p>
<?php endif; ?>
</div>
<?php } else { ?>
<label class="label" for="<?= /* @noEscape */ $_fileName ?>" id="<?= /* @noEscape */ $_fileName ?>-label">
<span><?= $block->escapeHtml($_option->getTitle()) ?></span>
<?= /* @noEscape */ $block->getFormattedPrice() ?>
</label>
<?php if ($_fileExists) :?>
<div class="control">
<span class="<?= /* @noEscape */ $_fileNamed ?>"><?= $block->escapeHtml($_fileInfo->getTitle()) ?></span>
<a href="javascript:void(0)" class="label" id="change-<?= /* @noEscape */ $_fileName ?>" >
<?= $block->escapeHtml(__('Change')) ?>
</a>
<?php if (!$_option->getIsRequire()) :?>
<input type="checkbox" id="delete-<?= /* @noEscape */ $_fileName ?>" />
<span class="label"><?= $block->escapeHtml(__('Delete')) ?></span>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="control" id="input-box-<?= /* @noEscape */ $_fileName ?>"
data-mage-init='{"priceOptionFile":{
"fileName":"<?= /* @noEscape */ $_fileName ?>",
"fileNamed":"<?= /* @noEscape */ $_fileNamed ?>",
"fieldNameAction":"<?= /* @noEscape */ $_fieldNameAction ?>",
"changeFileSelector":"#change-<?= /* @noEscape */ $_fileName ?>",
"deleteFileSelector":"#delete-<?= /* @noEscape */ $_fileName ?>"}
}'
<?= $_fileExists ? 'style="display:none"' : '' ?>>
<input type="file"
name="<?= /* @noEscape */ $_fileName ?>"
id="<?= /* @noEscape */ $_fileName ?>"
class="product-custom-option<?= $_option->getIsRequire() ? ' required' : '' ?>"
<?= $_fileExists ? 'disabled="disabled"' : '' ?> />
<input type="hidden" name="<?= /* @noEscape */ $_fieldNameAction ?>" value="<?= /* @noEscape */ $_fieldValueAction ?>" />
<?php if ($_option->getFileExtension()) :?>
<p class="note">
<?= $block->escapeHtml(__('Compatible file extensions to upload')) ?>: <strong><?= $block->escapeHtml($_option->getFileExtension()) ?></strong>
</p>
<?php endif; ?>
<?php if ($_option->getImageSizeX() > 0) :?>
<p class="note">
<?= $block->escapeHtml(__('Maximum image width')) ?>: <strong><?= (int)$_option->getImageSizeX() ?> <?= $block->escapeHtml(__('px.')) ?></strong>
</p>
<?php endif; ?>
<?php if ($_option->getImageSizeY() > 0) :?>
<p class="note">
<?= $block->escapeHtml(__('Maximum image height')) ?>: <strong><?= (int)$_option->getImageSizeY() ?> <?= $block->escapeHtml(__('px.')) ?></strong>
</p>
<?php endif; ?>
</div>
<?php } ?>
</div>
/**
* Copyright © Customily, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'jquery',
'Magento_Ui/js/modal/modal'
], function ($) {
'use strict';
$.widget('customily.personalizationModal', {
options: {
customilyPopupInitButton: '[data-role=customily-popup-modal-button]',
hasCustomilyPopupClass: 'has-customily-popup',
attributesContainer: '[data-role="swatch-options"]',
optionsContainer: '[data-role="customily-options"]',
optionsContainerClass: 'customily-options',
customilyModalContainer: '[data-role="customily-modal-container"]',
customilyModalClass: 'customily-modal',
customilyModalCanvasWrapper: 'fabric-container-modal',
customilyModalProductInfoClass: '.cl-personalization-product-info',
tocartFormFields: '.product-add-form [data-role="customily-options"]',
tocartModalButtonClass: '.cl-personalization-button',
tocartPageButton: '#customily-addtocart-button',
priceConfig: false,
popupOptions: {
type: 'popup',
responsive: true,
innerScroll: true,
buttons: [],
modalClass: 'customily-popup-modal',
title: ''
}
},
_create: function () {
$('body').addClass(this.options.hasCustomilyPopupClass);
this._adjustOptionsContainer();
},
_adjustOptionsContainer: function() {
var self = this,
options = self.options;
setTimeout(function () {
if ($(options.optionsContainer).length > 0) {
var $modalContainer = $('<div/>', {
'class': options.customilyModalClass,
'data-role': 'content'
}).appendTo(options.optionsContainer);
var $modalCanvasWrapper = $('<div/>', {
'id': options.customilyModalCanvasWrapper,
'class': options.customilyModalCanvasWrapper
}).appendTo($modalContainer);
var $optionsContainer = $(options.optionsContainer);
var $optionsContainerCloned = $optionsContainer.clone(true);
$optionsContainer.removeClass(options.optionsContainerClass).addClass('hidden');
$optionsContainerCloned.addClass(options.optionsContainerClass).appendTo($modalContainer);
if (customily.attributes_options && customily.attributes_options.length > 0) {
var t = 0;
var checkAttrsInterval = setInterval(function () {
var $attributeInputs = $(options.attributesContainer + ' input[type="text"]');
if ($attributeInputs.length == customily.attributes_options.length) {
var $attributesContainer = $(options.attributesContainer);
$attributesContainer.find('select').each(function () {
var $that = $(this);
if (!$that.attr('id')) {
var $parent = $that.parents('.swatch-attribute');
var attrId = $parent.attr('attribute-id') || $parent.attr('data-attribute-id');
$that.attr('id', 'select-attribute-' + attrId);
}
});
var $attributesContainerCloned = $attributesContainer.clone(true);
$attributesContainerCloned.find('.swatch-attribute').addClass('swatch-attribute-md');
if (customily.isMobile()) {
$optionsContainerCloned.prepend($attributesContainerCloned);
} else {
$optionsContainerCloned.find('.cl-personalization-product-info').after($attributesContainerCloned);
}
$attributesContainer.addClass('hidden');
self._handleAttributes();
console.log('Customily Magento: attributes are ready.');
clearInterval(checkAttrsInterval);
}
if (t > 30000) clearInterval(checkAttrsInterval);
t += 250;
}, 250);
}
$('#customily-popup-modal-button').show();
$('.start-configurator-wrapper').show();
$('.product-social-links').show();
if (customily.isMobile()) {
if (!$modalCanvasWrapper.find('.' + options.customilyModalClass + ' ' + options.customilyModalProductInfoClass).length) {
$modalCanvasWrapper.prepend($('.' + options.customilyModalClass + ' ' + options.customilyModalProductInfoClass));
}
}
self._renameFieldsAttr();
var popup = $('.' + options.customilyModalClass).modal(options.popupOptions);
$(options.customilyPopupInitButton).on('click', function () {
$('.' + options.optionsContainerClass).addClass('hidden');
$(options.attributesContainer).css('visibility', 'visible');
$('.' + options.customilyModalClass + ' ' + options.tocartModalButtonClass).show();
$('.' + options.customilyModalClass + ' .cl-personalization-price-container').show();
$('.' + options.customilyModalClass + ' ' + options.customilyModalProductInfoClass).show();
customily.updatePriceElement();
$('.' + options.customilyModalClass).modal('openModal');
});
$(document).on('click', options.tocartModalButtonClass, function () {
if (customily.validateRequired() == 0) {
popup.modal('closeModal');
setTimeout(function () {
$(options.tocartPageButton).trigger('click');
}, 200);
}
});
customily.priceConfig = options.priceConfig;
popup.on('modalopened', function () {
self.onModalOpened();
setTimeout(function() {
$('.' + options.optionsContainerClass).css('visibility', 'visible').removeClass('hidden').show();
$('.customily-file-field').css('visibility', 'visible');
}, 300);
});
popup.on('modalclosed', function () {
self._copyEnteredValues();
});
}
}, 1000);
},
onModalOpened: function () {
this._copyPreview();
customily.handleCustomilyOptions();
if (customily.isMobile()) {
var $personalizationBox = $('._show .customily-options .cl-personalization-box');
$personalizationBox.css('position', 'fixed').css('bottom', '0');
$('._show .modal-inner-wrap').css('max-height', window.outerHeight + 'px').append($personalizationBox);
}
customily.checkSelection();
},
_copyPreview: function () {
var canvasWrapper = '.canvas-wrapper',
$modalCanvasWrapper = $('#' + this.options.customilyModalCanvasWrapper);
if (!$modalCanvasWrapper.find(canvasWrapper).length) {
if (customily.isMobile()) {
$modalCanvasWrapper.append($(canvasWrapper));
} else {
$modalCanvasWrapper.prepend($(canvasWrapper));
}
$(canvasWrapper).addClass('visible');
}
customily.displayProductImage();
},
_handleAttributes: function () {
var $attributeContainer = $('.' + this.options.customilyModalClass + ' ' + this.options.attributesContainer);
$attributeContainer.find('.swatch-option').each(function () {
$(this).attr('data-id', $(this).attr('id'));
$(this).attr('id', $(this).attr('id') + '_md');
});
$attributeContainer.find('select').each(function () {
$(this).attr('data-id', $(this).attr('id'));
$(this).attr('id', $(this).attr('id') + '_md');
});
},
_renameFieldsAttr: function() {
$('.' + this.options.customilyModalClass + ' .' + this.options.optionsContainerClass).find('.control').each(function () {
var $that = $(this);
if ($that.find('label').length) {
$that.find('label').each(function() {
if ($(this).attr('for')) {
$(this).attr('for', $(this).attr('for') + '_md');
}
});
}
if ($that.find('input').length) {
$that.find('input').each(function() {
if ($(this).attr('id')) {
$(this).attr('data-id', $(this).attr('id'));
$(this).attr('id', $(this).attr('id') + '_md');
}
});
}
if ($that.find('textarea').length) {
$that.find('textarea').each(function() {
if ($(this).attr('id')) {
$(this).attr('data-id', $(this).attr('id'));
$(this).attr('id', $(this).attr('id') + '_md');
}
});
}
if ($that.find('select').length) {
$that.find('select').each(function() {
if ($(this).attr('id')) {
$(this).attr('data-id', $(this).attr('id'));
$(this).attr('id', $(this).attr('id') + '_md');
}
});
}
});
},
_copyEnteredValues: function() {
var options = this.options,
controlAttr = [];
var $optionsContainer = $('.' + options.customilyModalClass + ' .' + options.optionsContainerClass);
if (customily.attributes_options.length > 0) {
var $attributes = $optionsContainer.find('.swatch-attribute');
$attributes.each(function () {
var $that = $(this);
var value = $that.attr('option-selected') || $that.attr('data-option-selected');
var $attrEl = $(':not(.customily-options) .swatch-attribute[attribute-id="' + $that.attr('attribute-id') + '"]');
var dataAttr = false;
if (!$attrEl.length) {
$attrEl = $(':not(.customily-options) .swatch-attribute[data-attribute-id="' + $that.attr('data-attribute-id') + '"]');
dataAttr = true;
}
if (dataAttr) {
$attrEl.attr('data-option-selected', $that.attr('data-option-selected'));
} else {
$attrEl.attr('option-selected', $that.attr('option-selected'));
}
var $input = $($attrEl).find('input:text');
if ($input.length) {
$input.val(value);
$input.trigger('change', { force: true });
}
var $select = $($attrEl).find('select');
if ($select.length) {
$select.val(value);
$input.trigger('change', { force: true });
}
});
}
$optionsContainer.find('.control').filter(function () {
return $(this).is(':visible');
}).each(function () {
var $that = $(this);
var $input = $that.find('input:text');
if ($input.length) {
controlAttr.push({
id: $input.attr('data-id'),
value: $input.val()
});
}
var $file = $that.find('input:file');
if ($file.length) {
controlAttr.push({
id: $file.attr('data-id'),
type: 'file',
$el: $file
});
}
var $radio = $that.find('input:radio').filter(function() { return $(this).prop('checked') == true });
if ($radio.length) {
controlAttr.push({
id: $radio.attr('data-id'),
value: $radio.attr('value'),
type: 'radio'
});
}
var $checkbox = $that.find('input:checkbox').filter(function() { return $(this).prop('checked') == true });
if ($checkbox.length) {
controlAttr.push({
id: $checkbox.attr('data-id'),
value: $checkbox.attr('value'),
type: 'checkbox'
});
}
var $textarea = $that.find('textarea');
if ($textarea.length) {
controlAttr.push({
id: $textarea.attr('data-id'),
value: $textarea.val()
});
}
var $select = $that.find('select');
if ($select.length) {
controlAttr.push({
id: $select.attr('data-id'),
value: $select.children('option:selected').val()
});
}
});
controlAttr.forEach(function (input) {
if (input.type == 'file') {
var $el = $(options.tocartFormFields).find('#' + input.id);
var $newEl = input.$el.clone();
$el.attr('id', input.id + 'tmp')
$newEl.attr('id', input.id)
$el.after($newEl);
$el.remove();
$newEl.trigger('change');
} else {
var $el = $(options.tocartFormFields).find('#' + input.id);
if (input.type == 'radio' || input.type == 'checkbox') {
$(options.tocartFormFields).find('[name="' + $el.attr('name') + '"]').removeProp('checked');
$el.prop('checked', true);
}
$el.val(input.value).trigger('change');
}
});
}
});
return $.customily.personalizationModal;
});
\ No newline at end of file
/**
* Copyright © Customily, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
define([
'jquery',
'underscore',
'priceUtils',
'priceBox',
'jquery-ui-modules/widget'
], function ($, _, utils) {
'use strict';
var globalOptions = {
productId: null,
priceHolderSelector: '.price-box', //data-role="priceBox"
optionsSelector: '.product-custom-option',
optionConfig: {},
optionHandlers: {},
optionTemplate: '<%= data.label %>' +
'<% if (data.finalPrice.value > 0) { %>' +
' +<%- data.finalPrice.formatted %>' +
'<% } else if (data.finalPrice.value < 0) { %>' +
' <%- data.finalPrice.formatted %>' +
'<% } %>',
controlContainer: 'dd'
};
var defaultGetOptionValue;
if (
window.customily &&
window.customily.personalization &&
window.customily.personalization.handlePrices == '1' &&
window.customily.defaultGetOptionValue
) {
defaultGetOptionValue = window.customily.defaultGetOptionValue;
} else {
defaultGetOptionValue = function(element, optionsConfig) {
var changes = {},
optionValue = element.val(),
optionId = utils.findOptionId(element[0]),
optionName = element.prop('name'),
optionType = element.prop('type'),
optionConfig = optionsConfig[optionId],
optionHash = optionName;
switch (optionType) {
case 'text':
case 'textarea':
changes[optionHash] = optionValue ? optionConfig.prices : {};
break;
case 'radio':
if (element.is(':checked')) {
changes[optionHash] = optionConfig[optionValue] && optionConfig[optionValue].prices || {};
}
break;
case 'select-one':
changes[optionHash] = optionConfig[optionValue] && optionConfig[optionValue].prices || {};
break;
case 'select-multiple':
_.each(optionConfig, function (row, optionValueCode) {
optionHash = optionName + '##' + optionValueCode;
changes[optionHash] = _.contains(optionValue, optionValueCode) ? row.prices : {};
});
break;
case 'checkbox':
optionHash = optionName + '##' + optionValue;
changes[optionHash] = element.is(':checked') ? optionConfig[optionValue].prices : {};
break;
case 'file':
// Checking for 'disable' property equal to checking DOMNode with id*="change-"
changes[optionHash] = optionValue || element.prop('disabled') ? optionConfig.prices : {};
break;
}
return changes;
};
}
return function (widget) {
$.widget('mage.priceOptions', widget, {
options: globalOptions,
_onOptionChanged: function onOptionChanged(event) {
var $element = $(event.target);
var $controlContainer = $element.closest(this.options.controlContainer);
if ($controlContainer.length) {
$element.data('optionContainer', $controlContainer);
var handler = this.options.optionHandlers[$element.data('role')];
var changes;
if (handler && handler instanceof Function) {
changes = handler($element, this.options.optionConfig, this);
} else {
changes = defaultGetOptionValue($element, this.options.optionConfig);
}
$(this.options.priceHolderSelector).trigger('updatePrice', changes);
}
}
});
return $.mage.priceOptions;
}
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment