From 855381a4869cc07ae4ffdfec45d14451fe8c449b Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 28 Jan 2021 06:20:15 -0800 Subject: [PATCH] feat(preprocess): add optimizeCarbonImports preprocessor (#499) --- .travis.yml | 2 +- README.md | 73 ++- package.json | 12 +- preprocess/api.json | 482 ++++++++++++++++++ preprocess/index.js | 5 + preprocess/optimize-carbon-imports.js | 97 ++++ scripts/build-api.js | 20 + tests/preprocess/index.js | 1 + .../optimize-carbon-imports.test.js | 139 +++++ 9 files changed, 825 insertions(+), 6 deletions(-) create mode 100644 preprocess/api.json create mode 100644 preprocess/index.js create mode 100644 preprocess/optimize-carbon-imports.js create mode 100644 scripts/build-api.js create mode 100644 tests/preprocess/index.js create mode 100644 tests/preprocess/optimize-carbon-imports.test.js diff --git a/.travis.yml b/.travis.yml index 0f44cad7..bad68449 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,5 @@ language: node_js node_js: 12 cache: yarn script: - - yarn check-types - yarn prepack + - yarn test diff --git a/README.md b/README.md index eebdba1a..3fdfcafc 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,78 @@ Using JavaScript: ``` -### TypeScript support +## Preprocessors + +### optimizeCarbonImports + +`optimizeCarbonImports` is a Svelte preprocessor that optimizes base imports inside the `script` block of a Svelte file from the following libraries: + +- carbon-components-svelte +- carbon-icons-svelte +- carbon-pictograms-svelte + +The preprocessor rewrites base imports to directly import the source Svelte file. This may lead to faster complile times **during development**. + +Example: + +**Before** + +```js +import { Button, Header } from "carbon-components-svelte"; +import { Notification20 } from "carbon-icons-svelte"; +import { Airplane } from "carbon-pictograms-svelte"; +``` + +**After** + +```js +import Button from "carbon-components-svelte/Button/Button.svelte"; +import Header from "carbon-components-svelte/UIShell/GlobalHeader/Header.svelte"; +import Notification20 from "carbon-icons-svelte/lib/Notification20/Notification20.svelte"; +import Airplane from "carbon-pictograms-svelte/lib/Airplane/Airplane.svelte"; +``` + +#### svelte.config.js + +```js +// svelte.config.js +const { + optimizeCarbonImports, +} = require("carbon-components-svelte/preprocess"); + +module.exports = { + preprocess: [optimizeCarbonImports()], +}; +``` + +#### svelte-loader + +```js +// webpack.config.js +const { + optimizeCarbonImports, +} = require("carbon-components-svelte/preprocess"); + +module.exports = { + // ... + module: { + rules: [ + { + test: /\.svelte$/, + use: { + loader: "svelte-loader", + options: { + hotReload: true, + preprocess: [optimizeCarbonImports()], + }, + }, + }, + ], + }, +}; +``` + +## TypeScript support [TypeScript definitions](types) are generated by [sveld](https://github.com/IBM/sveld). diff --git a/package.json b/package.json index 1f122ea1..b50569b5 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,15 @@ "types": "./types/index.d.ts", "sideEffects": false, "scripts": { - "check-types": "svelte-check --workspace tests", - "publish-examples": "node scripts/publish-examples", + "test": "run-p test:*", + "test:types": "svelte-check --workspace tests", + "test:preprocess": "node tests/preprocess", "build:css": "node scripts/build-css", + "build:api": "node scripts/build-api", "build:lib": "rollup -c", "prepack": "run-p build:*", - "format": "prettier --write './**/*.{svelte,js,md}'" + "format": "prettier --write './**/*.{svelte,js,md}'", + "publish-examples": "node scripts/publish-examples" }, "dependencies": { "carbon-icons-svelte": "^10.21.0", @@ -75,6 +78,7 @@ "lib", "src", "types", - "css" + "css", + "preprocess" ] } diff --git a/preprocess/api.json b/preprocess/api.json new file mode 100644 index 00000000..4498490e --- /dev/null +++ b/preprocess/api.json @@ -0,0 +1,482 @@ +{ + "version": "0.26.0", + "components": { + "Accordion": { + "path": "carbon-components-svelte/src/Accordion/Accordion.svelte" + }, + "AccordionItem": { + "path": "carbon-components-svelte/src/Accordion/AccordionItem.svelte" + }, + "AccordionSkeleton": { + "path": "carbon-components-svelte/src/Accordion/AccordionSkeleton.svelte" + }, + "AspectRatio": { + "path": "carbon-components-svelte/src/AspectRatio/AspectRatio.svelte" + }, + "Breadcrumb": { + "path": "carbon-components-svelte/src/Breadcrumb/Breadcrumb.svelte" + }, + "BreadcrumbItem": { + "path": "carbon-components-svelte/src/Breadcrumb/BreadcrumbItem.svelte" + }, + "BreadcrumbSkeleton": { + "path": "carbon-components-svelte/src/Breadcrumb/BreadcrumbSkeleton.svelte" + }, + "Button": { + "path": "carbon-components-svelte/src/Button/Button.svelte" + }, + "ButtonSet": { + "path": "carbon-components-svelte/src/Button/ButtonSet.svelte" + }, + "ButtonSkeleton": { + "path": "carbon-components-svelte/src/Button/ButtonSkeleton.svelte" + }, + "Checkbox": { + "path": "carbon-components-svelte/src/Checkbox/Checkbox.svelte" + }, + "CheckboxSkeleton": { + "path": "carbon-components-svelte/src/Checkbox/CheckboxSkeleton.svelte" + }, + "InlineCheckbox": { + "path": "carbon-components-svelte/src/Checkbox/InlineCheckbox.svelte" + }, + "CodeSnippet": { + "path": "carbon-components-svelte/src/CodeSnippet/CodeSnippet.svelte" + }, + "CodeSnippetSkeleton": { + "path": "carbon-components-svelte/src/CodeSnippet/CodeSnippetSkeleton.svelte" + }, + "ComboBox": { + "path": "carbon-components-svelte/src/ComboBox/ComboBox.svelte" + }, + "ComposedModal": { + "path": "carbon-components-svelte/src/ComposedModal/ComposedModal.svelte" + }, + "ModalBody": { + "path": "carbon-components-svelte/src/ComposedModal/ModalBody.svelte" + }, + "ModalFooter": { + "path": "carbon-components-svelte/src/ComposedModal/ModalFooter.svelte" + }, + "ModalHeader": { + "path": "carbon-components-svelte/src/ComposedModal/ModalHeader.svelte" + }, + "ContentSwitcher": { + "path": "carbon-components-svelte/src/ContentSwitcher/ContentSwitcher.svelte" + }, + "Switch": { + "path": "carbon-components-svelte/src/ContentSwitcher/Switch.svelte" + }, + "Copy": { + "path": "carbon-components-svelte/src/Copy/Copy.svelte" + }, + "CopyButton": { + "path": "carbon-components-svelte/src/CopyButton/CopyButton.svelte" + }, + "DataTable": { + "path": "carbon-components-svelte/src/DataTable/DataTable.svelte" + }, + "DataTableSkeleton": { + "path": "carbon-components-svelte/src/DataTable/DataTableSkeleton.svelte" + }, + "Table": { + "path": "carbon-components-svelte/src/DataTable/Table.svelte" + }, + "TableBody": { + "path": "carbon-components-svelte/src/DataTable/TableBody.svelte" + }, + "TableCell": { + "path": "carbon-components-svelte/src/DataTable/TableCell.svelte" + }, + "TableContainer": { + "path": "carbon-components-svelte/src/DataTable/TableContainer.svelte" + }, + "TableHead": { + "path": "carbon-components-svelte/src/DataTable/TableHead.svelte" + }, + "TableHeader": { + "path": "carbon-components-svelte/src/DataTable/TableHeader.svelte" + }, + "TableRow": { + "path": "carbon-components-svelte/src/DataTable/TableRow.svelte" + }, + "Toolbar": { + "path": "carbon-components-svelte/src/DataTable/Toolbar.svelte" + }, + "ToolbarBatchActions": { + "path": "carbon-components-svelte/src/DataTable/ToolbarBatchActions.svelte" + }, + "ToolbarContent": { + "path": "carbon-components-svelte/src/DataTable/ToolbarContent.svelte" + }, + "ToolbarMenu": { + "path": "carbon-components-svelte/src/DataTable/ToolbarMenu.svelte" + }, + "ToolbarMenuItem": { + "path": "carbon-components-svelte/src/DataTable/ToolbarMenuItem.svelte" + }, + "ToolbarSearch": { + "path": "carbon-components-svelte/src/DataTable/ToolbarSearch.svelte" + }, + "DatePicker": { + "path": "carbon-components-svelte/src/DatePicker/DatePicker.svelte" + }, + "DatePickerInput": { + "path": "carbon-components-svelte/src/DatePicker/DatePickerInput.svelte" + }, + "DatePickerSkeleton": { + "path": "carbon-components-svelte/src/DatePicker/DatePickerSkeleton.svelte" + }, + "Dropdown": { + "path": "carbon-components-svelte/src/Dropdown/Dropdown.svelte" + }, + "DropdownSkeleton": { + "path": "carbon-components-svelte/src/Dropdown/DropdownSkeleton.svelte" + }, + "Filename": { + "path": "carbon-components-svelte/src/FileUploader/Filename.svelte" + }, + "FileUploader": { + "path": "carbon-components-svelte/src/FileUploader/FileUploader.svelte" + }, + "FileUploaderButton": { + "path": "carbon-components-svelte/src/FileUploader/FileUploaderButton.svelte" + }, + "FileUploaderDropContainer": { + "path": "carbon-components-svelte/src/FileUploader/FileUploaderDropContainer.svelte" + }, + "FileUploaderItem": { + "path": "carbon-components-svelte/src/FileUploader/FileUploaderItem.svelte" + }, + "FileUploaderSkeleton": { + "path": "carbon-components-svelte/src/FileUploader/FileUploaderSkeleton.svelte" + }, + "FluidForm": { + "path": "carbon-components-svelte/src/FluidForm/FluidForm.svelte" + }, + "Form": { + "path": "carbon-components-svelte/src/Form/Form.svelte" + }, + "FormGroup": { + "path": "carbon-components-svelte/src/FormGroup/FormGroup.svelte" + }, + "FormItem": { + "path": "carbon-components-svelte/src/FormItem/FormItem.svelte" + }, + "FormLabel": { + "path": "carbon-components-svelte/src/FormLabel/FormLabel.svelte" + }, + "Column": { + "path": "carbon-components-svelte/src/Grid/Column.svelte" + }, + "Grid": { + "path": "carbon-components-svelte/src/Grid/Grid.svelte" + }, + "Row": { + "path": "carbon-components-svelte/src/Grid/Row.svelte" + }, + "Icon": { + "path": "carbon-components-svelte/src/Icon/Icon.svelte" + }, + "IconSkeleton": { + "path": "carbon-components-svelte/src/Icon/IconSkeleton.svelte" + }, + "InlineLoading": { + "path": "carbon-components-svelte/src/InlineLoading/InlineLoading.svelte" + }, + "Link": { + "path": "carbon-components-svelte/src/Link/Link.svelte" + }, + "ListBox": { + "path": "carbon-components-svelte/src/ListBox/ListBox.svelte" + }, + "ListBoxField": { + "path": "carbon-components-svelte/src/ListBox/ListBoxField.svelte" + }, + "ListBoxMenu": { + "path": "carbon-components-svelte/src/ListBox/ListBoxMenu.svelte" + }, + "ListBoxMenuIcon": { + "path": "carbon-components-svelte/src/ListBox/ListBoxMenuIcon.svelte" + }, + "ListBoxMenuItem": { + "path": "carbon-components-svelte/src/ListBox/ListBoxMenuItem.svelte" + }, + "ListBoxSelection": { + "path": "carbon-components-svelte/src/ListBox/ListBoxSelection.svelte" + }, + "ListItem": { + "path": "carbon-components-svelte/src/ListItem/ListItem.svelte" + }, + "Loading": { + "path": "carbon-components-svelte/src/Loading/Loading.svelte" + }, + "Modal": { + "path": "carbon-components-svelte/src/Modal/Modal.svelte" + }, + "MultiSelect": { + "path": "carbon-components-svelte/src/MultiSelect/MultiSelect.svelte" + }, + "InlineNotification": { + "path": "carbon-components-svelte/src/Notification/InlineNotification.svelte" + }, + "NotificationActionButton": { + "path": "carbon-components-svelte/src/Notification/NotificationActionButton.svelte" + }, + "NotificationButton": { + "path": "carbon-components-svelte/src/Notification/NotificationButton.svelte" + }, + "NotificationIcon": { + "path": "carbon-components-svelte/src/Notification/NotificationIcon.svelte" + }, + "NotificationTextDetails": { + "path": "carbon-components-svelte/src/Notification/NotificationTextDetails.svelte" + }, + "ToastNotification": { + "path": "carbon-components-svelte/src/Notification/ToastNotification.svelte" + }, + "NumberInput": { + "path": "carbon-components-svelte/src/NumberInput/NumberInput.svelte" + }, + "NumberInputSkeleton": { + "path": "carbon-components-svelte/src/NumberInput/NumberInputSkeleton.svelte" + }, + "OrderedList": { + "path": "carbon-components-svelte/src/OrderedList/OrderedList.svelte" + }, + "OverflowMenu": { + "path": "carbon-components-svelte/src/OverflowMenu/OverflowMenu.svelte" + }, + "OverflowMenuItem": { + "path": "carbon-components-svelte/src/OverflowMenu/OverflowMenuItem.svelte" + }, + "Pagination": { + "path": "carbon-components-svelte/src/Pagination/Pagination.svelte" + }, + "PaginationSkeleton": { + "path": "carbon-components-svelte/src/Pagination/PaginationSkeleton.svelte" + }, + "PaginationItem": { + "path": "carbon-components-svelte/src/PaginationNav/PaginationItem.svelte" + }, + "PaginationNav": { + "path": "carbon-components-svelte/src/PaginationNav/PaginationNav.svelte" + }, + "PaginationOverflow": { + "path": "carbon-components-svelte/src/PaginationNav/PaginationOverflow.svelte" + }, + "ProgressIndicator": { + "path": "carbon-components-svelte/src/ProgressIndicator/ProgressIndicator.svelte" + }, + "ProgressIndicatorSkeleton": { + "path": "carbon-components-svelte/src/ProgressIndicator/ProgressIndicatorSkeleton.svelte" + }, + "ProgressStep": { + "path": "carbon-components-svelte/src/ProgressIndicator/ProgressStep.svelte" + }, + "RadioButton": { + "path": "carbon-components-svelte/src/RadioButton/RadioButton.svelte" + }, + "RadioButtonSkeleton": { + "path": "carbon-components-svelte/src/RadioButton/RadioButtonSkeleton.svelte" + }, + "RadioButtonGroup": { + "path": "carbon-components-svelte/src/RadioButtonGroup/RadioButtonGroup.svelte" + }, + "Search": { + "path": "carbon-components-svelte/src/Search/Search.svelte" + }, + "SearchSkeleton": { + "path": "carbon-components-svelte/src/Search/SearchSkeleton.svelte" + }, + "Select": { + "path": "carbon-components-svelte/src/Select/Select.svelte" + }, + "SelectItem": { + "path": "carbon-components-svelte/src/Select/SelectItem.svelte" + }, + "SelectItemGroup": { + "path": "carbon-components-svelte/src/Select/SelectItemGroup.svelte" + }, + "SelectSkeleton": { + "path": "carbon-components-svelte/src/Select/SelectSkeleton.svelte" + }, + "SkeletonPlaceholder": { + "path": "carbon-components-svelte/src/SkeletonPlaceholder/SkeletonPlaceholder.svelte" + }, + "SkeletonText": { + "path": "carbon-components-svelte/src/SkeletonText/SkeletonText.svelte" + }, + "Slider": { + "path": "carbon-components-svelte/src/Slider/Slider.svelte" + }, + "SliderSkeleton": { + "path": "carbon-components-svelte/src/Slider/SliderSkeleton.svelte" + }, + "StructuredList": { + "path": "carbon-components-svelte/src/StructuredList/StructuredList.svelte" + }, + "StructuredListBody": { + "path": "carbon-components-svelte/src/StructuredList/StructuredListBody.svelte" + }, + "StructuredListCell": { + "path": "carbon-components-svelte/src/StructuredList/StructuredListCell.svelte" + }, + "StructuredListHead": { + "path": "carbon-components-svelte/src/StructuredList/StructuredListHead.svelte" + }, + "StructuredListInput": { + "path": "carbon-components-svelte/src/StructuredList/StructuredListInput.svelte" + }, + "StructuredListRow": { + "path": "carbon-components-svelte/src/StructuredList/StructuredListRow.svelte" + }, + "StructuredListSkeleton": { + "path": "carbon-components-svelte/src/StructuredList/StructuredListSkeleton.svelte" + }, + "Tab": { + "path": "carbon-components-svelte/src/Tabs/Tab.svelte" + }, + "TabContent": { + "path": "carbon-components-svelte/src/Tabs/TabContent.svelte" + }, + "Tabs": { + "path": "carbon-components-svelte/src/Tabs/Tabs.svelte" + }, + "TabsSkeleton": { + "path": "carbon-components-svelte/src/Tabs/TabsSkeleton.svelte" + }, + "Tag": { + "path": "carbon-components-svelte/src/Tag/Tag.svelte" + }, + "TagSkeleton": { + "path": "carbon-components-svelte/src/Tag/TagSkeleton.svelte" + }, + "TextArea": { + "path": "carbon-components-svelte/src/TextArea/TextArea.svelte" + }, + "TextAreaSkeleton": { + "path": "carbon-components-svelte/src/TextArea/TextAreaSkeleton.svelte" + }, + "PasswordInput": { + "path": "carbon-components-svelte/src/TextInput/PasswordInput.svelte" + }, + "TextInput": { + "path": "carbon-components-svelte/src/TextInput/TextInput.svelte" + }, + "TextInputSkeleton": { + "path": "carbon-components-svelte/src/TextInput/TextInputSkeleton.svelte" + }, + "ClickableTile": { + "path": "carbon-components-svelte/src/Tile/ClickableTile.svelte" + }, + "ExpandableTile": { + "path": "carbon-components-svelte/src/Tile/ExpandableTile.svelte" + }, + "RadioTile": { + "path": "carbon-components-svelte/src/Tile/RadioTile.svelte" + }, + "SelectableTile": { + "path": "carbon-components-svelte/src/Tile/SelectableTile.svelte" + }, + "Tile": { + "path": "carbon-components-svelte/src/Tile/Tile.svelte" + }, + "TileGroup": { + "path": "carbon-components-svelte/src/Tile/TileGroup.svelte" + }, + "TimePicker": { + "path": "carbon-components-svelte/src/TimePicker/TimePicker.svelte" + }, + "TimePickerSelect": { + "path": "carbon-components-svelte/src/TimePicker/TimePickerSelect.svelte" + }, + "Toggle": { + "path": "carbon-components-svelte/src/Toggle/Toggle.svelte" + }, + "ToggleSkeleton": { + "path": "carbon-components-svelte/src/Toggle/ToggleSkeleton.svelte" + }, + "ToggleSmall": { + "path": "carbon-components-svelte/src/ToggleSmall/ToggleSmall.svelte" + }, + "ToggleSmallSkeleton": { + "path": "carbon-components-svelte/src/ToggleSmall/ToggleSmallSkeleton.svelte" + }, + "Tooltip": { + "path": "carbon-components-svelte/src/Tooltip/Tooltip.svelte" + }, + "TooltipDefinition": { + "path": "carbon-components-svelte/src/TooltipDefinition/TooltipDefinition.svelte" + }, + "TooltipIcon": { + "path": "carbon-components-svelte/src/TooltipIcon/TooltipIcon.svelte" + }, + "Content": { + "path": "carbon-components-svelte/src/UIShell/Content.svelte" + }, + "Header": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/Header.svelte" + }, + "HeaderAction": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderAction.svelte" + }, + "HeaderActionLink": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderActionLink.svelte" + }, + "HeaderActionSearch": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderActionSearch.svelte" + }, + "HeaderNav": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderNav.svelte" + }, + "HeaderNavItem": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderNavItem.svelte" + }, + "HeaderNavMenu": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderNavMenu.svelte" + }, + "HeaderPanelDivider": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderPanelDivider.svelte" + }, + "HeaderPanelLink": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderPanelLink.svelte" + }, + "HeaderPanelLinks": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderPanelLinks.svelte" + }, + "HeaderUtilities": { + "path": "carbon-components-svelte/src/UIShell/GlobalHeader/HeaderUtilities.svelte" + }, + "HeaderGlobalAction": { + "path": "carbon-components-svelte/src/UIShell/HeaderGlobalAction.svelte" + }, + "HeaderSearch": { + "path": "carbon-components-svelte/src/UIShell/HeaderSearch.svelte" + }, + "HamburgerMenu": { + "path": "carbon-components-svelte/src/UIShell/SideNav/HamburgerMenu.svelte" + }, + "SideNav": { + "path": "carbon-components-svelte/src/UIShell/SideNav/SideNav.svelte" + }, + "SideNavItems": { + "path": "carbon-components-svelte/src/UIShell/SideNav/SideNavItems.svelte" + }, + "SideNavLink": { + "path": "carbon-components-svelte/src/UIShell/SideNav/SideNavLink.svelte" + }, + "SideNavMenu": { + "path": "carbon-components-svelte/src/UIShell/SideNav/SideNavMenu.svelte" + }, + "SideNavMenuItem": { + "path": "carbon-components-svelte/src/UIShell/SideNav/SideNavMenuItem.svelte" + }, + "SkipToContent": { + "path": "carbon-components-svelte/src/UIShell/SkipToContent.svelte" + }, + "UnorderedList": { + "path": "carbon-components-svelte/src/UnorderedList/UnorderedList.svelte" + } + } +} diff --git a/preprocess/index.js b/preprocess/index.js new file mode 100644 index 00000000..464e96a7 --- /dev/null +++ b/preprocess/index.js @@ -0,0 +1,5 @@ +const { optimizeCarbonImports } = require("./optimize-carbon-imports"); + +module.exports = { + optimizeCarbonImports, +}; diff --git a/preprocess/optimize-carbon-imports.js b/preprocess/optimize-carbon-imports.js new file mode 100644 index 00000000..bcbc0ad9 --- /dev/null +++ b/preprocess/optimize-carbon-imports.js @@ -0,0 +1,97 @@ +const fs = require("fs"); +const path = require("path"); +const { parse, walk } = require("svelte/compiler"); +const api = require("./api.json"); + +const carbon = { + components: "carbon-components-svelte", + icons: "carbon-icons-svelte", + pictograms: "carbon-pictograms-svelte", +}; + +function getPackageJson() { + const path_pkg = path.join(process.cwd(), "package.json"); + + if (fs.existsSync(path_pkg)) { + return JSON.parse(fs.readFileSync(path_pkg, "utf-8")); + } else { + return {}; + } +} + +function getCarbonVersions() { + const pkg = getPackageJson(); + const devDeps = pkg.devDependencies || {}; + const deps = pkg.dependencies || {}; + + return [carbon.components, carbon.icons, carbon.pictograms].reduce((a, c) => { + let version = devDeps[c] || deps[c]; + + if (version !== undefined) { + const [major, minor, patch] = version.replace(/^(\^|\~)/, "").split("."); + version = major; + } + + return { ...a, [c]: version }; + }, {}); +} + +const versions = getCarbonVersions(); + +function optimizeCarbonImports() { + return { + script: ({ content, filename }) => { + if (/node_modules/.test(filename)) return { code: content }; + + const ast = parse(``, { filename }); + + let cursor = -8; + + function replaceContent(node, onSpecifier) { + const replacer = node.specifiers.map((i) => onSpecifier(i)).join("\n"); + const replacee = content.slice(node.start + cursor, node.end + cursor); + + content = content.replace(replacee, replacer); + cursor += replacer.length - replacee.length; + } + + walk(ast.instance, { + enter(node) { + if (node.type === "ImportDeclaration") { + switch (node.source.value) { + case carbon.components: + replaceContent(node, ({ local, imported }) => { + return `import ${local.name} from "${ + api.components[imported.name].path + }";`; + }); + break; + + case carbon.icons: + replaceContent(node, ({ local, imported }) => { + return `import ${local.name} from "carbon-icons-svelte/lib/${imported.name}/${imported.name}.svelte";`; + }); + break; + + case carbon.pictograms: + replaceContent(node, ({ local, imported }) => { + if (versions[carbon.pictograms] === "11") { + return `import ${local.name} from "carbon-pictograms-svelte/lib/${imported.name}.svelte";`; + } + + return `import ${local.name} from "carbon-pictograms-svelte/lib/${imported.name}/${imported.name}.svelte";`; + }); + break; + } + } + }, + }); + + return { code: content }; + }, + }; +} + +module.exports = { + optimizeCarbonImports, +}; diff --git a/scripts/build-api.js b/scripts/build-api.js new file mode 100644 index 00000000..90d2d172 --- /dev/null +++ b/scripts/build-api.js @@ -0,0 +1,20 @@ +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); +const pkg = require("../package.json"); + +function buildApi() { + const components = {}; + + glob.sync("src/**/*.svelte").forEach((file) => { + const { name } = path.parse(file); + components[name] = { path: path.join(pkg.name, file) }; + }); + + fs.writeFileSync( + "preprocess/api.json", + JSON.stringify({ version: pkg.version, components }, null, 2) + ); +} + +buildApi(); diff --git a/tests/preprocess/index.js b/tests/preprocess/index.js new file mode 100644 index 00000000..b70ca2ba --- /dev/null +++ b/tests/preprocess/index.js @@ -0,0 +1 @@ +require("./optimize-carbon-imports.test"); diff --git a/tests/preprocess/optimize-carbon-imports.test.js b/tests/preprocess/optimize-carbon-imports.test.js new file mode 100644 index 00000000..de42e64e --- /dev/null +++ b/tests/preprocess/optimize-carbon-imports.test.js @@ -0,0 +1,139 @@ +const assert = require("assert"); +const { preprocess } = require("svelte/compiler"); +const { optimizeCarbonImports } = require("../../preprocess"); + +const fixtures = [ + { + name: "Single base import", + input: ` + `, + output: ` + `, + }, + { + name: "Single base import with markup, styles", + input: ` + + + + + `, + output: ` + + + + + `, + }, + { + name: "Single, aliased base import", + input: ` + `, + output: ` + `, + }, + { + name: "Multiple base imports", + input: ` + `, + output: ` + `, + }, + { + name: "Multiple imports from component folder", + input: ` + `, + output: ` + `, + }, + { + name: "Direct import from component source", + input: ` + `, + output: ` + `, + }, + { + name: "Carbon icons", + input: ` + `, + output: ` + `, + }, + { + name: "Carbon pictograms", + input: ` + `, + output: ` + `, + }, + { + name: "Integration", + input: ` + `, + output: ` + + `, + }, +]; + +(async () => { + for (const { name, input, output } of fixtures) { + console.log("[optimizeCarbonImports]", name); + + const result = await preprocess(input.trim(), [optimizeCarbonImports()]); + assert.strictEqual(result.toString(), output.trim()); + } +})();