xmlui 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Pdf-DeGhSMXe.mjs +19537 -0
- package/dist/Pdf.css +1 -0
- package/dist/apiInterceptorWorker-CwuUhYyc.mjs +9229 -0
- package/dist/array-USo-Szhp.mjs +12 -0
- package/dist/index-C24dkfpd.mjs +1434 -0
- package/dist/index-ao27SnVp.mjs +145185 -0
- package/dist/index.css +1 -0
- package/dist/nivo-bar.es-CWh0ZlxB.mjs +1666 -0
- package/dist/nivo-geo.es-BTqNt5Db.mjs +1579 -0
- package/dist/nivo-legends.es-BuIxHGSU.mjs +6916 -0
- package/dist/nivo-pie.es-BvCBFA0L.mjs +700 -0
- package/dist/react-apexcharts.min-DqWuDOyO.mjs +8881 -0
- package/dist/scripts/bin/bootstrap.js +11 -0
- package/dist/scripts/bin/build.js +256 -0
- package/dist/scripts/bin/index.js +88 -0
- package/dist/scripts/bin/preview.js +27 -0
- package/dist/scripts/bin/start.js +41 -0
- package/dist/scripts/bin/vite-ueml-plugin.js +113 -0
- package/dist/scripts/bin/viteConfig.js +112 -0
- package/dist/scripts/src/abstractions/ActionDefs.js +2 -0
- package/dist/scripts/src/abstractions/AppContextDefs.js +2 -0
- package/dist/scripts/src/abstractions/BlockScope.js +4 -0
- package/dist/scripts/src/abstractions/ComponentDefs.js +2 -0
- package/dist/scripts/src/abstractions/ComponentDescriptorDefs.js +2 -0
- package/dist/scripts/src/abstractions/ContainerDefs.js +2 -0
- package/dist/scripts/src/abstractions/FunctionDefs.js +2 -0
- package/dist/scripts/src/abstractions/RendererDefs.js +2 -0
- package/dist/scripts/src/abstractions/scripting/ScriptParserError.js +2 -0
- package/dist/scripts/src/abstractions/scripting/ScriptingSourceTree.js +2 -0
- package/dist/scripts/src/abstractions/scripting/Token.js +110 -0
- package/dist/scripts/src/components/App/App.js +253 -0
- package/dist/scripts/src/components/App/AppLayoutContext.js +9 -0
- package/dist/scripts/src/components/App/AppStateContext.js +9 -0
- package/dist/scripts/src/components/App/Sheet.js +89 -0
- package/dist/scripts/src/components/AppHeader/AppHeader.js +121 -0
- package/dist/scripts/src/components/AppState/AppState.js +29 -0
- package/dist/scripts/src/components/Avatar/Avatar.js +81 -0
- package/dist/scripts/src/components/Badge/Badge.js +56 -0
- package/dist/scripts/src/components/BarChart/BarChart.js +199 -0
- package/dist/scripts/src/components/Bookmark/Bookmark.js +11 -0
- package/dist/scripts/src/components/Button/Button.js +196 -0
- package/dist/scripts/src/components/Card/Card.js +65 -0
- package/dist/scripts/src/components/ChangeListener/ChangeListener.js +43 -0
- package/dist/scripts/src/components/Chart/Chart.js +158 -0
- package/dist/scripts/src/components/Checkbox/Checkbox.js +43 -0
- package/dist/scripts/src/components/Combobox/Combobox.js +145 -0
- package/dist/scripts/src/components/ComponentProvider.js +357 -0
- package/dist/scripts/src/components/ContentSeparator/ContentSeparator.js +40 -0
- package/dist/scripts/src/components/DatePicker/DatePicker.js +196 -0
- package/dist/scripts/src/components/DropdownMenu/DropdownMenu.js +175 -0
- package/dist/scripts/src/components/EmojiSelector/EmojiSelector.js +56 -0
- package/dist/scripts/src/components/FileInput/FileInput.js +127 -0
- package/dist/scripts/src/components/FileUploadDropZone/FileUploadDropZone.js +106 -0
- package/dist/scripts/src/components/FlowLayout/FlowLayout.js +139 -0
- package/dist/scripts/src/components/Footer/Footer.js +42 -0
- package/dist/scripts/src/components/Form/Form.js +320 -0
- package/dist/scripts/src/components/Form/FormContext.js +9 -0
- package/dist/scripts/src/components/Form/formActions.js +86 -0
- package/dist/scripts/src/components/FormItem/FormItem.js +204 -0
- package/dist/scripts/src/components/FormItem/HelperText.js +27 -0
- package/dist/scripts/src/components/FormItem/ItemWithLabel.js +39 -0
- package/dist/scripts/src/components/FormItem/Validations.js +346 -0
- package/dist/scripts/src/components/FormSection/FormSection.js +45 -0
- package/dist/scripts/src/components/Heading/Heading.js +206 -0
- package/dist/scripts/src/components/HoverCard/HoverCard.js +45 -0
- package/dist/scripts/src/components/Icon/ApiIcon.js +10 -0
- package/dist/scripts/src/components/Icon/Attach.js +10 -0
- package/dist/scripts/src/components/Icon/Binding.js +11 -0
- package/dist/scripts/src/components/Icon/BoardIcon.js +7 -0
- package/dist/scripts/src/components/Icon/BoxIcon.js +10 -0
- package/dist/scripts/src/components/Icon/CheckIcon.js +7 -0
- package/dist/scripts/src/components/Icon/ChevronDownIcon.js +7 -0
- package/dist/scripts/src/components/Icon/ChevronLeft.js +7 -0
- package/dist/scripts/src/components/Icon/ChevronRight.js +7 -0
- package/dist/scripts/src/components/Icon/ChevronUpIcon.js +7 -0
- package/dist/scripts/src/components/Icon/CodeFileIcon.js +10 -0
- package/dist/scripts/src/components/Icon/CodeSandbox.js +10 -0
- package/dist/scripts/src/components/Icon/CompactListIcon.js +7 -0
- package/dist/scripts/src/components/Icon/ContentCopyIcon.js +7 -0
- package/dist/scripts/src/components/Icon/DatabaseIcon.js +11 -0
- package/dist/scripts/src/components/Icon/DocFileIcon.js +10 -0
- package/dist/scripts/src/components/Icon/DocIcon.js +10 -0
- package/dist/scripts/src/components/Icon/DotMenuHorizontalIcon.js +7 -0
- package/dist/scripts/src/components/Icon/DotMenuIcon.js +7 -0
- package/dist/scripts/src/components/Icon/EmailIcon.js +7 -0
- package/dist/scripts/src/components/Icon/EmptyFolderIcon.js +10 -0
- package/dist/scripts/src/components/Icon/ErrorIcon.js +7 -0
- package/dist/scripts/src/components/Icon/ExpressionIcon.js +10 -0
- package/dist/scripts/src/components/Icon/FillPlusCricleIcon.js +7 -0
- package/dist/scripts/src/components/Icon/FilterIcon.js +10 -0
- package/dist/scripts/src/components/Icon/FolderIcon.js +10 -0
- package/dist/scripts/src/components/Icon/GlobeIcon.js +7 -0
- package/dist/scripts/src/components/Icon/HomeIcon.js +7 -0
- package/dist/scripts/src/components/Icon/HyperLinkIcon.js +7 -0
- package/dist/scripts/src/components/Icon/Icon.js +101 -0
- package/dist/scripts/src/components/Icon/ImageFileIcon.js +10 -0
- package/dist/scripts/src/components/Icon/LinkIcon.js +7 -0
- package/dist/scripts/src/components/Icon/ListIcon.js +7 -0
- package/dist/scripts/src/components/Icon/LooseListIcon.js +7 -0
- package/dist/scripts/src/components/Icon/MoonIcon.js +10 -0
- package/dist/scripts/src/components/Icon/MoreOptionsIcon.js +7 -0
- package/dist/scripts/src/components/Icon/PDFIcon.js +10 -0
- package/dist/scripts/src/components/Icon/PenIcon.js +7 -0
- package/dist/scripts/src/components/Icon/PhoneIcon.js +7 -0
- package/dist/scripts/src/components/Icon/PhotoIcon.js +10 -0
- package/dist/scripts/src/components/Icon/PlusIcon.js +7 -0
- package/dist/scripts/src/components/Icon/SearchIcon.js +7 -0
- package/dist/scripts/src/components/Icon/ShareIcon.js +10 -0
- package/dist/scripts/src/components/Icon/SunIcon.js +10 -0
- package/dist/scripts/src/components/Icon/TrashIcon.js +7 -0
- package/dist/scripts/src/components/Icon/TxtIcon.js +10 -0
- package/dist/scripts/src/components/Icon/UnknownFileIcon.js +10 -0
- package/dist/scripts/src/components/Icon/UnlinkIcon.js +10 -0
- package/dist/scripts/src/components/Icon/UserIcon.js +7 -0
- package/dist/scripts/src/components/Icon/WarningIcon.js +7 -0
- package/dist/scripts/src/components/Icon/XlsIcon.js +10 -0
- package/dist/scripts/src/components/IconProvider.js +249 -0
- package/dist/scripts/src/components/IconRegistryContext.js +307 -0
- package/dist/scripts/src/components/Image/Image.js +34 -0
- package/dist/scripts/src/components/Input/InputAdornment.js +14 -0
- package/dist/scripts/src/components/Input/input-abstractions.js +44 -0
- package/dist/scripts/src/components/Items/Items.js +48 -0
- package/dist/scripts/src/components/Link/Link.js +72 -0
- package/dist/scripts/src/components/List/List.js +442 -0
- package/dist/scripts/src/components/Logo/Logo.js +25 -0
- package/dist/scripts/src/components/Map/Map.js +60 -0
- package/dist/scripts/src/components/Map/world_countries.json +45307 -0
- package/dist/scripts/src/components/Markdown/Markdown.js +120 -0
- package/dist/scripts/src/components/ModalDialog/ConfirmationModalContextProvider.js +106 -0
- package/dist/scripts/src/components/ModalDialog/Dialog.js +20 -0
- package/dist/scripts/src/components/ModalDialog/ModalDialog.js +145 -0
- package/dist/scripts/src/components/MultiCombobox/MultiCombobox.js +249 -0
- package/dist/scripts/src/components/MultiSelect/MultiSelect.js +192 -0
- package/dist/scripts/src/components/NavGroup/NavGroup.js +113 -0
- package/dist/scripts/src/components/NavLink/NavLink.js +115 -0
- package/dist/scripts/src/components/NavPanel/NavPanel.js +101 -0
- package/dist/scripts/src/components/NoResult/NoResult.js +39 -0
- package/dist/scripts/src/components/NumberBox/NumberBox.js +373 -0
- package/dist/scripts/src/components/Option/Option.js +41 -0
- package/dist/scripts/src/components/PageMetaTitle/PageMetaTitle.js +22 -0
- package/dist/scripts/src/components/Pages/Pages.js +74 -0
- package/dist/scripts/src/components/Pdf/LazyPdf.js +44 -0
- package/dist/scripts/src/components/Pdf/Pdf.js +19 -0
- package/dist/scripts/src/components/PieChart/PieChart.js +184 -0
- package/dist/scripts/src/components/PositionedContainer/PositionedContainer.js +29 -0
- package/dist/scripts/src/components/ProgressBar/ProgressBar.js +38 -0
- package/dist/scripts/src/components/Queue/Queue.js +286 -0
- package/dist/scripts/src/components/Queue/queueActions.js +87 -0
- package/dist/scripts/src/components/RadioGroup/RadioGroup.js +144 -0
- package/dist/scripts/src/components/RealTimeAdapter/RealTimeAdapter.js +147 -0
- package/dist/scripts/src/components/Redirect/Redirect.js +10 -0
- package/dist/scripts/src/components/Select/Select.js +139 -0
- package/dist/scripts/src/components/Select/SelectContext.js +45 -0
- package/dist/scripts/src/components/SelectionStore/SelectionStore.js +88 -0
- package/dist/scripts/src/components/SpaceFiller/SpaceFiller.js +22 -0
- package/dist/scripts/src/components/Spinner/Spinner.js +59 -0
- package/dist/scripts/src/components/Splitter/Splitter.js +205 -0
- package/dist/scripts/src/components/Splitter/utils.js +17 -0
- package/dist/scripts/src/components/Stack/Stack.js +117 -0
- package/dist/scripts/src/components/StickyBox/StickyBox.js +33 -0
- package/dist/scripts/src/components/Switch/Switch.js +50 -0
- package/dist/scripts/src/components/Table/Table.js +499 -0
- package/dist/scripts/src/components/Table/useRowSelection.js +169 -0
- package/dist/scripts/src/components/TableColumnDef/TableColumnDef.js +44 -0
- package/dist/scripts/src/components/TableColumnDef/TableContext.js +12 -0
- package/dist/scripts/src/components/Tabs/Tabs.js +85 -0
- package/dist/scripts/src/components/Text/Text.js +175 -0
- package/dist/scripts/src/components/TextArea/TextArea.js +194 -0
- package/dist/scripts/src/components/TextArea/TextAreaResizable.js +63 -0
- package/dist/scripts/src/components/TextArea/useComposedRef.js +50 -0
- package/dist/scripts/src/components/TextBox/TextBox.js +145 -0
- package/dist/scripts/src/components/Theme/NotificationToast.js +39 -0
- package/dist/scripts/src/components/Theme/Theme.js +153 -0
- package/dist/scripts/src/components/ThemeChanger/ThemeChanger.js +125 -0
- package/dist/scripts/src/components/Toggle/Toggle.js +88 -0
- package/dist/scripts/src/components/Tree/TreeComponent.js +79 -0
- package/dist/scripts/src/components/ValidationSummary/ValidationSummary.js +59 -0
- package/dist/scripts/src/components/ViewComponentRegistryContext.js +34 -0
- package/dist/scripts/src/components/abstractions.js +2 -0
- package/dist/scripts/src/components/chart-color-schemes.js +43 -0
- package/dist/scripts/src/components/component-utils.js +32 -0
- package/dist/scripts/src/components/container-helpers.js +18 -0
- package/dist/scripts/src/components-core/ApiBoundComponent.js +189 -0
- package/dist/scripts/src/components-core/AppContext.js +17 -0
- package/dist/scripts/src/components-core/ChildrenSlot.js +10 -0
- package/dist/scripts/src/components-core/Component.js +280 -0
- package/dist/scripts/src/components-core/ComponentDecorator.js +63 -0
- package/dist/scripts/src/components-core/CompoundComponent.js +132 -0
- package/dist/scripts/src/components-core/EngineError.js +91 -0
- package/dist/scripts/src/components-core/ErrorBoundary.js +58 -0
- package/dist/scripts/src/components-core/Fragment.js +14 -0
- package/dist/scripts/src/components-core/InvalidComponent.js +15 -0
- package/dist/scripts/src/components-core/LoaderComponent.js +78 -0
- package/dist/scripts/src/components-core/RestApiProxy.js +341 -0
- package/dist/scripts/src/components-core/RootComponent.js +272 -0
- package/dist/scripts/src/components-core/RouteContext.js +45 -0
- package/dist/scripts/src/components-core/ScrollContext.js +9 -0
- package/dist/scripts/src/components-core/UnknownComponent.js +15 -0
- package/dist/scripts/src/components-core/abstractions/ComponentRenderer.js +2 -0
- package/dist/scripts/src/components-core/abstractions/LoaderRenderer.js +2 -0
- package/dist/scripts/src/components-core/abstractions/containers.js +18 -0
- package/dist/scripts/src/components-core/abstractions/treeAbstractions.js +2 -0
- package/dist/scripts/src/components-core/action/ApiAction.js +276 -0
- package/dist/scripts/src/components-core/action/DownloadFileAction.js +80 -0
- package/dist/scripts/src/components-core/action/NavigateAction.js +20 -0
- package/dist/scripts/src/components-core/action/TimedAction.js +21 -0
- package/dist/scripts/src/components-core/action/UploadAction.js +88 -0
- package/dist/scripts/src/components-core/action/actions.js +15 -0
- package/dist/scripts/src/components-core/appContext/date-functions.js +19 -0
- package/dist/scripts/src/components-core/appContext/misc-utils.js +12 -0
- package/dist/scripts/src/components-core/component-hooks.js +25 -0
- package/dist/scripts/src/components-core/constants.js +18 -0
- package/dist/scripts/src/components-core/container/Container.js +1110 -0
- package/dist/scripts/src/components-core/container/ContainerComponentDef.js +16 -0
- package/dist/scripts/src/components-core/container/buildProxy.js +54 -0
- package/dist/scripts/src/components-core/container/collectFnVarDeps.js +26 -0
- package/dist/scripts/src/components-core/container/valueExtractor.js +195 -0
- package/dist/scripts/src/components-core/descriptorHelper.js +75 -0
- package/dist/scripts/src/components-core/interception/abstractions.js +2 -0
- package/dist/scripts/src/components-core/interception/useApiInterceptorContext.js +9 -0
- package/dist/scripts/src/components-core/loader/ApiLoader.js +46 -0
- package/dist/scripts/src/components-core/loader/DataLoader.js +160 -0
- package/dist/scripts/src/components-core/loader/ExternalDataLoader.js +52 -0
- package/dist/scripts/src/components-core/loader/Loader.js +115 -0
- package/dist/scripts/src/components-core/loader/MockLoaderRenderer.js +32 -0
- package/dist/scripts/src/components-core/loader/PageableLoader.js +240 -0
- package/dist/scripts/src/components-core/renderers.js +45 -0
- package/dist/scripts/src/components-core/reportEngineError.js +59 -0
- package/dist/scripts/src/components-core/script-runner/BindingTreeEvaluationContext.js +35 -0
- package/dist/scripts/src/components-core/script-runner/ICustomOperations.js +34 -0
- package/dist/scripts/src/components-core/script-runner/LogicalThread.js +2 -0
- package/dist/scripts/src/components-core/script-runner/LoopScope.js +2 -0
- package/dist/scripts/src/components-core/script-runner/ParameterParser.js +117 -0
- package/dist/scripts/src/components-core/script-runner/TryScope.js +2 -0
- package/dist/scripts/src/components-core/script-runner/asyncProxy.js +96 -0
- package/dist/scripts/src/components-core/script-runner/bannedFunctions.js +34 -0
- package/dist/scripts/src/components-core/script-runner/custom-operations-registry.js +40 -0
- package/dist/scripts/src/components-core/script-runner/custom-ui-data.js +40 -0
- package/dist/scripts/src/components-core/script-runner/eval-tree-async.js +551 -0
- package/dist/scripts/src/components-core/script-runner/eval-tree-common.js +498 -0
- package/dist/scripts/src/components-core/script-runner/eval-tree-sync.js +434 -0
- package/dist/scripts/src/components-core/script-runner/modules.js +250 -0
- package/dist/scripts/src/components-core/script-runner/process-statement-async.js +818 -0
- package/dist/scripts/src/components-core/script-runner/process-statement-common.js +193 -0
- package/dist/scripts/src/components-core/script-runner/process-statement-sync.js +740 -0
- package/dist/scripts/src/components-core/script-runner/statement-queue.js +62 -0
- package/dist/scripts/src/components-core/script-runner/visitors.js +352 -0
- package/dist/scripts/src/components-core/theming/ThemeContext.js +43 -0
- package/dist/scripts/src/components-core/theming/ThemeProvider.js +334 -0
- package/dist/scripts/src/components-core/theming/abstractions.js +11 -0
- package/dist/scripts/src/components-core/theming/extendThemeUtils.js +114 -0
- package/dist/scripts/src/components-core/theming/hvar.js +105 -0
- package/dist/scripts/src/components-core/theming/themeVars.js +62 -0
- package/dist/scripts/src/components-core/theming/themes/base-utils.js +31 -0
- package/dist/scripts/src/components-core/theming/themes/palette.js +53 -0
- package/dist/scripts/src/components-core/theming/themes/root.js +257 -0
- package/dist/scripts/src/components-core/theming/themes/solid.js +16 -0
- package/dist/scripts/src/components-core/theming/themes/theme-colors.js +407 -0
- package/dist/scripts/src/components-core/theming/themes/xmlui.js +32 -0
- package/dist/scripts/src/components-core/theming/transformThemeVars.js +286 -0
- package/dist/scripts/src/components-core/utils/DataLoaderQueryKeyGenerator.js +34 -0
- package/dist/scripts/src/components-core/utils/LruCache.js +184 -0
- package/dist/scripts/src/components-core/utils/actionUtils.js +32 -0
- package/dist/scripts/src/components-core/utils/classnames.js +58 -0
- package/dist/scripts/src/components-core/utils/css-utils.js +127 -0
- package/dist/scripts/src/components-core/utils/date-utils.js +78 -0
- package/dist/scripts/src/components-core/utils/extractParam.js +148 -0
- package/dist/scripts/src/components-core/utils/hooks.js +221 -0
- package/dist/scripts/src/components-core/utils/mergeProps.js +45 -0
- package/dist/scripts/src/components-core/utils/misc.js +460 -0
- package/dist/scripts/src/components-core/utils/statementUtils.js +205 -0
- package/dist/scripts/src/components-core/utils/treeUtils.js +48 -0
- package/dist/scripts/src/components-core/xmlui-parser.js +52 -0
- package/dist/scripts/src/parsers/scripting/InputStream.js +59 -0
- package/dist/scripts/src/parsers/scripting/Lexer.js +1028 -0
- package/dist/scripts/src/parsers/scripting/Parser.js +2647 -0
- package/dist/scripts/src/parsers/scripting/ParserError.js +46 -0
- package/dist/scripts/src/parsers/scripting/TokenTrait.js +109 -0
- package/dist/scripts/src/parsers/scripting/code-behind-collect.js +118 -0
- package/dist/scripts/src/parsers/scripting/tree-visitor.js +602 -0
- package/dist/scripts/src/parsers/style-parser/StyleInputStream.js +39 -0
- package/dist/scripts/src/parsers/style-parser/StyleLexer.js +621 -0
- package/dist/scripts/src/parsers/style-parser/StyleParser.js +1000 -0
- package/dist/scripts/src/parsers/style-parser/errors.js +37 -0
- package/dist/scripts/src/parsers/style-parser/source-tree.js +2 -0
- package/dist/scripts/src/parsers/style-parser/style-compiler.js +513 -0
- package/dist/scripts/src/parsers/style-parser/tokens.js +42 -0
- package/dist/scripts/src/parsers/ueml/ParserError.js +54 -0
- package/dist/scripts/src/parsers/ueml/UemlHelper.js +579 -0
- package/dist/scripts/src/parsers/ueml/UemlInputStream.js +59 -0
- package/dist/scripts/src/parsers/ueml/UemlLexer.js +868 -0
- package/dist/scripts/src/parsers/ueml/UemlParser.js +1439 -0
- package/dist/scripts/src/parsers/ueml/UemlToken.js +24 -0
- package/dist/scripts/src/parsers/ueml/fileExtensions.js +6 -0
- package/dist/scripts/src/parsers/ueml/source-tree.js +2 -0
- package/dist/scripts/src/parsers/ueml/ueml-tree.js +2 -0
- package/dist/scripts/src/parsers/xmlui-parser/CharacterCodes.js +136 -0
- package/dist/scripts/src/parsers/xmlui-parser/diagnostics.js +100 -0
- package/dist/scripts/src/parsers/xmlui-parser/parser.js +476 -0
- package/dist/scripts/src/parsers/xmlui-parser/scanner.js +415 -0
- package/dist/scripts/src/parsers/xmlui-parser/syntax-kind.js +106 -0
- package/dist/scripts/src/parsers/xmlui-parser/syntax-node.js +2 -0
- package/dist/scripts/src/parsers/xmlui-parser/transform.js +922 -0
- package/dist/scripts/src/parsers/xmlui-parser/utils.js +83 -0
- package/dist/xmlui.es.d.ts +1667 -0
- package/dist/xmlui.es.js +17 -0
- package/dist/xmlui.umd.js +1589 -0
- package/package.json +175 -0
|
@@ -0,0 +1,1000 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StyleParser = exports.THEME_VAR_PREFIX = void 0;
|
|
4
|
+
exports.toCssVar = toCssVar;
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
const StyleInputStream_1 = require("./StyleInputStream");
|
|
7
|
+
const StyleLexer_1 = require("./StyleLexer");
|
|
8
|
+
const tokens_1 = require("./tokens");
|
|
9
|
+
exports.THEME_VAR_PREFIX = "xmlui";
|
|
10
|
+
/**
|
|
11
|
+
* This class parses a binding expression and transforms it into an evaluable expression tree
|
|
12
|
+
*/
|
|
13
|
+
class StyleParser {
|
|
14
|
+
/**
|
|
15
|
+
* Initializes the parser with the specified source code
|
|
16
|
+
* @param source Source code to parse
|
|
17
|
+
*/
|
|
18
|
+
constructor(source) {
|
|
19
|
+
this.source = source;
|
|
20
|
+
// --- Keep track of error messages
|
|
21
|
+
this._parseErrors = [];
|
|
22
|
+
this._lexer = new StyleLexer_1.StyleLexer(new StyleInputStream_1.StyleInputStream(source));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The errors raised during the parse phase
|
|
26
|
+
*/
|
|
27
|
+
get errors() {
|
|
28
|
+
return this._parseErrors;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Gets the current token
|
|
32
|
+
*/
|
|
33
|
+
get current() {
|
|
34
|
+
return this._lexer.peek();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Checks if we're at the end of the expression
|
|
38
|
+
*/
|
|
39
|
+
get isEof() {
|
|
40
|
+
return this._lexer.peek().type === tokens_1.StyleTokenType.Eof;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Gets the characters remaining after parsing
|
|
44
|
+
*/
|
|
45
|
+
getTail() {
|
|
46
|
+
return this._lexer.getTail();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Tests if the parse is complete
|
|
50
|
+
*/
|
|
51
|
+
testCompleted() {
|
|
52
|
+
const token = this._lexer.peek(true);
|
|
53
|
+
if (token.type === tokens_1.StyleTokenType.Eof)
|
|
54
|
+
return true;
|
|
55
|
+
if (token.type === tokens_1.StyleTokenType.Ws) {
|
|
56
|
+
this._lexer.get(true);
|
|
57
|
+
return this._lexer.peek().type === tokens_1.StyleTokenType.Eof;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Parses a size value with its unit
|
|
65
|
+
*/
|
|
66
|
+
parseSize() {
|
|
67
|
+
return this.parseSizeLike("px");
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Parses a line height value
|
|
71
|
+
*/
|
|
72
|
+
parseLineHeight() {
|
|
73
|
+
return this.parseSizeLike("");
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Parses size and allows "fit-content"
|
|
77
|
+
*/
|
|
78
|
+
parseMargin() {
|
|
79
|
+
const startToken = this._lexer.peek();
|
|
80
|
+
if (startToken.type === tokens_1.StyleTokenType.Auto) {
|
|
81
|
+
this._lexer.get();
|
|
82
|
+
return this.createNode("Size", {
|
|
83
|
+
value: -1,
|
|
84
|
+
unit: "",
|
|
85
|
+
extSize: startToken.text,
|
|
86
|
+
}, startToken);
|
|
87
|
+
}
|
|
88
|
+
return this.parseSize();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parses an opacity value
|
|
92
|
+
*/
|
|
93
|
+
parseOpacity() {
|
|
94
|
+
const startToken = this._lexer.peek();
|
|
95
|
+
const themeIdNode = this.tryThemeId();
|
|
96
|
+
if (themeIdNode)
|
|
97
|
+
return themeIdNode;
|
|
98
|
+
const value = this.getNumber();
|
|
99
|
+
if (value === null)
|
|
100
|
+
return null;
|
|
101
|
+
// --- Get the unit
|
|
102
|
+
let unit = "";
|
|
103
|
+
const unitToken = this._lexer.peek(true);
|
|
104
|
+
if (unitToken.text === "%") {
|
|
105
|
+
unit = this._lexer.get(true).text;
|
|
106
|
+
}
|
|
107
|
+
else if (unitToken.type === tokens_1.StyleTokenType.Ws) {
|
|
108
|
+
this._lexer.get(true);
|
|
109
|
+
}
|
|
110
|
+
else if (unitToken.type !== tokens_1.StyleTokenType.Eof) {
|
|
111
|
+
this.reportError("S016", unitToken);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
// --- Done.
|
|
115
|
+
return this.createNode("Size", {
|
|
116
|
+
value,
|
|
117
|
+
unit,
|
|
118
|
+
}, startToken);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Parses a boolean value
|
|
122
|
+
*/
|
|
123
|
+
parseBoolean() {
|
|
124
|
+
const startToken = this._lexer.peek();
|
|
125
|
+
const themeIdNode = this.tryThemeId();
|
|
126
|
+
if (themeIdNode)
|
|
127
|
+
return themeIdNode;
|
|
128
|
+
if (startToken.type !== tokens_1.StyleTokenType.Boolean) {
|
|
129
|
+
this.reportError("S017", startToken);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
// --- Done.
|
|
133
|
+
this._lexer.get();
|
|
134
|
+
return this.createNode("Boolean", {
|
|
135
|
+
value: startToken.text === "true" || startToken.text === "yes" || startToken.text === "on",
|
|
136
|
+
}, startToken);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Parses an alignment value
|
|
140
|
+
*/
|
|
141
|
+
parseAlignment() {
|
|
142
|
+
const startToken = this._lexer.peek();
|
|
143
|
+
if (startToken.type !== tokens_1.StyleTokenType.Alignment) {
|
|
144
|
+
this.reportError("S003", startToken);
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
// --- Done.
|
|
148
|
+
this._lexer.get();
|
|
149
|
+
return this.createNode("Alignment", {
|
|
150
|
+
value: startToken.text,
|
|
151
|
+
}, startToken);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Parses a text alignment value
|
|
155
|
+
*/
|
|
156
|
+
parseTextAlign() {
|
|
157
|
+
const startToken = this._lexer.peek();
|
|
158
|
+
if (startToken.type !== tokens_1.StyleTokenType.Alignment && startToken.type !== tokens_1.StyleTokenType.TextAlignment) {
|
|
159
|
+
this.reportError("S003", startToken);
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
// --- Done.
|
|
163
|
+
this._lexer.get();
|
|
164
|
+
return this.createNode("TextAlign", {
|
|
165
|
+
value: startToken.text,
|
|
166
|
+
}, startToken);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Parses a user select value
|
|
170
|
+
*/
|
|
171
|
+
parseUserSelect() {
|
|
172
|
+
const startToken = this._lexer.peek();
|
|
173
|
+
if (startToken.type !== tokens_1.StyleTokenType.None &&
|
|
174
|
+
startToken.type !== tokens_1.StyleTokenType.Auto &&
|
|
175
|
+
startToken.type !== tokens_1.StyleTokenType.UserSelect) {
|
|
176
|
+
this.reportError("S020", startToken);
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
// --- Done.
|
|
180
|
+
this._lexer.get();
|
|
181
|
+
return this.createNode("UserSelect", {
|
|
182
|
+
value: startToken.text,
|
|
183
|
+
}, startToken);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Parses a text transform value
|
|
187
|
+
*/
|
|
188
|
+
parseTextTransform() {
|
|
189
|
+
const startToken = this._lexer.peek();
|
|
190
|
+
if (startToken.type !== tokens_1.StyleTokenType.None && startToken.type !== tokens_1.StyleTokenType.TextTransform) {
|
|
191
|
+
this.reportError("S021", startToken);
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
// --- Done.
|
|
195
|
+
this._lexer.get();
|
|
196
|
+
return this.createNode("TextTransform", {
|
|
197
|
+
value: startToken.text,
|
|
198
|
+
}, startToken);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Parses an orientation value
|
|
202
|
+
*/
|
|
203
|
+
parseOrientation() {
|
|
204
|
+
const startToken = this._lexer.peek();
|
|
205
|
+
if (startToken.type !== tokens_1.StyleTokenType.Orientation) {
|
|
206
|
+
this.reportError("S018", startToken);
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
// --- Done.
|
|
210
|
+
this._lexer.get();
|
|
211
|
+
return this.createNode("Orientation", {
|
|
212
|
+
value: startToken.text,
|
|
213
|
+
}, startToken);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Parses a cursor value
|
|
217
|
+
*/
|
|
218
|
+
parseCursor() {
|
|
219
|
+
const startToken = this._lexer.peek();
|
|
220
|
+
switch (startToken.type) {
|
|
221
|
+
case tokens_1.StyleTokenType.Auto:
|
|
222
|
+
case tokens_1.StyleTokenType.None:
|
|
223
|
+
case tokens_1.StyleTokenType.Default:
|
|
224
|
+
case tokens_1.StyleTokenType.Cursor:
|
|
225
|
+
this._lexer.get();
|
|
226
|
+
return this.createNode("Cursor", {
|
|
227
|
+
value: startToken.text,
|
|
228
|
+
}, startToken);
|
|
229
|
+
case tokens_1.StyleTokenType.UserSelect:
|
|
230
|
+
if (startToken.text === "text") {
|
|
231
|
+
this._lexer.get();
|
|
232
|
+
return this.createNode("Cursor", {
|
|
233
|
+
value: "text",
|
|
234
|
+
}, startToken);
|
|
235
|
+
}
|
|
236
|
+
this.reportError("S018", startToken);
|
|
237
|
+
return null;
|
|
238
|
+
default:
|
|
239
|
+
this.reportError("S018", startToken);
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Parses a direction value
|
|
245
|
+
*/
|
|
246
|
+
parseDirection() {
|
|
247
|
+
const startToken = this._lexer.peek();
|
|
248
|
+
const themeIdNode = this.tryThemeId();
|
|
249
|
+
if (themeIdNode)
|
|
250
|
+
return themeIdNode;
|
|
251
|
+
if (startToken.type !== tokens_1.StyleTokenType.Direction) {
|
|
252
|
+
this.reportError("S013", startToken);
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
// --- Done.
|
|
256
|
+
this._lexer.get();
|
|
257
|
+
return this.createNode("Direction", {
|
|
258
|
+
value: startToken.text,
|
|
259
|
+
}, startToken);
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Parses a fontFamily value
|
|
263
|
+
*/
|
|
264
|
+
parseFontFamily() {
|
|
265
|
+
const startToken = this._lexer.peek();
|
|
266
|
+
const themeIdNode = this.tryThemeId();
|
|
267
|
+
if (themeIdNode)
|
|
268
|
+
return themeIdNode;
|
|
269
|
+
let value = "";
|
|
270
|
+
let nextToken = startToken;
|
|
271
|
+
while (true) {
|
|
272
|
+
// --- Get font name token
|
|
273
|
+
if (nextToken.type === tokens_1.StyleTokenType.Eof)
|
|
274
|
+
break;
|
|
275
|
+
if (nextToken.type === tokens_1.StyleTokenType.FontFamily ||
|
|
276
|
+
nextToken.type === tokens_1.StyleTokenType.Identifier ||
|
|
277
|
+
nextToken.type === tokens_1.StyleTokenType.String) {
|
|
278
|
+
value += (value ? ", " : "") + nextToken.text;
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
this.reportError("S014", nextToken);
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
// --- Skip the parsed token
|
|
285
|
+
this._lexer.get();
|
|
286
|
+
// --- Check for separator comma
|
|
287
|
+
nextToken = this._lexer.peek();
|
|
288
|
+
if (nextToken.type === tokens_1.StyleTokenType.Comma) {
|
|
289
|
+
this._lexer.get();
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
nextToken = this._lexer.peek();
|
|
295
|
+
}
|
|
296
|
+
// --- Done.
|
|
297
|
+
return this.createNode("FontFamily", {
|
|
298
|
+
value,
|
|
299
|
+
}, startToken);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Parses a weight value
|
|
303
|
+
*/
|
|
304
|
+
parseFontWeight() {
|
|
305
|
+
const startToken = this._lexer.peek();
|
|
306
|
+
const themeIdNode = this.tryThemeId();
|
|
307
|
+
if (themeIdNode)
|
|
308
|
+
return themeIdNode;
|
|
309
|
+
if (startToken.type !== tokens_1.StyleTokenType.FontWeight && startToken.type !== tokens_1.StyleTokenType.Number) {
|
|
310
|
+
this.reportError("S015", startToken);
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
// --- Done.
|
|
314
|
+
this._lexer.get();
|
|
315
|
+
return this.createNode("FontWeight", {
|
|
316
|
+
value: startToken.text,
|
|
317
|
+
}, startToken);
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Parses a zIndex value
|
|
321
|
+
*/
|
|
322
|
+
parseZIndex() {
|
|
323
|
+
const startToken = this._lexer.peek();
|
|
324
|
+
const themeIdNode = this.tryThemeId();
|
|
325
|
+
if (themeIdNode)
|
|
326
|
+
return themeIdNode;
|
|
327
|
+
if (startToken.type !== tokens_1.StyleTokenType.Number) {
|
|
328
|
+
this.reportError("S001", startToken);
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
// --- Done.
|
|
332
|
+
this._lexer.get();
|
|
333
|
+
return this.createNode("ZIndex", {
|
|
334
|
+
value: startToken.text,
|
|
335
|
+
}, startToken);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Parses a scrolling value
|
|
339
|
+
*/
|
|
340
|
+
parseScrolling() {
|
|
341
|
+
const startToken = this._lexer.peek();
|
|
342
|
+
const themeIdNode = this.tryThemeId();
|
|
343
|
+
if (themeIdNode)
|
|
344
|
+
return themeIdNode;
|
|
345
|
+
if (startToken.type !== tokens_1.StyleTokenType.Scrolling) {
|
|
346
|
+
this.reportError("S012", startToken);
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
// --- Done.
|
|
350
|
+
this._lexer.get();
|
|
351
|
+
return this.createNode("Scrolling", {
|
|
352
|
+
value: startToken.text,
|
|
353
|
+
}, startToken);
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Parses a border style value with its unit
|
|
357
|
+
*/
|
|
358
|
+
parseBorderStyle() {
|
|
359
|
+
const startToken = this._lexer.peek();
|
|
360
|
+
if (startToken.type !== tokens_1.StyleTokenType.BorderStyle && startToken.type !== tokens_1.StyleTokenType.None) {
|
|
361
|
+
this.reportError("S004", startToken);
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
// --- Done.
|
|
365
|
+
this._lexer.get();
|
|
366
|
+
return this.createNode("BorderStyle", {
|
|
367
|
+
value: startToken.text,
|
|
368
|
+
}, startToken);
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Parses a border (size, style, color in arbitrary order)
|
|
372
|
+
*/
|
|
373
|
+
parseBorder() {
|
|
374
|
+
const startToken = this._lexer.peek();
|
|
375
|
+
const themeIdNode = this.tryThemeId();
|
|
376
|
+
let themeId1;
|
|
377
|
+
let maxStyleTokens = 3;
|
|
378
|
+
if (themeIdNode) {
|
|
379
|
+
if (this.testCompleted()) {
|
|
380
|
+
return themeIdNode;
|
|
381
|
+
}
|
|
382
|
+
maxStyleTokens = 2;
|
|
383
|
+
themeId1 = themeIdNode.themeId;
|
|
384
|
+
}
|
|
385
|
+
let sizeFound = null;
|
|
386
|
+
let styleFound = null;
|
|
387
|
+
let colorFound = null;
|
|
388
|
+
let themeId2;
|
|
389
|
+
let themeId3;
|
|
390
|
+
for (let i = 0; i < maxStyleTokens; i++) {
|
|
391
|
+
const nextToken = this._lexer.peek();
|
|
392
|
+
if (isThemeId(nextToken)) {
|
|
393
|
+
if (!themeId2) {
|
|
394
|
+
themeId2 = this.parseThemeId();
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
themeId3 = this.parseThemeId();
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
switch (nextToken.type) {
|
|
402
|
+
case tokens_1.StyleTokenType.Number:
|
|
403
|
+
if (sizeFound) {
|
|
404
|
+
this.reportError("S016", nextToken);
|
|
405
|
+
return null;
|
|
406
|
+
}
|
|
407
|
+
sizeFound = this.parseSize();
|
|
408
|
+
break;
|
|
409
|
+
case tokens_1.StyleTokenType.BorderStyle:
|
|
410
|
+
if (styleFound) {
|
|
411
|
+
this.reportError("S016", nextToken);
|
|
412
|
+
return null;
|
|
413
|
+
}
|
|
414
|
+
styleFound = this.parseBorderStyle();
|
|
415
|
+
break;
|
|
416
|
+
case tokens_1.StyleTokenType.ColorName:
|
|
417
|
+
case tokens_1.StyleTokenType.ColorFunc:
|
|
418
|
+
case tokens_1.StyleTokenType.HexaColor:
|
|
419
|
+
if (colorFound) {
|
|
420
|
+
this.reportError("S016", nextToken);
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
colorFound = this.parseColor();
|
|
424
|
+
break;
|
|
425
|
+
default:
|
|
426
|
+
this.reportError("S016", nextToken);
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
const spToken = this._lexer.peek(true);
|
|
431
|
+
if (spToken.type === tokens_1.StyleTokenType.Eof)
|
|
432
|
+
break;
|
|
433
|
+
if (spToken.type === tokens_1.StyleTokenType.Ws) {
|
|
434
|
+
this._lexer.get(true);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return this.createNode("Border", {
|
|
438
|
+
themeId1,
|
|
439
|
+
themeId2,
|
|
440
|
+
themeId3,
|
|
441
|
+
widthValue: sizeFound === null || sizeFound === void 0 ? void 0 : sizeFound.value,
|
|
442
|
+
widthUnit: sizeFound === null || sizeFound === void 0 ? void 0 : sizeFound.unit,
|
|
443
|
+
color: colorFound === null || colorFound === void 0 ? void 0 : colorFound.value,
|
|
444
|
+
styleValue: styleFound === null || styleFound === void 0 ? void 0 : styleFound.value,
|
|
445
|
+
}, startToken);
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Parses a color value
|
|
449
|
+
*/
|
|
450
|
+
parseColor() {
|
|
451
|
+
const startToken = this._lexer.peek();
|
|
452
|
+
const themeIdNode = this.tryThemeId();
|
|
453
|
+
if (themeIdNode)
|
|
454
|
+
return themeIdNode;
|
|
455
|
+
const parser = this;
|
|
456
|
+
switch (startToken.type) {
|
|
457
|
+
case tokens_1.StyleTokenType.ColorName:
|
|
458
|
+
this._lexer.get();
|
|
459
|
+
return this.createNode("Color", {
|
|
460
|
+
value: startToken.text.toLowerCase(),
|
|
461
|
+
}, startToken);
|
|
462
|
+
case tokens_1.StyleTokenType.HexaColor:
|
|
463
|
+
this._lexer.get();
|
|
464
|
+
return this.createNode("Color", {
|
|
465
|
+
value: startToken.text,
|
|
466
|
+
}, startToken);
|
|
467
|
+
case tokens_1.StyleTokenType.ColorFunc:
|
|
468
|
+
let success = false;
|
|
469
|
+
switch (startToken.text) {
|
|
470
|
+
case "rgb":
|
|
471
|
+
success = parseColorParameters(["V%", "V%", "V%"]);
|
|
472
|
+
break;
|
|
473
|
+
case "rgba":
|
|
474
|
+
success = parseColorParameters(["V%", "V%", "V%", "alpha"]);
|
|
475
|
+
break;
|
|
476
|
+
case "hsl":
|
|
477
|
+
success = parseColorParameters(["angle", "%", "%"]);
|
|
478
|
+
break;
|
|
479
|
+
case "hsla":
|
|
480
|
+
success = parseColorParameters(["angle", "%", "%", "alpha"]);
|
|
481
|
+
break;
|
|
482
|
+
default:
|
|
483
|
+
this.reportError("S006", startToken, startToken.text);
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
if (success) {
|
|
487
|
+
return {
|
|
488
|
+
type: "Color",
|
|
489
|
+
startPosition: startToken.start,
|
|
490
|
+
endPosition: this._lexer.peek().start,
|
|
491
|
+
value: this.getSource(startToken, this._lexer.peek()),
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
return null;
|
|
495
|
+
default:
|
|
496
|
+
this.reportError("S005", startToken);
|
|
497
|
+
return null;
|
|
498
|
+
}
|
|
499
|
+
function parseColorParameters(pars) {
|
|
500
|
+
// --- Skip the color function name token
|
|
501
|
+
parser._lexer.get();
|
|
502
|
+
// --- Expect "("
|
|
503
|
+
parser.expectToken(tokens_1.StyleTokenType.LParent, "S007");
|
|
504
|
+
// --- Iterate through pars
|
|
505
|
+
for (let i = 0; i < pars.length; i++) {
|
|
506
|
+
// --- Get the parameter value
|
|
507
|
+
const value = parser.getNumber();
|
|
508
|
+
if (value === null)
|
|
509
|
+
return false;
|
|
510
|
+
// --- Get optional parameter unit
|
|
511
|
+
const unit = parser._lexer.peek(true);
|
|
512
|
+
// --- Process the value & unit
|
|
513
|
+
switch (pars[i]) {
|
|
514
|
+
// 0-255 or 0%-100%
|
|
515
|
+
case "V%":
|
|
516
|
+
if (unit.type === tokens_1.StyleTokenType.Percentage) {
|
|
517
|
+
if (value < 0 || value > 100) {
|
|
518
|
+
parser.reportError("S008");
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
parser._lexer.get();
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
if (value < 0 || value > 255) {
|
|
525
|
+
parser.reportError("S009");
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
break;
|
|
530
|
+
// 0%-100%
|
|
531
|
+
case "%":
|
|
532
|
+
if (unit.type !== tokens_1.StyleTokenType.Percentage || value < 0 || value > 100) {
|
|
533
|
+
parser.reportError("S008");
|
|
534
|
+
return false;
|
|
535
|
+
}
|
|
536
|
+
parser._lexer.get();
|
|
537
|
+
break;
|
|
538
|
+
case "angle":
|
|
539
|
+
if (unit.type === tokens_1.StyleTokenType.Angle) {
|
|
540
|
+
parser._lexer.get();
|
|
541
|
+
}
|
|
542
|
+
break;
|
|
543
|
+
// alpha with units
|
|
544
|
+
case "alpha":
|
|
545
|
+
if (unit.type === tokens_1.StyleTokenType.Percentage) {
|
|
546
|
+
if (value < 0 || value > 100) {
|
|
547
|
+
parser.reportError("S008");
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
parser._lexer.get();
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
if (value < 0 || value > 1) {
|
|
554
|
+
parser.reportError("S011");
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
// --- No separator expected after the last parameter
|
|
561
|
+
if (i === pars.length - 1)
|
|
562
|
+
continue;
|
|
563
|
+
// --- Process the separator
|
|
564
|
+
let sepToken = parser._lexer.peek(true);
|
|
565
|
+
if (sepToken.type === tokens_1.StyleTokenType.Ws) {
|
|
566
|
+
parser._lexer.get();
|
|
567
|
+
sepToken = parser._lexer.peek(true);
|
|
568
|
+
if (sepToken.type === tokens_1.StyleTokenType.Comma) {
|
|
569
|
+
parser._lexer.get();
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
parser.expectToken(tokens_1.StyleTokenType.Comma);
|
|
574
|
+
}
|
|
575
|
+
sepToken = parser._lexer.peek();
|
|
576
|
+
if (sepToken.type === tokens_1.StyleTokenType.Ws) {
|
|
577
|
+
parser._lexer.get();
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
// --- Process the optional separator
|
|
581
|
+
let aSepToken = parser._lexer.peek();
|
|
582
|
+
if (aSepToken.type === tokens_1.StyleTokenType.Ws) {
|
|
583
|
+
parser._lexer.get();
|
|
584
|
+
}
|
|
585
|
+
// --- Expect ")"
|
|
586
|
+
parser.expectToken(tokens_1.StyleTokenType.RParent, "S010");
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Parses a text decoration value
|
|
592
|
+
*/
|
|
593
|
+
parseTextDecoration() {
|
|
594
|
+
const startToken = this._lexer.peek();
|
|
595
|
+
if (startToken.type === tokens_1.StyleTokenType.None) {
|
|
596
|
+
this._lexer.get();
|
|
597
|
+
return this.createNode("TextDecoration", {
|
|
598
|
+
none: true,
|
|
599
|
+
}, startToken);
|
|
600
|
+
}
|
|
601
|
+
const themeIdNode = this.tryThemeId();
|
|
602
|
+
let themeId1;
|
|
603
|
+
let maxStyleTokens = 3;
|
|
604
|
+
if (themeIdNode) {
|
|
605
|
+
if (this.testCompleted()) {
|
|
606
|
+
return themeIdNode;
|
|
607
|
+
}
|
|
608
|
+
maxStyleTokens = 2;
|
|
609
|
+
themeId1 = themeIdNode.themeId;
|
|
610
|
+
}
|
|
611
|
+
const acceptedStyles = ["solid", "double", "dotted", "dashed", "wavy"];
|
|
612
|
+
let lineFound;
|
|
613
|
+
let styleFound;
|
|
614
|
+
let colorFound = null;
|
|
615
|
+
let themeId2;
|
|
616
|
+
let themeId3;
|
|
617
|
+
for (let i = 0; i < maxStyleTokens; i++) {
|
|
618
|
+
const nextToken = this._lexer.peek();
|
|
619
|
+
if (isThemeId(nextToken)) {
|
|
620
|
+
if (!themeId2) {
|
|
621
|
+
themeId2 = this.parseThemeId();
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
themeId3 = this.parseThemeId();
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
else {
|
|
628
|
+
if (acceptedStyles.indexOf(nextToken.text) >= 0) {
|
|
629
|
+
styleFound = nextToken.text;
|
|
630
|
+
this._lexer.get();
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
switch (nextToken.type) {
|
|
634
|
+
case tokens_1.StyleTokenType.DecorationLine:
|
|
635
|
+
if (lineFound) {
|
|
636
|
+
this.reportError("S016", nextToken);
|
|
637
|
+
return null;
|
|
638
|
+
}
|
|
639
|
+
this._lexer.get();
|
|
640
|
+
lineFound = nextToken.text;
|
|
641
|
+
break;
|
|
642
|
+
case tokens_1.StyleTokenType.ColorName:
|
|
643
|
+
case tokens_1.StyleTokenType.ColorFunc:
|
|
644
|
+
case tokens_1.StyleTokenType.HexaColor:
|
|
645
|
+
if (colorFound) {
|
|
646
|
+
this.reportError("S016", nextToken);
|
|
647
|
+
return null;
|
|
648
|
+
}
|
|
649
|
+
colorFound = this.parseColor();
|
|
650
|
+
break;
|
|
651
|
+
default:
|
|
652
|
+
this.reportError("S016", nextToken);
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const spToken = this._lexer.peek(true);
|
|
658
|
+
if (spToken.type === tokens_1.StyleTokenType.Eof)
|
|
659
|
+
break;
|
|
660
|
+
if (spToken.type === tokens_1.StyleTokenType.Ws) {
|
|
661
|
+
this._lexer.get(true);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return this.createNode("TextDecoration", {
|
|
665
|
+
themeId1,
|
|
666
|
+
themeId2,
|
|
667
|
+
themeId3,
|
|
668
|
+
color: colorFound === null || colorFound === void 0 ? void 0 : colorFound.value,
|
|
669
|
+
style: styleFound,
|
|
670
|
+
line: lineFound,
|
|
671
|
+
}, startToken);
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Parses a radius value
|
|
675
|
+
*/
|
|
676
|
+
parseRadius() {
|
|
677
|
+
var _a, _b, _c, _d;
|
|
678
|
+
const values = [];
|
|
679
|
+
const themeIds = [];
|
|
680
|
+
const startToken = this._lexer.peek();
|
|
681
|
+
let count = 0;
|
|
682
|
+
while (count < 2) {
|
|
683
|
+
// --- Resolve to theme id or size
|
|
684
|
+
const themeIdNode = this.tryThemeId();
|
|
685
|
+
if (themeIdNode) {
|
|
686
|
+
themeIds[count] = themeIdNode.themeId;
|
|
687
|
+
if (this._lexer.peek().type === tokens_1.StyleTokenType.Eof) {
|
|
688
|
+
// --- No more token
|
|
689
|
+
count = 5;
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
// --- Skip trailing spaces
|
|
693
|
+
while (this._lexer.peek(true).type === tokens_1.StyleTokenType.Ws) {
|
|
694
|
+
this._lexer.get(true);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
let size = this.parseSize();
|
|
700
|
+
if (!size) {
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
values[count] = size;
|
|
704
|
+
// --- Search for the end/whitespace
|
|
705
|
+
let wsCount = 0;
|
|
706
|
+
while (true) {
|
|
707
|
+
let nextToken = this._lexer.peek(true);
|
|
708
|
+
if (nextToken.type === tokens_1.StyleTokenType.Eof) {
|
|
709
|
+
// --- No more token
|
|
710
|
+
count = 5;
|
|
711
|
+
wsCount = 1;
|
|
712
|
+
break;
|
|
713
|
+
}
|
|
714
|
+
if (nextToken.type === tokens_1.StyleTokenType.Ws) {
|
|
715
|
+
// Skip the whitespace
|
|
716
|
+
this._lexer.get(true);
|
|
717
|
+
wsCount++;
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
// --- We need a separator
|
|
724
|
+
if (!wsCount) {
|
|
725
|
+
this.reportError("S016");
|
|
726
|
+
return null;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
// --- Next item
|
|
730
|
+
count++;
|
|
731
|
+
}
|
|
732
|
+
return this.createNode("Radius", {
|
|
733
|
+
themeId1: themeIds[0],
|
|
734
|
+
themeId2: themeIds[1],
|
|
735
|
+
value1: (_a = values[0]) === null || _a === void 0 ? void 0 : _a.value,
|
|
736
|
+
unit1: (_b = values[0]) === null || _b === void 0 ? void 0 : _b.unit,
|
|
737
|
+
value2: (_c = values[1]) === null || _c === void 0 ? void 0 : _c.value,
|
|
738
|
+
unit2: (_d = values[1]) === null || _d === void 0 ? void 0 : _d.unit,
|
|
739
|
+
}, startToken);
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Parses a shadow value
|
|
743
|
+
*/
|
|
744
|
+
parseShadow() {
|
|
745
|
+
const startToken = this._lexer.peek();
|
|
746
|
+
const themeIdNode = this.tryThemeId();
|
|
747
|
+
if (themeIdNode)
|
|
748
|
+
return themeIdNode;
|
|
749
|
+
const segments = [];
|
|
750
|
+
let nextToken = null;
|
|
751
|
+
// --- Parse a single segment
|
|
752
|
+
while (true) {
|
|
753
|
+
let inset = null;
|
|
754
|
+
let sizeX = null;
|
|
755
|
+
let sizeY = null;
|
|
756
|
+
let blurRadius = null;
|
|
757
|
+
let spreadRadius = null;
|
|
758
|
+
let color = null;
|
|
759
|
+
nextToken = this._lexer.peek();
|
|
760
|
+
if (nextToken.text === "inset") {
|
|
761
|
+
inset = true;
|
|
762
|
+
this._lexer.get();
|
|
763
|
+
nextToken = this._lexer.peek();
|
|
764
|
+
}
|
|
765
|
+
// --- Offset values
|
|
766
|
+
sizeX = this.parseSize();
|
|
767
|
+
if (!sizeX) {
|
|
768
|
+
return null;
|
|
769
|
+
}
|
|
770
|
+
nextToken = this._lexer.peek(true);
|
|
771
|
+
if (nextToken.type !== tokens_1.StyleTokenType.Ws) {
|
|
772
|
+
this.reportError("S016", nextToken);
|
|
773
|
+
}
|
|
774
|
+
this._lexer.get();
|
|
775
|
+
sizeY = this.parseSize();
|
|
776
|
+
if (!sizeY) {
|
|
777
|
+
return null;
|
|
778
|
+
}
|
|
779
|
+
nextToken = this._lexer.peek(true);
|
|
780
|
+
if (nextToken.type === tokens_1.StyleTokenType.Ws) {
|
|
781
|
+
this._lexer.get();
|
|
782
|
+
nextToken = this._lexer.peek();
|
|
783
|
+
if (nextToken.type === tokens_1.StyleTokenType.Number) {
|
|
784
|
+
// --- Blur radius
|
|
785
|
+
blurRadius = this.parseSize();
|
|
786
|
+
nextToken = this._lexer.peek(true);
|
|
787
|
+
}
|
|
788
|
+
if (nextToken.type === tokens_1.StyleTokenType.Ws) {
|
|
789
|
+
this._lexer.get();
|
|
790
|
+
nextToken = this._lexer.peek();
|
|
791
|
+
if (nextToken.type === tokens_1.StyleTokenType.Number) {
|
|
792
|
+
// --- Spread radius
|
|
793
|
+
spreadRadius = this.parseSize();
|
|
794
|
+
nextToken = this._lexer.peek(true);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
// --- Check for color
|
|
799
|
+
if (nextToken.type === tokens_1.StyleTokenType.Ws) {
|
|
800
|
+
nextToken = this._lexer.get();
|
|
801
|
+
}
|
|
802
|
+
if (nextToken.type !== tokens_1.StyleTokenType.Eof && nextToken.type !== tokens_1.StyleTokenType.Comma) {
|
|
803
|
+
color = this.parseColor();
|
|
804
|
+
}
|
|
805
|
+
// --- Create segment
|
|
806
|
+
segments.push({
|
|
807
|
+
inset: inset !== null && inset !== void 0 ? inset : undefined,
|
|
808
|
+
offsetXValue: sizeX.value,
|
|
809
|
+
offsetXUnit: sizeX.unit,
|
|
810
|
+
offsetYValue: sizeY.value,
|
|
811
|
+
offsetYUnit: sizeY.unit,
|
|
812
|
+
blurRadiusValue: blurRadius === null || blurRadius === void 0 ? void 0 : blurRadius.value,
|
|
813
|
+
blurRadiusUnit: blurRadius === null || blurRadius === void 0 ? void 0 : blurRadius.unit,
|
|
814
|
+
spreadRadiusValue: spreadRadius === null || spreadRadius === void 0 ? void 0 : spreadRadius.value,
|
|
815
|
+
spreadRadiusUnit: spreadRadius === null || spreadRadius === void 0 ? void 0 : spreadRadius.unit,
|
|
816
|
+
color: color === null || color === void 0 ? void 0 : color.value,
|
|
817
|
+
});
|
|
818
|
+
// --- Check for next segment
|
|
819
|
+
const sp = this._lexer.peek(true);
|
|
820
|
+
if (sp.type === tokens_1.StyleTokenType.Comma) {
|
|
821
|
+
// --- There is a next shadow segment
|
|
822
|
+
this._lexer.get();
|
|
823
|
+
}
|
|
824
|
+
else {
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
return this.createNode("Shadow", {
|
|
829
|
+
segments,
|
|
830
|
+
}, startToken);
|
|
831
|
+
}
|
|
832
|
+
getNumber() {
|
|
833
|
+
const token = this._lexer.get();
|
|
834
|
+
if (token.type === tokens_1.StyleTokenType.Number) {
|
|
835
|
+
return parseFloat(token.text);
|
|
836
|
+
}
|
|
837
|
+
this.reportError("S001", token);
|
|
838
|
+
return null;
|
|
839
|
+
}
|
|
840
|
+
expectToken(type, errorCode, allowEof) {
|
|
841
|
+
const next = this._lexer.peek();
|
|
842
|
+
if (next.type === type || (allowEof && next.type === tokens_1.StyleTokenType.Eof)) {
|
|
843
|
+
// --- Skip the expected token
|
|
844
|
+
return this._lexer.get();
|
|
845
|
+
}
|
|
846
|
+
this.reportError(errorCode !== null && errorCode !== void 0 ? errorCode : "S007", next, next.text);
|
|
847
|
+
return null;
|
|
848
|
+
}
|
|
849
|
+
/**
|
|
850
|
+
* Reports the specified error
|
|
851
|
+
* @param errorCode Error code
|
|
852
|
+
* @param token Token that represents the error's position
|
|
853
|
+
* @param options Error message options
|
|
854
|
+
*/
|
|
855
|
+
reportError(errorCode, token, ...options) {
|
|
856
|
+
var _a;
|
|
857
|
+
let errorText = (_a = errors_1.styleErrorMessages[errorCode]) !== null && _a !== void 0 ? _a : "Unknown error";
|
|
858
|
+
if (options) {
|
|
859
|
+
options.forEach((o, idx) => (errorText = replace(errorText, `{${idx}}`, options[idx].toString())));
|
|
860
|
+
}
|
|
861
|
+
if (!token) {
|
|
862
|
+
token = this._lexer.peek(true);
|
|
863
|
+
}
|
|
864
|
+
this._parseErrors.push({
|
|
865
|
+
code: errorCode,
|
|
866
|
+
text: errorText,
|
|
867
|
+
position: token.start,
|
|
868
|
+
});
|
|
869
|
+
throw new errors_1.StyleParserError(errorText, errorCode);
|
|
870
|
+
function replace(input, placeholder, replacement) {
|
|
871
|
+
do {
|
|
872
|
+
input = input.replace(placeholder, replacement);
|
|
873
|
+
} while (input.includes(placeholder));
|
|
874
|
+
return input;
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Creates an expression node
|
|
879
|
+
* @param type Expression type
|
|
880
|
+
* @param stump Stump properties
|
|
881
|
+
* @param startToken The token that starts the expression
|
|
882
|
+
* @param endToken The token that ends the expression
|
|
883
|
+
* @param source Expression source code to store to the node
|
|
884
|
+
*/
|
|
885
|
+
createNode(type, stump, startToken, endToken, source) {
|
|
886
|
+
if (!endToken) {
|
|
887
|
+
endToken = this._lexer.peek(true);
|
|
888
|
+
}
|
|
889
|
+
const startPosition = startToken.start;
|
|
890
|
+
const endPosition = endToken.start;
|
|
891
|
+
return Object.assign({}, stump, {
|
|
892
|
+
type,
|
|
893
|
+
startPosition,
|
|
894
|
+
endPosition,
|
|
895
|
+
source: source !== null && source !== void 0 ? source : this.getSource(startToken, endToken),
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Gets the source code for the specified token range
|
|
900
|
+
* @param start Start token
|
|
901
|
+
* @param end Optional end token
|
|
902
|
+
* @returns The source code for the token range
|
|
903
|
+
*/
|
|
904
|
+
getSource(start, end) {
|
|
905
|
+
if (!end)
|
|
906
|
+
end = this._lexer.peek();
|
|
907
|
+
return this.source.substring(start.start, end.start);
|
|
908
|
+
}
|
|
909
|
+
tryThemeId() {
|
|
910
|
+
const token = this._lexer.peek();
|
|
911
|
+
if (isThemeId(token)) {
|
|
912
|
+
return this.createNode("Boolean", {
|
|
913
|
+
themeId: this.parseThemeId(),
|
|
914
|
+
}, token);
|
|
915
|
+
}
|
|
916
|
+
return null;
|
|
917
|
+
}
|
|
918
|
+
parseThemeId() {
|
|
919
|
+
const startToken = this._lexer.peek();
|
|
920
|
+
this._lexer.get();
|
|
921
|
+
return {
|
|
922
|
+
id: startToken.text,
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Parses a size value with its unit
|
|
927
|
+
*/
|
|
928
|
+
parseSizeLike(defUnit = "") {
|
|
929
|
+
const startToken = this._lexer.peek();
|
|
930
|
+
const themeIdNode = this.tryThemeId();
|
|
931
|
+
if (themeIdNode)
|
|
932
|
+
return themeIdNode;
|
|
933
|
+
if (startToken.type === tokens_1.StyleTokenType.Star) {
|
|
934
|
+
this._lexer.get();
|
|
935
|
+
const nextToken = this._lexer.peek(true);
|
|
936
|
+
if (nextToken.type === tokens_1.StyleTokenType.Ws) {
|
|
937
|
+
this._lexer.get(true);
|
|
938
|
+
}
|
|
939
|
+
else if (nextToken.type !== tokens_1.StyleTokenType.Eof) {
|
|
940
|
+
this.reportError("S016", nextToken);
|
|
941
|
+
return null;
|
|
942
|
+
}
|
|
943
|
+
// --- Done with "*"
|
|
944
|
+
return this.createNode("Size", {
|
|
945
|
+
value: 1,
|
|
946
|
+
unit: "*",
|
|
947
|
+
}, startToken);
|
|
948
|
+
}
|
|
949
|
+
const value = this.getNumber();
|
|
950
|
+
if (value === null)
|
|
951
|
+
return null;
|
|
952
|
+
// --- Get the unit
|
|
953
|
+
let unit = "";
|
|
954
|
+
const unitToken = this._lexer.peek(true);
|
|
955
|
+
if (unitToken.type === tokens_1.StyleTokenType.SizeUnit ||
|
|
956
|
+
unitToken.type === tokens_1.StyleTokenType.Star ||
|
|
957
|
+
unitToken.type === tokens_1.StyleTokenType.Percentage) {
|
|
958
|
+
unit = this._lexer.get(true).text;
|
|
959
|
+
}
|
|
960
|
+
else if (unitToken.type === tokens_1.StyleTokenType.Ws) {
|
|
961
|
+
this._lexer.get(true);
|
|
962
|
+
}
|
|
963
|
+
else if (unitToken.type !== tokens_1.StyleTokenType.Eof) {
|
|
964
|
+
this.reportError("S016", unitToken);
|
|
965
|
+
return null;
|
|
966
|
+
}
|
|
967
|
+
// --- Done.
|
|
968
|
+
return this.createNode("Size", {
|
|
969
|
+
value,
|
|
970
|
+
unit: unit ? unit : value ? defUnit : "",
|
|
971
|
+
}, startToken);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
exports.StyleParser = StyleParser;
|
|
975
|
+
/**
|
|
976
|
+
* Tests if the specified token is a theme identifier
|
|
977
|
+
* @param value Token to test
|
|
978
|
+
*/
|
|
979
|
+
function isThemeId(value) {
|
|
980
|
+
return value.type === tokens_1.StyleTokenType.Identifier && value.text.charAt(0) === "$";
|
|
981
|
+
}
|
|
982
|
+
/**
|
|
983
|
+
* Converts the specified themeID to a CSS var string
|
|
984
|
+
* @param c segment to convert
|
|
985
|
+
*/
|
|
986
|
+
function toCssVar(c) {
|
|
987
|
+
if (typeof c === "string") {
|
|
988
|
+
return `var(--${exports.THEME_VAR_PREFIX}-${c.substring(1)})`;
|
|
989
|
+
}
|
|
990
|
+
if (c.defaultValue && c.defaultValue.length > 0) {
|
|
991
|
+
let defaultValueString = "";
|
|
992
|
+
for (const segment of c.defaultValue) {
|
|
993
|
+
defaultValueString += typeof segment === "string" ? segment : toCssVar(segment);
|
|
994
|
+
}
|
|
995
|
+
return `var(--${exports.THEME_VAR_PREFIX}-${c.id.substring(1)}, ${defaultValueString})`;
|
|
996
|
+
}
|
|
997
|
+
else {
|
|
998
|
+
return `var(--${exports.THEME_VAR_PREFIX}-${c.id.substring(1)})`;
|
|
999
|
+
}
|
|
1000
|
+
}
|