feat(rocket-preset-extend-lion-docs): initial release
This commit is contained in:
parent
0bda0fbff3
commit
0ca860315b
53 changed files with 1523 additions and 567 deletions
13
.changeset/big-hotels-exercise.md
Normal file
13
.changeset/big-hotels-exercise.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
'babel-plugin-extend-docs': minor
|
||||
---
|
||||
|
||||
Work with package entry points (exports) and internal imports.
|
||||
|
||||
This simplified the internal logic a lot. For more details please see [package entry points](https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_exports) in the node documentation.
|
||||
|
||||
BREAKING CHANGES:
|
||||
|
||||
- we no longer support relative import paths in demos
|
||||
- no need to pass on a `rootPath` or `\_\_filePath`` anymore
|
||||
- option `throwOnNonExistingPathToFiles` and `throwOnNonExistingRootPath` got removed
|
||||
5
.changeset/light-clouds-scream.md
Normal file
5
.changeset/light-clouds-scream.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'rocket-preset-extend-lion-docs': minor
|
||||
---
|
||||
|
||||
Initial release
|
||||
|
|
@ -2,4 +2,4 @@
|
|||
'@lion/combobox': minor
|
||||
---
|
||||
|
||||
Add a new \_getTextboxValueFromOption method on LionCombobox, to be able to overide how the modelValue is displayed in the textbox
|
||||
Add a new \_getTextboxValueFromOption method on LionCombobox, to be able to override how the modelValue is displayed in the textbox
|
||||
|
|
|
|||
|
|
@ -10,25 +10,32 @@ npm i -D babel-plugin-extend-docs
|
|||
```
|
||||
|
||||
We want to only execute `babel-plugin-extend-docs` on the actual files we want to modify/extend.
|
||||
We recommend using [babel overrides](https://babeljs.io/docs/en/options#overrides) for it.
|
||||
|
||||
👉 _babel.config.js_
|
||||
You may also consider using [babel overrides](https://babeljs.io/docs/en/options#overrides).
|
||||
|
||||
👉 _web-dev-server.config.js_
|
||||
|
||||
```js
|
||||
import path from 'path';
|
||||
import { fromRollup } from '@web/dev-server-rollup';
|
||||
import rollupBabel from '@rollup/plugin-babel';
|
||||
|
||||
const extendDocsConfig = {
|
||||
rootPath: process.cwd(), // or `path.resolve('./')` as plugin needs to know the rootPath of your project
|
||||
changes: [
|
||||
// possible changes as described below
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
overrides: [
|
||||
{
|
||||
// plugin will only be executed on files that match this pattern
|
||||
test: ['./node_modules/source-library/demos/**/*.js'],
|
||||
plugins: [['babel-plugin-extend-docs', extendDocsConfig]],
|
||||
},
|
||||
// note that you need to use `.default` for babel
|
||||
const babel = fromRollup(rollupBabel.default);
|
||||
|
||||
export default {
|
||||
nodeResolve: true,
|
||||
plugins: [
|
||||
babel({
|
||||
include: ['./glob/to/files/**/*.js'],
|
||||
plugins: [[path.resolve('./'), extendDocsConfig]],
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
|
@ -63,14 +70,11 @@ changes: [
|
|||
|
||||
### Paths
|
||||
|
||||
Both `variable` and `tag` are required to have a `paths` array which defines how to remap import paths. As demos can use multiple ways to import all of them needs to be written down in the config.
|
||||
Both `variable` and `tag` are required to have a `paths` array which defines how to remap import paths. Generally it should be a single entry.
|
||||
|
||||
```js
|
||||
paths: [
|
||||
{ from: './index.js', to: './my-extension/index.js' },
|
||||
{ from: '../index.js', to: '../my-extension/index.js' },
|
||||
{ from: './src/MyCounter.js', to: './my-extension/index.js' },
|
||||
{ from: '../src/MyCounter.js', to: '../my-extension/index.js' },
|
||||
{ from: 'source-pkg/counter', to: 'extension-pkg/counter' },
|
||||
],
|
||||
```
|
||||
|
||||
|
|
@ -80,28 +84,28 @@ We have an existing demo code which we want to reuse.
|
|||
|
||||
```js
|
||||
import { LitElement, html } from '@lion/core';
|
||||
import './my-counter.js';
|
||||
import 'source-pkg/counter/define';
|
||||
class MyApp extends LitElement {
|
||||
render() {
|
||||
return html`
|
||||
<h1>Example App</h1>
|
||||
<my-counter></my-counter>
|
||||
<source-counter></source-counter>
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define('my-app', MyApp);
|
||||
```
|
||||
|
||||
We created a "better" version of `<my-counter>` so we would like to use that in the demo.
|
||||
Our extension is called `<my-extension>` and is available in `./my-extension/my-extension.js`.
|
||||
We created a "better" version of `<source-counter>` so we would like to use that in the demo.
|
||||
Our extension is called `<extension-counter>` and is available via `extension-pkg/counter/define`.
|
||||
|
||||
Within `babel-plugin-extend-docs` we can define to replace the tag + it's import.
|
||||
|
||||
```js
|
||||
tag: {
|
||||
from: 'my-counter',
|
||||
to: 'my-extension',
|
||||
paths: [{ from: './my-counter.js', to: './my-extension/my-extension.js' }],
|
||||
from: 'source-counter',
|
||||
to: 'extension-counter',
|
||||
paths: [{ from: 'source-pkg/counter/define', to: 'extension-pkg/counter/define' }],
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -109,12 +113,12 @@ tag: {
|
|||
|
||||
```js
|
||||
import { LitElement, html } from '@lion/core';
|
||||
import './my-extension/my-extension.js';
|
||||
import 'extension-pkg/counter/define';
|
||||
class MyApp extends LitElement {
|
||||
render() {
|
||||
return html`
|
||||
<h1>Example App</h1>
|
||||
<my-extension></my-extension>
|
||||
<extension-counter></extension-counter>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
@ -127,13 +131,14 @@ We have an existing demo code which we want to reuse.
|
|||
|
||||
```js
|
||||
import { LitElement, html } from '@lion/core';
|
||||
import { MyCounter } from './src/MyCounter.js';
|
||||
class TenCounter extends MyCounter {
|
||||
import { SourceCounter } from 'source-pkg/counter';
|
||||
class TenCounter extends SourceCounter {
|
||||
inc() {
|
||||
this.count += 10;
|
||||
}
|
||||
}
|
||||
customElements.define('ten-counter', TenCounter);
|
||||
|
||||
class MyApp extends LitElement {
|
||||
render() {
|
||||
return html`
|
||||
|
|
@ -145,16 +150,16 @@ class MyApp extends LitElement {
|
|||
customElements.define('my-app', MyApp);
|
||||
```
|
||||
|
||||
We created a "better" version of `MyCounter` so we would like that `TenCounter` now extends it instead.
|
||||
We created a "better" version of `SourceCounter` so we would like that `TenCounter` now extends it instead.
|
||||
|
||||
Within `babel-plugin-extend-docs` we can define to replace the class + it's import.
|
||||
|
||||
```js
|
||||
variable: {
|
||||
from: 'MyCounter',
|
||||
to: 'MyExtension',
|
||||
from: 'SourceCounter',
|
||||
to: 'ExtensionCounter',
|
||||
paths: [
|
||||
{ from: './src/MyCounter.js', to: './my-extension/index.js' },
|
||||
{ from: 'source-pkg/counter', to: 'extension-pkg/counter' },
|
||||
],
|
||||
},
|
||||
```
|
||||
|
|
@ -163,8 +168,8 @@ variable: {
|
|||
|
||||
```js
|
||||
import { LitElement, html } from '@lion/core';
|
||||
import { MyExtension } from './my-extension/index.js';
|
||||
class TenCounter extends MyExtension {
|
||||
import { SourceCounter } from 'extension-pkg/counter';
|
||||
class TenCounter extends SourceCounter {
|
||||
inc() {
|
||||
this.count += 10;
|
||||
}
|
||||
|
|
@ -184,41 +189,45 @@ customElements.define('my-app', MyApp);
|
|||
## Full Demo & Api Example
|
||||
|
||||
You can run the example locally via `npm run start` or look at its [source code](https://github.com/ing-bank/lion/tree/master/packages-node/babel-plugin-extend-docs/demo/).
|
||||
_Note we are configuring babel via the [server.config.js](https://github.com/ing-bank/lion/tree/master/packages-node/babel-plugin-extend-docs/demo/server.config.js)_
|
||||
_Note we are configuring babel via the [server.config.mjs](https://github.com/ing-bank/lion/tree/master/packages-node/babel-plugin-extend-docs/demo/server.config.mjs)_
|
||||
|
||||
👉 _babel.config.js_
|
||||
👉 _server.config.mjs_
|
||||
|
||||
```js
|
||||
const path = require('path');
|
||||
import path from 'path';
|
||||
import { fromRollup } from '@web/dev-server-rollup';
|
||||
import rollupBabel from '@rollup/plugin-babel';
|
||||
|
||||
const extendDocsConfig = {
|
||||
rootPath: path.resolve('./demo'),
|
||||
changes: [
|
||||
{
|
||||
name: 'MyCounter',
|
||||
name: 'SourceCounter',
|
||||
variable: {
|
||||
from: 'MyCounter',
|
||||
to: 'MyExtension',
|
||||
paths: [
|
||||
{ from: './index.js', to: './my-extension/index.js' },
|
||||
{ from: './src/MyCounter.js', to: './my-extension/index.js' },
|
||||
],
|
||||
from: 'SourceCounter',
|
||||
to: 'ExtensionCounter',
|
||||
paths: [{ from: '#source/counter', to: '#extension/counter' }],
|
||||
},
|
||||
tag: {
|
||||
from: 'my-counter',
|
||||
to: 'my-extension',
|
||||
paths: [{ from: './my-counter.js', to: './my-extension/my-extension.js' }],
|
||||
from: 'source-counter',
|
||||
to: 'extension-counter',
|
||||
paths: [{ from: '#source/counter/define', to: '#extension/counter/define' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
overrides: [
|
||||
{
|
||||
test: ['./node_modules/@lion/*/README.md', './node_modules/@lion/*/docs/**/*.md',
|
||||
plugins: [['babel-plugin-docs-extend', extendDocsConfig]],
|
||||
},
|
||||
// note that you need to use `.default` for babel
|
||||
const babel = fromRollup(rollupBabel.default);
|
||||
|
||||
export default {
|
||||
nodeResolve: true,
|
||||
watch: true,
|
||||
open: 'demo/',
|
||||
plugins: [
|
||||
babel({
|
||||
include: ['./demo/**/*.demo.js'],
|
||||
plugins: [[path.resolve('./'), extendDocsConfig]],
|
||||
}),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
# Node Tools >> Extend Docs ||5
|
||||
248
docs/docs/node-tools/rocket-preset-extend-lion-docs/overview.md
Normal file
248
docs/docs/node-tools/rocket-preset-extend-lion-docs/overview.md
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
# Node Tools >> Extend Docs >> Overview ||10
|
||||
|
||||
When maintaining your own extension layer of lion you most likely want to maintain a similar documentation.
|
||||
Copying and rewriting imports/tags the markdown files works but also means that whenever something change you need copy and rewrite again.
|
||||
|
||||
To do this automatically you can use this preset for [rocket](https://rocket.modern-web.dev/).
|
||||
|
||||
## Features
|
||||
|
||||
- Import lion documentation and adjust it using [remark-extend](../remark-extend/overview.md)
|
||||
- Renames named imports and all it's usage
|
||||
- Adjusts import paths
|
||||
- Replace tags in template literals
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i -D rocket-preset-extend-lion-docs
|
||||
```
|
||||
|
||||
👉 _rocket.config.js_
|
||||
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
import { extendLionDocs } from 'rocket-preset-extend-lion-docs';
|
||||
|
||||
const extendLionDocsInstance = await extendLionDocs({
|
||||
classPrefix: 'Wolf',
|
||||
classBareImport: '@wolf/',
|
||||
tagPrefix: 'wolf-',
|
||||
tagBareImport: '@wolf/',
|
||||
});
|
||||
|
||||
export default {
|
||||
presets: [rocketLaunch(), extendLionDocsInstance],
|
||||
};
|
||||
```
|
||||
|
||||
## Reusing documentation
|
||||
|
||||
To take an existing documentation you can "import" it using [remark-extend](../remark-extend/overview.md).
|
||||
|
||||
As an example you can create `docs/components/tabs/overview.md`.
|
||||
|
||||
In it you do
|
||||
|
||||
- write a headline
|
||||
- use importSmallBlockContent to reuse content from lion
|
||||
- add your own installation instruction
|
||||
|
||||
````md
|
||||
# Content >> Tabs >> Overview ||10
|
||||
|
||||
```js ::importSmallBlockContent('@lion/tabs/docs/overview.md', '# Content >> Tabs >> Overview ||10')
|
||||
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @wolf/tabs
|
||||
```
|
||||
|
||||
```js
|
||||
import { WolfTabs } from '@wolf/tabs';
|
||||
```
|
||||
````
|
||||
|
||||
## How does it work
|
||||
|
||||
1. `importSmallBlockContent`` will import the content from lion
|
||||
2. all code blocks will then be precessed to use `@wolf` instead of `@lion`
|
||||
3. all links which are absolute to github will be processed to be local links
|
||||
|
||||
as an example this is a part of the lion docs for tabs
|
||||
|
||||
````md
|
||||
```js script
|
||||
import { LitElement, html } from '@lion/core';
|
||||
import '@lion/tabs/define';
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html`
|
||||
<lion-tabs>
|
||||
<button slot="tab">Info</button>
|
||||
<p slot="panel">Info page with lots of information about us.</p>
|
||||
<button slot="tab">Work</button>
|
||||
<p slot="panel">Work page that showcases our work.</p>
|
||||
</lion-tabs>
|
||||
`;
|
||||
```
|
||||
````
|
||||
|
||||
After all replacements the output that will be used for markdown rendering will be
|
||||
|
||||
````md
|
||||
# Content >> Tabs >> Overview ||10
|
||||
|
||||
```js script
|
||||
import { LitElement, html } from '@wolf/core';
|
||||
import '@wolf/tabs/define';
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html`
|
||||
<wolf-tabs>
|
||||
<button slot="tab">Info</button>
|
||||
<p slot="panel">Info page with lots of information about us.</p>
|
||||
<button slot="tab">Work</button>
|
||||
<p slot="panel">Work page that showcases our work.</p>
|
||||
</wolf-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @wolf/tabs
|
||||
```
|
||||
|
||||
```js
|
||||
import { WolfTabs } from '@wolf/tabs';
|
||||
```
|
||||
````
|
||||
|
||||
Doing so means you can focus on writing what is specific to your design system extension and you don't need to rewrite all the examples and explanations of lion but you can import them while still using your components.
|
||||
|
||||
## Use with a monorepo
|
||||
|
||||
The above setup assumes that you have the same "system" of exports in `@wolf` as we have in `@lion`.
|
||||
|
||||
So your users are able to do
|
||||
|
||||
```js
|
||||
// provide classes as side effect free imports
|
||||
import { WolfTabs } from '@wolf/tabs';
|
||||
// register web components via `/define`
|
||||
import '@wolf/tabs/define';
|
||||
```
|
||||
|
||||
This means you need to have to define the following package entry points for you tabs extension.
|
||||
|
||||
👉 _tabs/package.json_
|
||||
|
||||
```json
|
||||
"exports": {
|
||||
".": "./src/index.js",
|
||||
"./define": "./src/define/tabs.js",
|
||||
}
|
||||
```
|
||||
|
||||
## Use as a single repo
|
||||
|
||||
Often its easier for your users to have one package to work with instead of a big list of individual packages.
|
||||
If you are distributing one package then your exports/imports will be different.
|
||||
|
||||
So your users are able to do
|
||||
|
||||
```js
|
||||
// provide classes as side effect free imports
|
||||
import { WolfTabs } from 'wolf-web/tabs';
|
||||
// register web components via `/define`
|
||||
import 'wolf-web/tabs/define';
|
||||
```
|
||||
|
||||
👉 _package.json_
|
||||
|
||||
```json
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./tabs/define": "./define/tabs.js",
|
||||
}
|
||||
```
|
||||
|
||||
The configuration for that is
|
||||
|
||||
👉 _rocket.config.js_
|
||||
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
import { extendLionDocs } from 'rocket-preset-extend-lion-docs';
|
||||
|
||||
const extendLionDocsInstance = await extendLionDocs({
|
||||
classPrefix: 'Wolf',
|
||||
classBareImport: 'wolf-web/',
|
||||
tagPrefix: 'wolf-',
|
||||
tagBareImport: 'wolf-web/',
|
||||
});
|
||||
|
||||
export default {
|
||||
presets: [rocketLaunch(), extendLionDocsInstance],
|
||||
};
|
||||
```
|
||||
|
||||
## Do not distribute side effects
|
||||
|
||||
When distributing you may choose to stay side effect free. This means no definitions of custom elements. You may want to do this to "force" usage of a scoped registry in order to support multiple mayor version of a component in a single application. We would recommend [Scoped Elements](https://open-wc.org/docs/development/scoped-elements/) for that.
|
||||
|
||||
So your users are able to do
|
||||
|
||||
```js
|
||||
// provide classes as side effect free imports
|
||||
import { WolfTabs } from 'wolf-web/tabs';
|
||||
// NOTE: there no way to import a definition as a user
|
||||
```
|
||||
|
||||
For demos it's still useful/needed to have those definitions. To have them but not exposing them you can use private imports which are only available to the package itself. This features is called [Subpath imports](https://nodejs.org/dist/latest-v16.x/docs/api/packages.html#packages_subpath_imports) in node.
|
||||
|
||||
To enable it you can set the following settings
|
||||
|
||||
👉 _rocket.config.js_
|
||||
|
||||
```js
|
||||
import { rocketLaunch } from '@rocket/launch';
|
||||
import { extendLionDocs } from 'rocket-preset-extend-lion-docs';
|
||||
|
||||
const extendLionDocsInstance = await extendLionDocs({
|
||||
classPrefix: 'Wolf',
|
||||
classBareImport: 'wolf-web/',
|
||||
tagPrefix: 'wolf-',
|
||||
tagBareImport: '#',
|
||||
});
|
||||
|
||||
export default {
|
||||
presets: [rocketLaunch(), extendLionDocsInstance],
|
||||
};
|
||||
```
|
||||
|
||||
This rewrites the custom element definition side effects to
|
||||
|
||||
```js
|
||||
// from
|
||||
import '@lion/tabs/define';
|
||||
|
||||
// to
|
||||
import '#tabs/define';
|
||||
```
|
||||
|
||||
In order for such imports to work you need to define them
|
||||
|
||||
👉 _package.json_
|
||||
|
||||
```json
|
||||
"imports": {
|
||||
"#tabs/define": "./__element-definitions/wolf-tabs.js",
|
||||
}
|
||||
```
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
"postinstall-postinstall": "^2.1.0",
|
||||
"prettier": "^2.0.5",
|
||||
"prettier-package-json": "^2.1.3",
|
||||
"remark-html": "^11.0.1",
|
||||
"remark-html": "^13.0.1",
|
||||
"rimraf": "^2.6.3",
|
||||
"rollup": "^2.0.0",
|
||||
"sinon": "^7.2.2",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
/* eslint-disable import/extensions */
|
||||
import { LitElement, html } from '@lion/core';
|
||||
|
||||
import { MyCounter } from './src/MyCounter.js';
|
||||
import './my-counter.js';
|
||||
import { SourceCounter } from '#source/counter';
|
||||
import '#source/counter/define';
|
||||
|
||||
class TenCounter extends MyCounter {
|
||||
class TenCounter extends SourceCounter {
|
||||
inc() {
|
||||
this.count += 10;
|
||||
}
|
||||
|
|
@ -15,7 +16,7 @@ class MyApp extends LitElement {
|
|||
return html`
|
||||
<h1>Example App</h1>
|
||||
<hr />
|
||||
<my-counter></my-counter>
|
||||
<source-counter></source-counter>
|
||||
<hr />
|
||||
<ten-counter></ten-counter>
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
import { MyCounter } from './src/MyCounter.js';
|
||||
|
||||
customElements.define('my-counter', MyCounter);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { html, css } from '@lion/core';
|
||||
import { MyCounter } from '../src/MyCounter.js';
|
||||
import { SourceCounter } from '../src/SourceCounter.js';
|
||||
|
||||
export class MyExtension extends MyCounter {
|
||||
export class ExtensionCounter extends SourceCounter {
|
||||
static get styles() {
|
||||
return [
|
||||
...super.styles,
|
||||
|
|
@ -14,6 +14,6 @@ export class MyExtension extends MyCounter {
|
|||
}
|
||||
|
||||
_renderHeader() {
|
||||
return html`<h2>I am MyExtension</h2> `;
|
||||
return html`<h2>I am ExtensionCounter</h2> `;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { ExtensionCounter } from './ExtensionCounter.js';
|
||||
|
||||
customElements.define('extension-counter', ExtensionCounter);
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { MyExtension } from './MyExtension.js';
|
||||
|
||||
customElements.define('my-extension', MyExtension);
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
const extendDocsConfig = {
|
||||
changes: [
|
||||
{
|
||||
name: 'MyCounter',
|
||||
variable: {
|
||||
from: 'MyCounter',
|
||||
to: 'MyExtension',
|
||||
paths: [
|
||||
{ from: './index.js', to: './my-extension/index.js' },
|
||||
{ from: './src/MyCounter.js', to: './my-extension/index.js' },
|
||||
],
|
||||
},
|
||||
tag: {
|
||||
from: 'my-counter',
|
||||
to: 'my-extension',
|
||||
paths: [{ from: './my-counter.js', to: './my-extension/my-extension.js' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
rootPath: path.resolve('./demo'),
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
nodeResolve: true,
|
||||
watch: true,
|
||||
open: 'packages-node/babel-plugin-extend-docs/demo/',
|
||||
babel: true,
|
||||
babelConfig: {
|
||||
overrides: [
|
||||
{
|
||||
test: ['./demo/**/*.demo.js'],
|
||||
plugins: [[path.resolve('./'), extendDocsConfig]],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import path from 'path';
|
||||
import { fromRollup } from '@web/dev-server-rollup';
|
||||
import rollupBabel from '@rollup/plugin-babel';
|
||||
|
||||
const extendDocsConfig = {
|
||||
changes: [
|
||||
{
|
||||
name: 'SourceCounter',
|
||||
variable: {
|
||||
from: 'SourceCounter',
|
||||
to: 'ExtensionCounter',
|
||||
paths: [
|
||||
{ from: '#source/counter', to: '#extension/counter' },
|
||||
],
|
||||
},
|
||||
tag: {
|
||||
from: 'source-counter',
|
||||
to: 'extension-counter',
|
||||
paths: [{ from: '#source/counter/define', to: '#extension/counter/define' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// note that you need to use `.default` for babel
|
||||
const babel = fromRollup(rollupBabel.default);
|
||||
|
||||
export default {
|
||||
nodeResolve: true,
|
||||
watch: true,
|
||||
open: 'demo/',
|
||||
plugins: [
|
||||
babel({
|
||||
include: ['./demo/**/*.demo.js'],
|
||||
plugins: [[path.resolve('./'), extendDocsConfig]],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
nodeResolve: true,
|
||||
watch: true,
|
||||
open: 'packages-node/babel-plugin-extend-docs/demo/',
|
||||
};
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
nodeResolve: true,
|
||||
watch: true,
|
||||
open: 'demo/',
|
||||
};
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
import { LitElement, html, css } from '@lion/core';
|
||||
|
||||
export class MyCounter extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
count: { type: Number },
|
||||
};
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return css`
|
||||
:host {
|
||||
display: block;
|
||||
width: 220px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
button,
|
||||
span {
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
span {
|
||||
width: 4rem;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
background-color: seagreen;
|
||||
color: white;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
inc() {
|
||||
this.count += 1;
|
||||
}
|
||||
|
||||
dec() {
|
||||
this.count -= 1;
|
||||
}
|
||||
|
||||
_renderHeader() {
|
||||
return html`<h3>I am MyCounter</h3> `;
|
||||
}
|
||||
|
||||
_renderIncButton() {
|
||||
return html`<button @click="${this.inc}">+</button> `;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${this._renderHeader()}
|
||||
<button @click="${this.dec}">-</button>
|
||||
<span>${this.count}</span>
|
||||
${this._renderIncButton()}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
import { LitElement, html, css } from '@lion/core';
|
||||
|
||||
export class SourceCounter extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
count: { type: Number },
|
||||
};
|
||||
}
|
||||
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
width: 220px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
button,
|
||||
span {
|
||||
font-size: 200%;
|
||||
}
|
||||
|
||||
span {
|
||||
width: 4rem;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
background-color: seagreen;
|
||||
color: white;
|
||||
}
|
||||
|
||||
h3 {
|
||||
text-align: center;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
inc() {
|
||||
this.count += 1;
|
||||
}
|
||||
|
||||
dec() {
|
||||
this.count -= 1;
|
||||
}
|
||||
|
||||
_renderHeader() {
|
||||
return html`<h3>I am SourceCounter</h3> `;
|
||||
}
|
||||
|
||||
_renderIncButton() {
|
||||
return html`<button @click="${this.inc}">+</button> `;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
${this._renderHeader()}
|
||||
<button @click="${this.dec}">-</button>
|
||||
<span>${this.count}</span>
|
||||
${this._renderIncButton()}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { SourceCounter } from './SourceCounter.js';
|
||||
|
||||
customElements.define('source-counter', SourceCounter);
|
||||
|
|
@ -19,8 +19,8 @@
|
|||
"scripts": {
|
||||
"publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../",
|
||||
"prepublishOnly": "npm run publish-docs",
|
||||
"start": "es-dev-server -c demo/server.config.js --root-dir ../../",
|
||||
"start:no-babel": "es-dev-server -c demo/server.no-babel.config.js --root-dir ../../",
|
||||
"start": "web-dev-server -c demo/server.config.mjs",
|
||||
"start:no-babel": "web-dev-server -c demo/server.no-babel.config.mjs",
|
||||
"test": "npm run test:node",
|
||||
"test:node": "mocha test-node",
|
||||
"test:watch": "mocha test-node --watch"
|
||||
|
|
@ -35,5 +35,11 @@
|
|||
"exports": {
|
||||
".": "./index.js",
|
||||
"./docs/": "./docs/"
|
||||
},
|
||||
"imports": {
|
||||
"#source/counter": "./demo/src/SourceCounter.js",
|
||||
"#source/counter/define": "./demo/src/define.js",
|
||||
"#extension/counter": "./demo/my-extension/ExtensionCounter.js",
|
||||
"#extension/counter/define": "./demo/my-extension/define.js"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,6 @@ function insertImportStatements({ imports, path }) {
|
|||
module.exports = ({ types: t }) => ({
|
||||
visitor: {
|
||||
ImportDeclaration(path, state) {
|
||||
// If a filePath is not passed explicitly by the user, take the filename provided by babel
|
||||
// and subtract the rootpath from it, to get the desired filePath relative to the root.
|
||||
state.filePath = state.opts.__filePath
|
||||
? state.opts.__filePath
|
||||
: state.file.opts.filename.replace(state.opts.rootPath, '');
|
||||
|
||||
if (path.node.specifiers.length > 0) {
|
||||
renameAndStoreImports({ path, state, opts: state.opts, types: t });
|
||||
} else {
|
||||
|
|
@ -52,7 +46,6 @@ module.exports = ({ types: t }) => ({
|
|||
validateOptions(state.opts);
|
||||
|
||||
state.importedStorage = [];
|
||||
state.filePath = '';
|
||||
},
|
||||
exit: (path, state) => {
|
||||
const imports = generateImportStatements({ state, types: t });
|
||||
|
|
|
|||
|
|
@ -1,15 +1,5 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
const { joinPaths } = require('./helpers.js');
|
||||
|
||||
/**
|
||||
* -1 because filepath is an absolute path starting with '/' and we turn it into a relative path without a '/' at the start
|
||||
* @param {*} filePath
|
||||
*/
|
||||
function getFolderDepth(filePath) {
|
||||
return [...filePath.match(new RegExp(/\/|\\/, 'g'))].length - 1;
|
||||
}
|
||||
|
||||
function getImportAs(specifier, newImportName) {
|
||||
if (specifier.local && specifier.local.name && specifier.local.name !== specifier.imported.name) {
|
||||
return specifier.local.name;
|
||||
|
|
@ -23,12 +13,10 @@ function renameAndStoreImports({ path, state, opts, types: t }) {
|
|||
|
||||
if (t.isIdentifier(specifier.imported) && specifier.type === 'ImportSpecifier') {
|
||||
for (const change of opts.changes) {
|
||||
if (specifier.imported.name === change.variable.from) {
|
||||
if (change.variable && specifier.imported.name === change.variable.from) {
|
||||
for (const { from, to } of change.variable.paths) {
|
||||
if (managed === false && from === path.node.source.value) {
|
||||
const relativePart = '../'.repeat(getFolderDepth(state.filePath));
|
||||
const importAs = getImportAs(specifier, change.variable.to);
|
||||
const newPath = joinPaths(relativePart, to);
|
||||
|
||||
// rename so it replaces all occurrences
|
||||
path.scope.rename(specifier.local.name, importAs);
|
||||
|
|
@ -38,7 +26,7 @@ function renameAndStoreImports({ path, state, opts, types: t }) {
|
|||
state.importedStorage.push({
|
||||
action: 'change',
|
||||
specifier,
|
||||
path: newPath,
|
||||
path: to,
|
||||
});
|
||||
managed = true;
|
||||
}
|
||||
|
|
@ -75,14 +63,12 @@ function generateImportStatements({ state, types: t }) {
|
|||
return res;
|
||||
}
|
||||
|
||||
function replaceTagImports({ path, state, opts, types: t }) {
|
||||
function replaceTagImports({ path, opts, types: t }) {
|
||||
for (const change of opts.changes) {
|
||||
if (change.tag && Array.isArray(change.tag.paths) && change.tag.paths.length > 0) {
|
||||
for (const { from, to } of change.tag.paths) {
|
||||
if (from === path.node.source.value) {
|
||||
const relativePart = '../'.repeat(getFolderDepth(state.filePath));
|
||||
const updatedPath = joinPaths(relativePart, to);
|
||||
path.node.source = t.stringLiteral(updatedPath);
|
||||
path.node.source = t.stringLiteral(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
function joinPaths(a, b) {
|
||||
let joinMe = b;
|
||||
if (a && a === b.substring(0, a.length)) {
|
||||
joinMe = b.substring(a.length + 1);
|
||||
}
|
||||
// Normalize for windows
|
||||
const updatedPath = path.posix.join(a, joinMe);
|
||||
|
||||
if (a === '' && b.startsWith('./')) {
|
||||
return `./${updatedPath}`;
|
||||
}
|
||||
return updatedPath;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
joinPaths,
|
||||
};
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
const fs = require('fs');
|
||||
|
||||
const { joinPaths } = require('./helpers.js');
|
||||
|
||||
const tagExample = [
|
||||
'Should be example:',
|
||||
' {',
|
||||
" from: 'my-counter',",
|
||||
" to: 'my-extension',",
|
||||
" from: 'source-counter',",
|
||||
" to: 'extension-counter',",
|
||||
' paths: [',
|
||||
' {',
|
||||
" from: './my-counter.js',",
|
||||
" to: './my-extension/my-extension.js'",
|
||||
" from: '@source/counter/define',",
|
||||
" to: 'extension/counter/define'",
|
||||
' }',
|
||||
' ]',
|
||||
' }',
|
||||
|
|
@ -19,12 +15,12 @@ const tagExample = [
|
|||
const variableExample = [
|
||||
'Should be example:',
|
||||
' {',
|
||||
" from: 'MyCounter',",
|
||||
" to: 'MyExtension',",
|
||||
" from: 'SourceCounter',",
|
||||
" to: 'ExtensionCounter',",
|
||||
' paths: [',
|
||||
' {',
|
||||
" from: './index.js',",
|
||||
" to: './my-extension/index.js'",
|
||||
" from: '@source/counter',",
|
||||
" to: 'extension/counter'",
|
||||
' }',
|
||||
' ]',
|
||||
' }',
|
||||
|
|
@ -37,7 +33,7 @@ function formatJsonErrorMessage(json) {
|
|||
return `\n ${JSON.stringify(json, null, 2).split('\n').join('\n ')}`;
|
||||
}
|
||||
|
||||
function validatePaths(paths, given, intro, example, options) {
|
||||
function validatePaths(paths, given, intro, example) {
|
||||
if (!Array.isArray(paths) || (Array.isArray(paths) && paths.length === 0)) {
|
||||
const errorMsg = [
|
||||
intro,
|
||||
|
|
@ -60,18 +56,11 @@ function validatePaths(paths, given, intro, example, options) {
|
|||
}
|
||||
if (typeof pathObj.to !== 'string' || !pathObj.to) {
|
||||
throw new Error(errorMsg);
|
||||
} else if (options.throwOnNonExistingPathToFiles === true) {
|
||||
const filePath = joinPaths(options.rootPath, pathObj.to);
|
||||
if (!(fs.existsSync(filePath) && fs.lstatSync(filePath).isFile())) {
|
||||
throw new Error(
|
||||
`babel-plugin-extend-docs: Rewriting import from "${pathObj.from}" to "${pathObj.to}" but we could not find a file at "${filePath}".`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateChanges(changes, options) {
|
||||
function validateChanges(changes) {
|
||||
if (!Array.isArray(changes) || (Array.isArray(changes) && changes.length === 0)) {
|
||||
const errorMsg = [
|
||||
'babel-plugin-extend-docs: The required changes array is missing.',
|
||||
|
|
@ -92,7 +81,7 @@ function validateChanges(changes, options) {
|
|||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
validatePaths(tag.paths, tag, intro, tagExample, options);
|
||||
validatePaths(tag.paths, tag, intro, tagExample);
|
||||
}
|
||||
|
||||
if (change.variable) {
|
||||
|
|
@ -109,39 +98,16 @@ function validateChanges(changes, options) {
|
|||
if (typeof variable.to !== 'string' || !variable.to) {
|
||||
throw new Error(errorMsg);
|
||||
}
|
||||
|
||||
validatePaths(variable.paths, variable, intro, variableExample, options);
|
||||
validatePaths(variable.paths, variable, intro, variableExample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateOptions(_options) {
|
||||
const options = {
|
||||
throwOnNonExistingPathToFiles: true,
|
||||
throwOnNonExistingRootPath: true,
|
||||
..._options,
|
||||
};
|
||||
if (options.throwOnNonExistingRootPath) {
|
||||
if (!options.rootPath) {
|
||||
throw new Error(
|
||||
`babel-plugin-extend-docs: You need to provide a rootPath option (string)\nExample: rootPath: path.resolve('.')`,
|
||||
);
|
||||
}
|
||||
if (!fs.existsSync(options.rootPath)) {
|
||||
throw new Error(
|
||||
`babel-plugin-extend-docs: The provided rootPath "${options.rootPath}" does not exist.`,
|
||||
);
|
||||
}
|
||||
if (!fs.lstatSync(options.rootPath).isDirectory()) {
|
||||
throw new Error(
|
||||
`babel-plugin-extend-docs: The provided rootPath "${options.rootPath}" is not a directory.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
validateChanges(options.changes, {
|
||||
throwOnNonExistingPathToFiles: options.throwOnNonExistingPathToFiles,
|
||||
rootPath: options.rootPath,
|
||||
});
|
||||
validateChanges(options.changes);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
|||
|
|
@ -4,64 +4,47 @@ const { executeBabel, baseConfig } = require('./helpers.js');
|
|||
|
||||
const testConfig = {
|
||||
...baseConfig,
|
||||
throwOnNonExistingPathToFiles: false,
|
||||
throwOnNonExistingRootPath: false,
|
||||
__filePath: '/node_module/@lion/input/README.md',
|
||||
};
|
||||
|
||||
describe('babel-plugin-extend-docs', () => {
|
||||
it('replaces local src class imports (1)', () => {
|
||||
const code = `import { LionInput } from './src/LionInput.js';`;
|
||||
const output = `import { WolfInput } from "../../../index.js";`;
|
||||
it('replaces src class imports (1)', () => {
|
||||
const code = `import { LionInput } from '@lion/input';`;
|
||||
const output = `import { WolfInput } from "wolf-web/input";`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('renames classes everywhere', () => {
|
||||
const code = [
|
||||
`import { LionInput } from './src/LionInput.js';`,
|
||||
`import { LionInput } from '@lion/input';`,
|
||||
`class Foo extends LionInput {}`,
|
||||
].join('\n');
|
||||
const output = [
|
||||
`import { WolfInput } from "../../../index.js";`,
|
||||
`import { WolfInput } from "wolf-web/input";`,
|
||||
'',
|
||||
`class Foo extends WolfInput {}`,
|
||||
].join('\n');
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces local src class imports (2)', () => {
|
||||
const code = `import { LionInput } from './src/LionInput.js';`;
|
||||
const output = `import { WolfInput } from "../../../../index.js";`;
|
||||
const config = {
|
||||
...testConfig,
|
||||
__filePath: '/node_module/@lion/input/docs/README.md',
|
||||
};
|
||||
expect(executeBabel(code, config)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces local src class imports (3)', () => {
|
||||
const code = `import { LionInput as Foo } from './src/LionInput.js';`;
|
||||
const output = `import { WolfInput as Foo } from "../../../index.js";`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces local src class imports (4)', () => {
|
||||
it('replaces src class imports (2)', () => {
|
||||
const code = [
|
||||
`import someDefaultHelper, { LionInput, someHelper } from './src/LionInput.js';`,
|
||||
`import someDefaultHelper, { LionInput, someHelper } from '@lion/input';`,
|
||||
`import { LionButton } from '@lion/button';`,
|
||||
].join('\n');
|
||||
const output = [
|
||||
`import someDefaultHelper, { someHelper } from "./src/LionInput.js";`,
|
||||
`import { WolfInput, WolfButton } from "../../../index.js";`,
|
||||
`import someDefaultHelper, { someHelper } from "@lion/input";`,
|
||||
`import { WolfInput } from "wolf-web/input";`,
|
||||
`import { WolfButton } from "wolf-web/button";`,
|
||||
].join('\n');
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces local src class imports (5)', () => {
|
||||
it('replaces src class imports (3)', () => {
|
||||
const code = `import { LionInput, LionFoo, LionBar, someHelper } from '@lion/input';`;
|
||||
const output = [
|
||||
`import { WolfInput, WolfFoo } from "../../../index.js";`,
|
||||
`import { WolfBar } from "../../../somewhere-else.js";`,
|
||||
`import { WolfInput } from "wolf-web/input";`,
|
||||
`import { WolfFoo } from "./index.js";`,
|
||||
`import { WolfBar } from "./somewhere-else.js";`,
|
||||
`import { someHelper } from "@lion/input";`,
|
||||
].join('\n');
|
||||
const config = {
|
||||
|
|
@ -95,7 +78,6 @@ describe('babel-plugin-extend-docs', () => {
|
|||
},
|
||||
},
|
||||
],
|
||||
__filePath: '/node_module/@lion/input/README.md',
|
||||
};
|
||||
expect(executeBabel(code, config)).to.equal(output);
|
||||
});
|
||||
|
|
@ -106,91 +88,27 @@ describe('babel-plugin-extend-docs', () => {
|
|||
import { LionInput } from '@lion/input';
|
||||
`;
|
||||
const output = [
|
||||
`import { localize } from "../../../localize.js";`,
|
||||
`import { WolfInput } from "../../../index.js";`,
|
||||
`import { localize } from "wolf-web/localize";`,
|
||||
`import { WolfInput } from "wolf-web/input";`,
|
||||
].join('\n');
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('allows separate import paths of managed imports', () => {
|
||||
const code1 = `import { LionInput } from '@lion/input';`;
|
||||
const code2 = `import { LionInput } from './src/LionInput.js';`;
|
||||
const output1 = `import { WolfInput } from "../../../index.js";`;
|
||||
const output2 = `import { WolfInput } from "../../../packages/input/src/WolfInput.js";`;
|
||||
const config = {
|
||||
...testConfig,
|
||||
changes: [
|
||||
{
|
||||
description: 'LionInput',
|
||||
variable: {
|
||||
from: 'LionInput',
|
||||
to: 'WolfInput',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/input',
|
||||
to: './index.js',
|
||||
},
|
||||
{
|
||||
from: './src/LionInput.js',
|
||||
to: './packages/input/src/WolfInput.js',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
__filePath: '/node_module/@lion/input/README.md',
|
||||
};
|
||||
expect(executeBabel(code1, config)).to.equal(output1);
|
||||
expect(executeBabel(code2, config)).to.equal(output2);
|
||||
});
|
||||
|
||||
it('replaces local index.js class imports (1)', () => {
|
||||
const code = `import { LionInput } from './index.js';`;
|
||||
const output = `import { WolfInput } from "../../../index.js";`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces local index.js class imports (2)', () => {
|
||||
const code = `import { LionInput } from './index.js';`;
|
||||
const output = `import { WolfInput } from "../../../../index.js";`;
|
||||
const config = {
|
||||
...testConfig,
|
||||
__filePath: '/node_module/@lion/input/docs/README.md',
|
||||
};
|
||||
expect(executeBabel(code, config)).to.equal(output);
|
||||
});
|
||||
|
||||
it('works with local index.js class imports with an empty relative path', () => {
|
||||
const code = `import { LionInput } from './index.js';`;
|
||||
const output = `import { WolfInput } from "./index.js";`;
|
||||
const config = {
|
||||
...testConfig,
|
||||
__filePath: './README.md',
|
||||
};
|
||||
expect(executeBabel(code, config)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces `@lion` class imports', () => {
|
||||
const code = `import { LionInput } from '@lion/input';`;
|
||||
const output = `import { WolfInput } from "../../../index.js";`;
|
||||
const output = `import { WolfInput } from "wolf-web/input";`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('does NOT replace imports no in the config', () => {
|
||||
const code = `import { FooInput } from '@lion/input';`;
|
||||
const output = `import { FooInput } from "@lion/input";`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces local tag imports', () => {
|
||||
const code = `import './lion-input.js';`;
|
||||
const output = `import "../../../__element-definitions/wolf-input.js";`;
|
||||
it('does NOT replace imports not in the config', () => {
|
||||
const code = `import { FooInput } from '@lion/calendar';`;
|
||||
const output = `import { FooInput } from "@lion/calendar";`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
it('replaces `@lion` tag imports', () => {
|
||||
const code = `import '@lion/input/define';`;
|
||||
const output = `import "../../../__element-definitions/wolf-input.js";`;
|
||||
const output = `import "#input/define";`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
});
|
||||
|
||||
|
|
@ -346,7 +264,7 @@ describe('babel-plugin-extend-docs', () => {
|
|||
const code = `import * as all from '@lion/input';`;
|
||||
const output = `
|
||||
import { notRenameHelper } from "@lion/input";
|
||||
import { WolfInput } from "../../../index.js";
|
||||
import { WolfInput } from "wolf-web/input";
|
||||
const all = { LionInput: WolfInput, someHelper };
|
||||
`;
|
||||
expect(executeBabel(code, testConfig)).to.equal(output);
|
||||
|
|
|
|||
|
|
@ -17,17 +17,9 @@ const baseConfig = {
|
|||
from: 'LionInput',
|
||||
to: 'WolfInput',
|
||||
paths: [
|
||||
{
|
||||
from: './index.js',
|
||||
to: './index.js',
|
||||
},
|
||||
{
|
||||
from: './src/LionInput.js',
|
||||
to: './index.js',
|
||||
},
|
||||
{
|
||||
from: '@lion/input',
|
||||
to: './index.js',
|
||||
to: 'wolf-web/input',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -35,13 +27,9 @@ const baseConfig = {
|
|||
from: 'lion-input',
|
||||
to: 'wolf-input',
|
||||
paths: [
|
||||
{
|
||||
from: './lion-input.js',
|
||||
to: './__element-definitions/wolf-input.js',
|
||||
},
|
||||
{
|
||||
from: '@lion/input/define',
|
||||
to: './__element-definitions/wolf-input.js',
|
||||
to: '#input/define',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -52,17 +40,9 @@ const baseConfig = {
|
|||
from: 'LionButton',
|
||||
to: 'WolfButton',
|
||||
paths: [
|
||||
{
|
||||
from: './index.js',
|
||||
to: './index.js',
|
||||
},
|
||||
{
|
||||
from: './src/LionButton.js',
|
||||
to: './index.js',
|
||||
},
|
||||
{
|
||||
from: '@lion/button',
|
||||
to: './index.js',
|
||||
to: 'wolf-web/button',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -70,13 +50,9 @@ const baseConfig = {
|
|||
from: 'lion-button',
|
||||
to: 'wolf-button',
|
||||
paths: [
|
||||
{
|
||||
from: './lion-button.js',
|
||||
to: './__element-definitions/wolf-button.js',
|
||||
},
|
||||
{
|
||||
from: '@lion/button/define',
|
||||
to: './__element-definitions/wolf-button.js',
|
||||
to: '#button/define',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -87,17 +63,9 @@ const baseConfig = {
|
|||
from: 'LionCheckbox',
|
||||
to: 'WolfCheckbox',
|
||||
paths: [
|
||||
{
|
||||
from: './index.js',
|
||||
to: './index.js',
|
||||
},
|
||||
{
|
||||
from: './src/LionCheckbox.js',
|
||||
to: './index.js',
|
||||
},
|
||||
{
|
||||
from: '@lion/checkbox-group',
|
||||
to: './index.js',
|
||||
to: 'wolf-web/checkbox-group',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -106,12 +74,8 @@ const baseConfig = {
|
|||
to: 'wolf-checkbox',
|
||||
paths: [
|
||||
{
|
||||
from: './lion-checkbox.js',
|
||||
to: './__element-definitions/wolf-checkbox.js',
|
||||
},
|
||||
{
|
||||
from: '@lion/checkbox-group/lion-checkbox.js',
|
||||
to: './__element-definitions/wolf-checkbox.js',
|
||||
from: '@lion/checkbox-group/define',
|
||||
to: '#checkbox-group/define',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -122,17 +86,9 @@ const baseConfig = {
|
|||
from: 'localize',
|
||||
to: 'localize',
|
||||
paths: [
|
||||
{
|
||||
from: './index.js',
|
||||
to: './localize.js',
|
||||
},
|
||||
{
|
||||
from: './src/localize.js',
|
||||
to: './localize.js',
|
||||
},
|
||||
{
|
||||
from: '@lion/localize',
|
||||
to: './localize.js',
|
||||
to: 'wolf-web/localize',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
const { expect } = require('chai');
|
||||
const path = require('path');
|
||||
const { executeBabel } = require('./helpers.js');
|
||||
|
||||
const extendDocsConfig = {
|
||||
|
|
@ -9,27 +8,22 @@ const extendDocsConfig = {
|
|||
variable: {
|
||||
from: 'MyCounter',
|
||||
to: 'MyExtension',
|
||||
paths: [
|
||||
{ from: './index.js', to: './my-extension/index.js' },
|
||||
{ from: './src/MyCounter.js', to: './my-extension/index.js' },
|
||||
],
|
||||
paths: [{ from: 'source/counter', to: 'extension/counter' }],
|
||||
},
|
||||
tag: {
|
||||
from: 'my-counter',
|
||||
to: 'my-extension',
|
||||
paths: [{ from: './my-counter.js', to: './my-extension/my-extension.js' }],
|
||||
paths: [{ from: 'source/counter/define', to: '#counter/define' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
rootPath: path.resolve('./demo'),
|
||||
__filePath: '/my-app.demo.js',
|
||||
};
|
||||
|
||||
describe('babel-plugin-extend-docs: integration tests', () => {
|
||||
it('works for the demo', () => {
|
||||
const code = `import { LitElement, html } from '@lion/core';
|
||||
import { MyCounter } from './src/MyCounter.js';
|
||||
import './my-counter.js';
|
||||
import { MyCounter } from 'source/counter';
|
||||
import 'source/counter/define';
|
||||
|
||||
class TenCounter extends MyCounter {
|
||||
inc() {
|
||||
|
|
@ -53,8 +47,8 @@ class MyApp extends LitElement {
|
|||
customElements.define('my-app', MyApp);
|
||||
`;
|
||||
const output = `import { LitElement, html } from "@lion/core";
|
||||
import { MyExtension } from "./my-extension/index.js";
|
||||
import "./my-extension/my-extension.js";
|
||||
import { MyExtension } from "extension/counter";
|
||||
import "#counter/define";
|
||||
|
||||
class TenCounter extends MyExtension {
|
||||
inc() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
const { expect } = require('chai');
|
||||
const path = require('path');
|
||||
const { executeBabel, baseConfig } = require('./helpers.js');
|
||||
const { executeBabel } = require('./helpers.js');
|
||||
|
||||
function formatJsonErrorMessage(json) {
|
||||
if (!json) {
|
||||
|
|
@ -10,30 +10,6 @@ function formatJsonErrorMessage(json) {
|
|||
}
|
||||
|
||||
describe('babel-plugin-extend-docs: validateOptions', () => {
|
||||
it('throws if no rootPath string is provided', () => {
|
||||
expect(() => executeBabel('', { ...baseConfig })).to.throw(
|
||||
`babel-plugin-extend-docs: You need to provide a rootPath option (string)\nExample: rootPath: path.resolve('.')`,
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if rootPath does not exist', () => {
|
||||
expect(() => executeBabel('', { ...baseConfig, rootPath: 'something' })).to.throw(
|
||||
`babel-plugin-extend-docs: The provided rootPath "something" does not exist.`,
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if rootPath is not a directory', () => {
|
||||
const rootPath = path.resolve('./index.js');
|
||||
expect(() => {
|
||||
executeBabel('', {
|
||||
...baseConfig,
|
||||
rootPath,
|
||||
});
|
||||
}).to.throw(
|
||||
`babel-plugin-extend-docs: The provided rootPath "${rootPath}" is not a directory.`,
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if no changes array is provided', () => {
|
||||
expect(() => {
|
||||
executeBabel('', {
|
||||
|
|
@ -45,12 +21,12 @@ describe('babel-plugin-extend-docs: validateOptions', () => {
|
|||
`Given: ${formatJsonErrorMessage(undefined)}`,
|
||||
'Should be example:',
|
||||
' {',
|
||||
" from: 'my-counter',",
|
||||
" to: 'my-extension',",
|
||||
" from: 'source-counter',",
|
||||
" to: 'extension-counter',",
|
||||
' paths: [',
|
||||
' {',
|
||||
" from: './my-counter.js',",
|
||||
" to: './my-extension/my-extension.js'",
|
||||
" from: '@source/counter/define',",
|
||||
" to: 'extension/counter/define'",
|
||||
' }',
|
||||
' ]',
|
||||
' }',
|
||||
|
|
@ -72,12 +48,12 @@ describe('babel-plugin-extend-docs: validateOptions', () => {
|
|||
`Given: ${formatJsonErrorMessage(tag)}`,
|
||||
'Should be example:',
|
||||
' {',
|
||||
" from: 'my-counter',",
|
||||
" to: 'my-extension',",
|
||||
" from: 'source-counter',",
|
||||
" to: 'extension-counter',",
|
||||
' paths: [',
|
||||
' {',
|
||||
" from: './my-counter.js',",
|
||||
" to: './my-extension/my-extension.js'",
|
||||
" from: '@source/counter/define',",
|
||||
" to: 'extension/counter/define'",
|
||||
' }',
|
||||
' ]',
|
||||
' }',
|
||||
|
|
@ -126,12 +102,12 @@ describe('babel-plugin-extend-docs: validateOptions', () => {
|
|||
`Given: ${formatJsonErrorMessage(variable)}`,
|
||||
'Should be example:',
|
||||
' {',
|
||||
" from: 'MyCounter',",
|
||||
" to: 'MyExtension',",
|
||||
" from: 'SourceCounter',",
|
||||
" to: 'ExtensionCounter',",
|
||||
' paths: [',
|
||||
' {',
|
||||
" from: './index.js',",
|
||||
" to: './my-extension/index.js'",
|
||||
" from: '@source/counter',",
|
||||
" to: 'extension/counter'",
|
||||
' }',
|
||||
' ]',
|
||||
' }',
|
||||
|
|
@ -166,33 +142,6 @@ describe('babel-plugin-extend-docs: validateOptions', () => {
|
|||
variableThrowsErrorFor({ ...pathSetup, paths: [{ from: '', to: './index.js' }] }, pathMsg);
|
||||
});
|
||||
|
||||
it('throws if "to path" could not be found on file system', () => {
|
||||
expect(() => {
|
||||
executeBabel('', {
|
||||
changes: [
|
||||
{
|
||||
tag: {
|
||||
from: 'lion-input',
|
||||
to: 'wolf-input',
|
||||
paths: [
|
||||
{
|
||||
from: './lion-input.js',
|
||||
to: './non-existing/wolf-input.js',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
rootPath: path.resolve('./'),
|
||||
});
|
||||
}).to.throw(
|
||||
[
|
||||
'babel-plugin-extend-docs: Rewriting import from "./lion-input.js" to "./non-existing/wolf-input.js" but we ',
|
||||
`could not find a file at "${path.resolve('./')}/non-existing/wolf-input.js".`,
|
||||
].join(''),
|
||||
);
|
||||
});
|
||||
|
||||
it('does NOT throws if "to path" could be found on file system', () => {
|
||||
expect(() => {
|
||||
executeBabel('', {
|
||||
|
|
|
|||
3
packages-node/rocket-preset-extend-lion-docs/README.md
Normal file
3
packages-node/rocket-preset-extend-lion-docs/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Rocket Preset Extend Lion Docs
|
||||
|
||||
[=> See Source <=](../../docs/docs/node-tools/rocket-preset-extend-lion-docs/overview.md)
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Rocket Preset Extend Lion Docs
|
||||
|
||||
[=> See Source <=](../../docs/docs/node-tools/rocket-preset-extend-lion-docs/overview.md)
|
||||
1
packages-node/rocket-preset-extend-lion-docs/index.js
Normal file
1
packages-node/rocket-preset-extend-lion-docs/index.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { extendLionDocs } from './preset/extendLionDocs.js';
|
||||
47
packages-node/rocket-preset-extend-lion-docs/package.json
Normal file
47
packages-node/rocket-preset-extend-lion-docs/package.json
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"name": "rocket-preset-extend-lion-docs",
|
||||
"version": "0.0.0",
|
||||
"description": "A rocket preset to reuse lion documentation inside your design system extension",
|
||||
"license": "MIT",
|
||||
"author": "ing-bank",
|
||||
"homepage": "https://github.com/ing-bank/lion/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ing-bank/lion.git",
|
||||
"directory": "packages-node/rocket-preset-extend-lion-docs"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"*.js",
|
||||
"docs",
|
||||
"preset",
|
||||
"src",
|
||||
"test"
|
||||
],
|
||||
"scripts": {
|
||||
"publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../",
|
||||
"prepublishOnly": "npm run publish-docs",
|
||||
"test": "npm run test:node",
|
||||
"test:node": "mocha test-node",
|
||||
"test:watch": "mocha test-node --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.10.1",
|
||||
"es-module-lexer": "^0.3.6",
|
||||
"plugins-manager": "^0.2.1",
|
||||
"remark-extend": "0.4.2",
|
||||
"unist-util-visit": "^2.0.2"
|
||||
},
|
||||
"keywords": [
|
||||
"docs",
|
||||
"lion",
|
||||
"rocket"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"exports": {
|
||||
".": "./index.js"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import { addPlugin } from 'plugins-manager';
|
||||
// @ts-ignore
|
||||
import remarkExtendPkg from 'remark-extend';
|
||||
import { remarkExtendLionDocsTransformJs } from '../src/remarkExtendLionDocsTransformJs.js';
|
||||
import { remarkUrlToLocal } from '../src/remarkUrlToLocal.js';
|
||||
import { generateExtendDocsConfig } from '../src/generateExtendDocsConfig.js';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {string} [opts.rootDir]
|
||||
* @param {string} [opts.nodeModulesDir]
|
||||
* @param {string} opts.classPrefix
|
||||
* @param {string} opts.classBareImport
|
||||
* @param {string} opts.tagPrefix
|
||||
* @param {string} opts.tagBareImport
|
||||
* @returns
|
||||
*/
|
||||
export async function extendLionDocs({
|
||||
rootDir,
|
||||
nodeModulesDir,
|
||||
classPrefix,
|
||||
classBareImport,
|
||||
tagPrefix,
|
||||
tagBareImport,
|
||||
}) {
|
||||
const changes = await generateExtendDocsConfig({
|
||||
nodeModulesDir,
|
||||
classPrefix,
|
||||
classBareImport,
|
||||
tagPrefix,
|
||||
tagBareImport,
|
||||
});
|
||||
const extendDocsConfig = {
|
||||
changes,
|
||||
};
|
||||
|
||||
const _rootDir = rootDir || path.resolve('.');
|
||||
|
||||
return {
|
||||
path: path.resolve(__dirname),
|
||||
setupUnifiedPlugins: [
|
||||
addPlugin({
|
||||
name: 'remark-extend',
|
||||
plugin: remarkExtendPkg.remarkExtend,
|
||||
location: 'markdown',
|
||||
}),
|
||||
addPlugin({
|
||||
name: 'github-urls-to-local',
|
||||
plugin: remarkUrlToLocal,
|
||||
location: 'remark-extend',
|
||||
options: {
|
||||
gitHubUrl: 'https://github.com/ing-bank/lion/',
|
||||
rootDir: _rootDir,
|
||||
},
|
||||
}),
|
||||
addPlugin({
|
||||
name: 'remark-extend-lion-docs-transform-js',
|
||||
plugin: remarkExtendLionDocsTransformJs,
|
||||
location: 'remark-extend',
|
||||
options: { extendDocsConfig },
|
||||
}),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
// @ts-ignore
|
||||
import { init, parse } from 'es-module-lexer/dist/lexer.js';
|
||||
|
||||
/**
|
||||
* @param {string} src
|
||||
* @returns
|
||||
*/
|
||||
function getImportNames(src) {
|
||||
const [imports] = parse(src);
|
||||
|
||||
/** @type {string[]} */
|
||||
const names = [];
|
||||
for (const importObj of imports) {
|
||||
const full = src.substring(importObj.ss, importObj.se);
|
||||
if (full.includes('{')) {
|
||||
const namesString = full.substring(full.indexOf('{') + 1, full.indexOf('}'));
|
||||
namesString.split(',').forEach(name => {
|
||||
names.push(name.trim());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {string} opts.className
|
||||
* @param {string} opts.pkgName
|
||||
* @param {string} opts.classPrefix
|
||||
* @param {string} opts.classBareImport
|
||||
* @param {string} [opts.sourceClassPrefix]
|
||||
* @param {string} [opts.sourceBareImport]
|
||||
* @returns
|
||||
*/
|
||||
function generateVariableChange({
|
||||
className,
|
||||
pkgName,
|
||||
|
||||
classPrefix,
|
||||
classBareImport,
|
||||
sourceClassPrefix = 'Lion',
|
||||
sourceBareImport = '@lion/',
|
||||
}) {
|
||||
const pureClassName = className.replace(sourceClassPrefix, '');
|
||||
const purePkgName = pkgName.replace(sourceBareImport, '');
|
||||
|
||||
return {
|
||||
name: `${pkgName} - ${className}`,
|
||||
variable: {
|
||||
from: `${sourceClassPrefix}${pureClassName}`,
|
||||
to: `${classPrefix}${pureClassName}`,
|
||||
paths: [
|
||||
{
|
||||
from: `${sourceBareImport}${purePkgName}`,
|
||||
to: `${classBareImport}${purePkgName}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {string} opts.tagName
|
||||
* @param {string} opts.pkgName
|
||||
* @param {string} opts.definePath
|
||||
* @param {string} opts.tagPrefix
|
||||
* @param {string} opts.tagBareImport
|
||||
* @param {string} [opts.sourceTagPrefix]
|
||||
* @param {string} [opts.sourceBareImport]
|
||||
* @returns
|
||||
*/
|
||||
function generateTagChange({
|
||||
tagName,
|
||||
pkgName,
|
||||
definePath,
|
||||
|
||||
tagPrefix,
|
||||
tagBareImport,
|
||||
sourceTagPrefix = 'lion-',
|
||||
sourceBareImport = '@lion/',
|
||||
}) {
|
||||
const pureTagName = tagName.replace(sourceTagPrefix, '');
|
||||
const purePkgName = pkgName.replace(sourceBareImport, '');
|
||||
|
||||
return {
|
||||
name: `${pkgName}${definePath}`,
|
||||
tag: {
|
||||
from: `${sourceTagPrefix}${pureTagName}`,
|
||||
to: `${tagPrefix}${pureTagName}`,
|
||||
paths: [
|
||||
{
|
||||
from: `${sourceBareImport}${purePkgName}${definePath}`,
|
||||
to: `${tagBareImport}${purePkgName}${definePath}`,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {string} [opts.nodeModulesDir]
|
||||
* @param {string} [opts.npmScope]
|
||||
* @param {string} opts.classPrefix
|
||||
* @param {string} opts.classBareImport
|
||||
* @param {string} opts.tagPrefix
|
||||
* @param {string} opts.tagBareImport
|
||||
* @returns
|
||||
*/
|
||||
export async function generateExtendDocsConfig({
|
||||
nodeModulesDir,
|
||||
npmScope = '@lion',
|
||||
classPrefix,
|
||||
classBareImport,
|
||||
tagPrefix,
|
||||
tagBareImport,
|
||||
}) {
|
||||
const _nodeModulesDir = nodeModulesDir || path.resolve('./node_modules');
|
||||
await init;
|
||||
const options = { classPrefix, classBareImport, tagPrefix, tagBareImport };
|
||||
|
||||
const folderToCheck = path.join(_nodeModulesDir, npmScope);
|
||||
const packages = fs
|
||||
.readdirSync(folderToCheck)
|
||||
.filter(dir => fs.statSync(path.join(folderToCheck, dir)).isDirectory())
|
||||
.map(dir => `${npmScope}/${dir}`);
|
||||
|
||||
const changes = [];
|
||||
for (const pkgName of packages) {
|
||||
const pkgPath = path.join(_nodeModulesDir, ...pkgName.split('/'));
|
||||
const pkgJsonPath = path.join(pkgPath, 'package.json');
|
||||
const pkgJsonString = await fs.promises.readFile(pkgJsonPath, 'utf8');
|
||||
const pkgJson = JSON.parse(pkgJsonString);
|
||||
const pkgExports = pkgJson.exports;
|
||||
|
||||
for (const pkgExportName of Object.keys(pkgExports)) {
|
||||
const pkgExportPath = pkgExports[pkgExportName];
|
||||
const entryPointFilePath = path.join(pkgPath, pkgExportPath);
|
||||
|
||||
if (pkgExportName === '.') {
|
||||
const src = await fs.promises.readFile(entryPointFilePath, 'utf8');
|
||||
const importNames = getImportNames(src);
|
||||
|
||||
for (const importName of importNames) {
|
||||
changes.push(generateVariableChange({ className: importName, pkgName, ...options }));
|
||||
}
|
||||
}
|
||||
if (pkgExportName.startsWith('./define')) {
|
||||
const src = await fs.promises.readFile(entryPointFilePath, 'utf8');
|
||||
const definePath = `/${pkgExportName.substr(2)}`;
|
||||
if (src.includes('.define(')) {
|
||||
const matches = src.match(/define\(['"](.*)['"]/);
|
||||
if (matches && matches[1]) {
|
||||
const tagName = matches[1];
|
||||
changes.push(generateTagChange({ tagName, pkgName, definePath, ...options }));
|
||||
}
|
||||
} else {
|
||||
changes.push(
|
||||
generateTagChange({ tagName: 'xxx-workaround-xxx', pkgName, definePath, ...options }),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import babelPkg from '@babel/core';
|
||||
import visit from 'unist-util-visit';
|
||||
|
||||
const { transformSync } = babelPkg;
|
||||
|
||||
/** @typedef {import('vfile').VFileOptions} VFileOptions */
|
||||
/** @typedef {import('unist').Node} Node */
|
||||
|
||||
/**
|
||||
* @typedef {Object} CodeProperties
|
||||
* @property {string} [value]
|
||||
* @property {string} [lang]
|
||||
* @property {string} [meta]
|
||||
*/
|
||||
|
||||
/** @typedef {Node & CodeProperties} CodeNode */
|
||||
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {object} opts.extendDocsConfig
|
||||
* @returns
|
||||
*/
|
||||
export function remarkExtendLionDocsTransformJs({ extendDocsConfig }) {
|
||||
/**
|
||||
* @param {CodeNode} node
|
||||
*/
|
||||
const visitor = node => {
|
||||
if (
|
||||
node.type === 'code' &&
|
||||
node.lang === 'js' &&
|
||||
(node.meta === 'story' || node.meta === 'preview-story' || node.meta === 'script') &&
|
||||
node.value
|
||||
) {
|
||||
const processed = transformSync(node.value, {
|
||||
plugins: [['babel-plugin-extend-docs', extendDocsConfig]],
|
||||
});
|
||||
if (processed && processed.code) {
|
||||
node.value = processed.code;
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Node} tree
|
||||
*/
|
||||
function transformer(tree) {
|
||||
// @ts-ignore
|
||||
visit(tree, visitor);
|
||||
return tree;
|
||||
}
|
||||
|
||||
return transformer;
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
import path from 'path';
|
||||
import visit from 'unist-util-visit';
|
||||
|
||||
/** @typedef {import('vfile').VFileOptions} VFileOptions */
|
||||
/** @typedef {import('unist').Node} Node */
|
||||
|
||||
/**
|
||||
* @typedef {Object} UrlProperty
|
||||
* @property {string} url
|
||||
*/
|
||||
|
||||
/** @typedef {Node & UrlProperty} UrlNode */
|
||||
|
||||
/**
|
||||
* @param {object} opts
|
||||
* @param {string} opts.gitHubUrl
|
||||
* @param {object} opts.page
|
||||
* @param {string} opts.page.inputPath
|
||||
* @param {string} opts.rootDir
|
||||
* @returns
|
||||
*/
|
||||
export function remarkUrlToLocal({ gitHubUrl, page, rootDir }) {
|
||||
/**
|
||||
* @param {UrlNode} node
|
||||
*/
|
||||
const visitor = node => {
|
||||
if (node.type === 'link' || node.type === 'image') {
|
||||
if (node.url.startsWith(gitHubUrl)) {
|
||||
const urlPart = node.url.substring(gitHubUrl.length);
|
||||
const urlParts = urlPart.split('/');
|
||||
|
||||
if (urlParts[0] === 'blob') {
|
||||
urlParts.shift();
|
||||
urlParts.shift();
|
||||
const fullUrlPath = path.join(rootDir, urlParts.join('/'));
|
||||
const fullInputPath =
|
||||
page.inputPath[0] === '/' ? page.inputPath : path.join(rootDir, page.inputPath);
|
||||
const newPath = path.relative(path.dirname(fullInputPath), fullUrlPath);
|
||||
node.url = newPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Node} tree
|
||||
*/
|
||||
function transformer(tree) {
|
||||
// @ts-ignore
|
||||
visit(tree, visitor);
|
||||
return tree;
|
||||
}
|
||||
|
||||
return transformer;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { LionAccordion } from './src/LionAccordion.js';
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { LionAccordion } from './src/LionAccordion.js';
|
||||
|
||||
customElements.define('lion-accordion', LionAccordion);
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"name": "@lion/accordion",
|
||||
"version": "0.5.0",
|
||||
"description": "Vertically stacked list of invokers that can be clicked to reveal or hide content associated with them.",
|
||||
"license": "MIT",
|
||||
"author": "ing-bank",
|
||||
"homepage": "https://github.com/ing-bank/lion/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ing-bank/lion.git",
|
||||
"directory": "packages/accordion"
|
||||
},
|
||||
"main": "index.js",
|
||||
"module": "index.js",
|
||||
"files": [
|
||||
"*.d.ts",
|
||||
"*.js",
|
||||
"custom-elements.json",
|
||||
"docs",
|
||||
"src",
|
||||
"test",
|
||||
"test-helpers",
|
||||
"translations",
|
||||
"types"
|
||||
],
|
||||
"scripts": {
|
||||
"custom-elements-manifest": "custom-elements-manifest analyze --litelement --exclude \"docs/**/*\" \"test-helpers/**/*\"",
|
||||
"debug": "cd ../../ && npm run debug -- --group accordion",
|
||||
"debug:firefox": "cd ../../ && npm run debug:firefox -- --group accordion",
|
||||
"debug:webkit": "cd ../../ && npm run debug:webkit -- --group accordion",
|
||||
"publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../",
|
||||
"prepublishOnly": "npm run publish-docs && npm run custom-elements-manifest",
|
||||
"test": "cd ../../ && npm run test:browser -- --group accordion"
|
||||
},
|
||||
"sideEffects": [
|
||||
"lion-accordion.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@lion/core": "0.17.0"
|
||||
},
|
||||
"keywords": [
|
||||
"accordion",
|
||||
"lion",
|
||||
"web-components"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"customElementsManifest": "custom-elements.json",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./define": "./lion-accordion.js",
|
||||
"./docs/": "./docs/"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export class LionAccordion extends HTMLElement {}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import '@lion/checkbox-group/define-checkbox';
|
||||
import '@lion/checkbox-group/define-checkbox-group';
|
||||
import '@lion/checkbox-group/define-checkbox-indeterminate';
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export { LionCheckboxGroup } from './src/LionCheckboxGroup.js';
|
||||
export { LionCheckboxIndeterminate } from './src/LionCheckboxIndeterminate.js';
|
||||
export { LionCheckbox } from './src/LionCheckbox.js';
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { LionCheckboxGroup } from './src/LionCheckboxGroup.js';
|
||||
|
||||
customElements.define('lion-checkbox-group', LionCheckboxGroup);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { LionCheckboxIndeterminate } from './src/LionCheckboxIndeterminate.js';
|
||||
|
||||
customElements.define('lion-checkbox-indeterminate', LionCheckboxIndeterminate);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import { LionCheckbox } from './src/LionCheckbox.js';
|
||||
|
||||
customElements.define('lion-checkbox', LionCheckbox);
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"name": "@lion/checkbox-group",
|
||||
"version": "0.17.0",
|
||||
"description": "A container for multiple checkboxes",
|
||||
"license": "MIT",
|
||||
"author": "ing-bank",
|
||||
"homepage": "https://github.com/ing-bank/lion/",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ing-bank/lion.git",
|
||||
"directory": "packages/checkbox-group"
|
||||
},
|
||||
"main": "index.js",
|
||||
"module": "index.js",
|
||||
"files": [
|
||||
"*.d.ts",
|
||||
"*.js",
|
||||
"custom-elements.json",
|
||||
"docs",
|
||||
"src",
|
||||
"test",
|
||||
"test-helpers",
|
||||
"translations",
|
||||
"types"
|
||||
],
|
||||
"scripts": {
|
||||
"custom-elements-manifest": "custom-elements-manifest analyze --litelement --exclude \"docs/**/*\" \"test-helpers/**/*\"",
|
||||
"debug": "cd ../../ && npm run debug -- --group checkbox-group",
|
||||
"debug:firefox": "cd ../../ && npm run debug:firefox -- --group checkbox-group",
|
||||
"debug:webkit": "cd ../../ && npm run debug:webkit -- --group checkbox-group",
|
||||
"publish-docs": "node ../../packages-node/publish-docs/src/cli.js --github-url https://github.com/ing-bank/lion/ --git-root-dir ../../",
|
||||
"prepublishOnly": "npm run publish-docs && npm run custom-elements-manifest",
|
||||
"test": "cd ../../ && npm run test:browser -- --group checkbox-group"
|
||||
},
|
||||
"sideEffects": [
|
||||
"define.js",
|
||||
"lion-checkbox.js",
|
||||
"lion-checkbox-group.js",
|
||||
"lion-checkbox-indeterminate.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@lion/core": "0.17.0",
|
||||
"@lion/form-core": "0.12.0",
|
||||
"@lion/input": "0.14.0"
|
||||
},
|
||||
"keywords": [
|
||||
"checkbox-group",
|
||||
"lion",
|
||||
"web-components"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"customElementsManifest": "custom-elements.json",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./define-checkbox": "./lion-checkbox.js",
|
||||
"./define-checkbox-group": "./lion-checkbox-group.js",
|
||||
"./define-checkbox-indeterminate": "./lion-checkbox-indeterminate.js",
|
||||
"./define": "./define.js",
|
||||
"./docs/": "./docs/"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export class LionCheckbox extends HTMLElement {}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export class LionCheckboxGroup extends HTMLElement {}
|
||||
|
|
@ -0,0 +1 @@
|
|||
export class LionCheckboxIndeterminate extends HTMLElement {}
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import chai from 'chai';
|
||||
|
||||
import { generateExtendDocsConfig } from '../src/generateExtendDocsConfig.js';
|
||||
|
||||
const { expect } = chai;
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {object} [options]
|
||||
* @param {string} [options.nodeModulesDir]
|
||||
* @param {string} [options.npmScope]
|
||||
* @param {string} [options.classPrefix]
|
||||
* @param {string} [options.classBareImport]
|
||||
* @param {string} [options.tagPrefix]
|
||||
* @param {string} [options.tagBareImport]
|
||||
* @returns
|
||||
*/
|
||||
async function execute(input, options = {}) {
|
||||
const nodeModulesDir = path.join(__dirname, input);
|
||||
|
||||
const result = await generateExtendDocsConfig({
|
||||
// used tsc version does not recognize optional jsdoc params
|
||||
// @ts-ignore
|
||||
nodeModulesDir,
|
||||
// @ts-ignore
|
||||
classPrefix: 'Ing',
|
||||
// @ts-ignore
|
||||
classBareImport: 'ing-web/',
|
||||
// @ts-ignore
|
||||
tagPrefix: 'ing-',
|
||||
// @ts-ignore
|
||||
tagBareImport: '#',
|
||||
// @ts-ignore
|
||||
...options,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
describe('generateExtendDocsConfig', () => {
|
||||
it('works for packages with a single class and tag export', async () => {
|
||||
const result = await execute('fixtures/accordion');
|
||||
|
||||
expect(result).to.deep.equal([
|
||||
{
|
||||
name: '@lion/accordion - LionAccordion',
|
||||
variable: {
|
||||
from: 'LionAccordion',
|
||||
to: 'IngAccordion',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/accordion',
|
||||
to: 'ing-web/accordion',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/accordion/define',
|
||||
tag: {
|
||||
from: 'lion-accordion',
|
||||
to: 'ing-accordion',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/accordion/define',
|
||||
to: '#accordion/define',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('can customize the target', async () => {
|
||||
const result = await execute('fixtures/accordion', {
|
||||
classPrefix: 'Wolf',
|
||||
classBareImport: '@wolf-web/',
|
||||
tagPrefix: 'wolf-',
|
||||
tagBareImport: '@wolf-web/',
|
||||
});
|
||||
|
||||
expect(result).to.deep.equal([
|
||||
{
|
||||
name: '@lion/accordion - LionAccordion',
|
||||
variable: {
|
||||
from: 'LionAccordion',
|
||||
to: 'WolfAccordion',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/accordion',
|
||||
to: '@wolf-web/accordion',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/accordion/define',
|
||||
tag: {
|
||||
from: 'lion-accordion',
|
||||
to: 'wolf-accordion',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/accordion/define',
|
||||
to: '@wolf-web/accordion/define',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('works for packages with multiple class and tag exports', async () => {
|
||||
const result = await execute('fixtures/checkbox-group');
|
||||
|
||||
expect(result).to.deep.equal([
|
||||
{
|
||||
name: '@lion/checkbox-group - LionCheckboxGroup',
|
||||
variable: {
|
||||
from: 'LionCheckboxGroup',
|
||||
to: 'IngCheckboxGroup',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/checkbox-group',
|
||||
to: 'ing-web/checkbox-group',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/checkbox-group - LionCheckboxIndeterminate',
|
||||
variable: {
|
||||
from: 'LionCheckboxIndeterminate',
|
||||
to: 'IngCheckboxIndeterminate',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/checkbox-group',
|
||||
to: 'ing-web/checkbox-group',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/checkbox-group - LionCheckbox',
|
||||
variable: {
|
||||
from: 'LionCheckbox',
|
||||
to: 'IngCheckbox',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/checkbox-group',
|
||||
to: 'ing-web/checkbox-group',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/checkbox-group/define-checkbox',
|
||||
tag: {
|
||||
from: 'lion-checkbox',
|
||||
to: 'ing-checkbox',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/checkbox-group/define-checkbox',
|
||||
to: '#checkbox-group/define-checkbox',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/checkbox-group/define-checkbox-group',
|
||||
tag: {
|
||||
from: 'lion-checkbox-group',
|
||||
to: 'ing-checkbox-group',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/checkbox-group/define-checkbox-group',
|
||||
to: '#checkbox-group/define-checkbox-group',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/checkbox-group/define-checkbox-indeterminate',
|
||||
tag: {
|
||||
from: 'lion-checkbox-indeterminate',
|
||||
to: 'ing-checkbox-indeterminate',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/checkbox-group/define-checkbox-indeterminate',
|
||||
to: '#checkbox-group/define-checkbox-indeterminate',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/checkbox-group/define',
|
||||
tag: {
|
||||
from: 'lion-xxx-workaround-xxx',
|
||||
to: 'ing-xxx-workaround-xxx',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/checkbox-group/define',
|
||||
to: '#checkbox-group/define',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import chai from 'chai';
|
||||
import { mdjsProcess } from '@mdjs/core';
|
||||
import { addPlugin } from 'plugins-manager';
|
||||
|
||||
import { remarkExtendLionDocsTransformJs } from '../src/remarkExtendLionDocsTransformJs.js';
|
||||
|
||||
const { expect } = chai;
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
*/
|
||||
async function execute(input) {
|
||||
const rootDir = path.join(__dirname, '../../../');
|
||||
|
||||
const extendDocsConfig = {
|
||||
rootPath: rootDir,
|
||||
__filePath: 'fake',
|
||||
changes: [
|
||||
{
|
||||
name: '@lion/accordion - LionAccordion',
|
||||
variable: {
|
||||
from: 'LionAccordion',
|
||||
to: 'IngAccordion',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/accordion',
|
||||
to: 'ing-web/accordion',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '@lion/accordion/define',
|
||||
tag: {
|
||||
from: 'lion-accordion',
|
||||
to: 'ing-accordion',
|
||||
paths: [
|
||||
{
|
||||
from: '@lion/accordion/define',
|
||||
to: '#accordion/define',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
const result = await mdjsProcess(input, {
|
||||
setupUnifiedPlugins: [
|
||||
addPlugin({
|
||||
name: 'remark-extend-lion-docs-transform-js',
|
||||
plugin: remarkExtendLionDocsTransformJs,
|
||||
location: 'markdown',
|
||||
options: { extendDocsConfig },
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
describe('remarkExtendLionDocsTransformJs', () => {
|
||||
it('processes all instance of code and code snippets', async () => {
|
||||
const result = await execute(
|
||||
[
|
||||
'',
|
||||
'```js script',
|
||||
"import { html } from '@lion/core';",
|
||||
"import '@lion/accordion/define';",
|
||||
'```',
|
||||
'',
|
||||
'```js preview-story',
|
||||
'export const main = () => html`',
|
||||
' <lion-accordion></lion-accordion>',
|
||||
'`;',
|
||||
'```',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
expect(result.html).to.include('ing-accordion');
|
||||
expect(result.html).to.equal(
|
||||
[
|
||||
'<mdjs-preview mdjs-story-name="main">',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'<pre class="language-js"><code class="language-js"><span class="token keyword module">export</span> <span class="token keyword">const</span> <span class="token function-variable function">main</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token arrow operator">=></span> html<span class="token template-string"><span class="token template-punctuation string">`</span><span class="token html language-html">',
|
||||
' <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>ing-accordion</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>ing-accordion</span><span class="token punctuation">></span></span>',
|
||||
'</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>',
|
||||
'</code></pre>',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'</mdjs-preview>',
|
||||
].join('\n'),
|
||||
);
|
||||
|
||||
expect(result.jsCode).to.include('ing-accordion');
|
||||
expect(result.jsCode).to.include('#accordion/define');
|
||||
expect(result.jsCode).to.equal(
|
||||
[
|
||||
'/** script code **/',
|
||||
'import { html } from "@lion/core";',
|
||||
'import "#accordion/define";',
|
||||
'/** stories code **/',
|
||||
'export const main = () => html`',
|
||||
' <ing-accordion></ing-accordion>',
|
||||
'`;',
|
||||
'/** stories setup code **/',
|
||||
'const rootNode = document;',
|
||||
"const stories = [{ key: 'main', story: main }];",
|
||||
'let needsMdjsElements = false;',
|
||||
'for (const story of stories) {',
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
' const storyEl = rootNode.querySelector(`[mdjs-story-name="${story.key}"]`);',
|
||||
' if (storyEl) {',
|
||||
' storyEl.story = story.story;',
|
||||
' storyEl.key = story.key;',
|
||||
' needsMdjsElements = true;',
|
||||
' Object.assign(storyEl, {});',
|
||||
' }',
|
||||
'};',
|
||||
'if (needsMdjsElements) {',
|
||||
" if (!customElements.get('mdjs-preview')) { import('@mdjs/mdjs-preview/define'); }",
|
||||
" if (!customElements.get('mdjs-story')) { import('@mdjs/mdjs-story/define'); }",
|
||||
'}',
|
||||
].join('\n'),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import chai from 'chai';
|
||||
import unified from 'unified';
|
||||
import markdown from 'remark-parse';
|
||||
import mdStringify from 'remark-html';
|
||||
|
||||
import { remarkUrlToLocal } from '../src/remarkUrlToLocal.js';
|
||||
|
||||
const { expect } = chai;
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @returns
|
||||
*/
|
||||
async function execute(input) {
|
||||
const rootDir = path.join(__dirname, '../../../');
|
||||
|
||||
const parser = unified()
|
||||
//
|
||||
.use(markdown)
|
||||
.use(remarkUrlToLocal, {
|
||||
gitHubUrl: 'https://github.com/ing-bank/lion/',
|
||||
rootDir,
|
||||
page: {
|
||||
inputPath: path.join(rootDir, 'docs/components/inputs/form/overview/index.md'),
|
||||
},
|
||||
})
|
||||
.use(mdStringify);
|
||||
const result = await parser.process(input);
|
||||
return result.contents.toString().trim();
|
||||
}
|
||||
|
||||
describe('remarkUrlToLocal', () => {
|
||||
it('convert urls to local', async () => {
|
||||
const result = await execute(
|
||||
'Since it extends from [fieldset](https://github.com/ing-bank/lion/blob/6f2b6f940a0875091f1d940f45f0cd32dffce9ac/docs/components/inputs/fieldset/overview.md)',
|
||||
);
|
||||
|
||||
expect(result).to.equal(
|
||||
'<p>Since it extends from <a href="../../fieldset/overview.md">fieldset</a></p>',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not touch issue urls', async () => {
|
||||
const result = await execute('see [explanation](https://github.com/ing-bank/lion/issues/591)');
|
||||
|
||||
expect(result).to.equal(
|
||||
'<p>see <a href="https://github.com/ing-bank/lion/issues/591">explanation</a></p>',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not touch urls to the repo', async () => {
|
||||
const result = await execute('see [explanation](https://github.com/ing-bank/lion/)');
|
||||
|
||||
expect(result).to.equal(
|
||||
'<p>see <a href="https://github.com/ing-bank/lion/">explanation</a></p>',
|
||||
);
|
||||
});
|
||||
|
||||
it('works with images', async () => {
|
||||
const result = await execute(
|
||||
`see `,
|
||||
);
|
||||
|
||||
expect(result).to.equal(
|
||||
'<p>see <img src="../../../../docs/systems/form/assets/FormatMixinDiagram-1.svg" alt="Standard flow" title="Standard flow"></p>',
|
||||
);
|
||||
});
|
||||
});
|
||||
78
yarn.lock
78
yarn.lock
|
|
@ -1526,9 +1526,9 @@
|
|||
rimraf "^2.5.2"
|
||||
|
||||
"@mdjs/core@^0.7.1":
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@mdjs/core/-/core-0.7.1.tgz#115681f1f24d68c042c9765f16ead87aee3ec726"
|
||||
integrity sha512-iHIXl230X3c0lsWAE+MUtd6lKmARj2bsh2yfS3UBfWbZiX7rMrK5AAb9Yh+5/aXaBOg3Gm2dHSeiSueen3kEBg==
|
||||
version "0.7.2"
|
||||
resolved "https://registry.yarnpkg.com/@mdjs/core/-/core-0.7.2.tgz#2d94c8440f81860cc8d9fef8d516e329463bfbd7"
|
||||
integrity sha512-0vaiM3l01TC6PCmMZ/Mgun3xHaTzg8A3tSEVewkSQ3unfoB1053GrrqDb8Y8K/CXM5c3CPG1cFJEYOTk4mhuyA==
|
||||
dependencies:
|
||||
"@mdjs/mdjs-preview" "^0.4.2"
|
||||
"@mdjs/mdjs-story" "^0.2.0"
|
||||
|
|
@ -4179,11 +4179,6 @@ code-point-at@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
collapse-white-space@^1.0.0:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287"
|
||||
integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==
|
||||
|
||||
color-convert@^1.9.0, color-convert@^1.9.1:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||
|
|
@ -5122,13 +5117,6 @@ destroy@^1.0.4, destroy@~1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||
|
||||
detab@^2.0.0:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.4.tgz#b927892069aff405fbb9a186fe97a44a92a94b43"
|
||||
integrity sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==
|
||||
dependencies:
|
||||
repeat-string "^1.5.4"
|
||||
|
||||
detect-indent@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd"
|
||||
|
|
@ -6808,10 +6796,10 @@ hast-util-raw@^6.1.0:
|
|||
xtend "^4.0.0"
|
||||
zwitch "^1.0.0"
|
||||
|
||||
hast-util-sanitize@^2.0.0:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-sanitize/-/hast-util-sanitize-2.0.3.tgz#3cf4a1f5adb7d3c0b1fbb5dc1b1930fab6574856"
|
||||
integrity sha512-RILqWHmzU0Anmfw1KEP41LbCsJuJUVM0lQWAbTDk9+0bWqzRFXDaMdqIoRocLlOfR5NfcWyhFfZw/mGsuftwYA==
|
||||
hast-util-sanitize@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hast-util-sanitize/-/hast-util-sanitize-3.0.2.tgz#b0b783220af528ba8fe6999f092d138908678520"
|
||||
integrity sha512-+2I0x2ZCAyiZOO/sb4yNLFmdwPBnyJ4PBkVTUMKMqBwYNA+lXSgOmoRXlJFazoyid9QPogRRKgKhVEodv181sA==
|
||||
dependencies:
|
||||
xtend "^4.0.0"
|
||||
|
||||
|
|
@ -8565,13 +8553,6 @@ maximatch@^0.1.0:
|
|||
arrify "^1.0.0"
|
||||
minimatch "^3.0.0"
|
||||
|
||||
mdast-util-definitions@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-2.0.1.tgz#2c931d8665a96670639f17f98e32c3afcfee25f3"
|
||||
integrity sha512-Co+DQ6oZlUzvUR7JCpP249PcexxygiaKk9axJh+eRzHDZJk2julbIdKB4PXHVxdBuLzvJ1Izb+YDpj2deGMOuA==
|
||||
dependencies:
|
||||
unist-util-visit "^2.0.0"
|
||||
|
||||
mdast-util-definitions@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz#c5c1a84db799173b4dcf7643cda999e440c24db2"
|
||||
|
|
@ -8641,7 +8622,7 @@ mdast-util-gfm@^0.1.0:
|
|||
mdast-util-gfm-task-list-item "^0.1.0"
|
||||
mdast-util-to-markdown "^0.6.1"
|
||||
|
||||
mdast-util-to-hast@^10.2.0:
|
||||
mdast-util-to-hast@^10.0.0, mdast-util-to-hast@^10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.2.0.tgz#61875526a017d8857b71abc9333942700b2d3604"
|
||||
integrity sha512-JoPBfJ3gBnHZ18icCwHR50orC9kNH81tiR1gs01D8Q5YpV6adHNO9nKNuFBCJQ941/32PT1a63UF/DitmS3amQ==
|
||||
|
|
@ -8655,21 +8636,6 @@ mdast-util-to-hast@^10.2.0:
|
|||
unist-util-position "^3.0.0"
|
||||
unist-util-visit "^2.0.0"
|
||||
|
||||
mdast-util-to-hast@^8.2.0:
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-8.2.0.tgz#adf9f824defcd382e53dd7bace4282a45602ac67"
|
||||
integrity sha512-WjH/KXtqU66XyTJQ7tg7sjvTw1OQcVV0hKdFh3BgHPwZ96fSBCQ/NitEHsN70Mmnggt+5eUUC7pCnK+2qGQnCA==
|
||||
dependencies:
|
||||
collapse-white-space "^1.0.0"
|
||||
detab "^2.0.0"
|
||||
mdast-util-definitions "^2.0.0"
|
||||
mdurl "^1.0.0"
|
||||
trim-lines "^1.0.0"
|
||||
unist-builder "^2.0.0"
|
||||
unist-util-generated "^1.0.0"
|
||||
unist-util-position "^3.0.0"
|
||||
unist-util-visit "^2.0.0"
|
||||
|
||||
mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0:
|
||||
version "0.6.5"
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe"
|
||||
|
|
@ -10100,9 +10066,9 @@ plugin-error@^1.0.1:
|
|||
extend-shallow "^3.0.2"
|
||||
|
||||
plugins-manager@^0.2.0, plugins-manager@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/plugins-manager/-/plugins-manager-0.2.1.tgz#fe42857f9dd9326eccdeb2e112f5f4e7fe9f261d"
|
||||
integrity sha512-ir2R5Jt1XH9/oFKEiyOhRFoGfFEToru8NinhebaBMm1iZdaL51k0hubjuVKPqMkA+T3FguB7FFd+x3iKSWOvAg==
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/plugins-manager/-/plugins-manager-0.2.2.tgz#1cae861e47f9806767fcaf1b25cbb2dcc149d016"
|
||||
integrity sha512-Yiqkl9DARga3182tk4x/iY0nf4A2mAnUMQp5xsCDz+3em9bevx102jLZrwhapw1BIN+fJK/igfuvOfqqjHnaBg==
|
||||
|
||||
plur@^3.1.1:
|
||||
version "3.1.1"
|
||||
|
|
@ -10868,15 +10834,14 @@ remark-gfm@^1.0.0:
|
|||
mdast-util-gfm "^0.1.0"
|
||||
micromark-extension-gfm "^0.3.0"
|
||||
|
||||
remark-html@^11.0.1:
|
||||
version "11.0.2"
|
||||
resolved "https://registry.yarnpkg.com/remark-html/-/remark-html-11.0.2.tgz#76f6f7c8981c736f01cb65f8853dbe5c2e546dfa"
|
||||
integrity sha512-U7qPKZq6Aai+UTpH5YrblLvqvdSUCRA4YmZYRTtbtknm/WUGmNUI0dvThbSuTNSf6TtC8btmbbScWi1wtUIxnw==
|
||||
remark-html@^13.0.1:
|
||||
version "13.0.1"
|
||||
resolved "https://registry.yarnpkg.com/remark-html/-/remark-html-13.0.1.tgz#d5b2d8be01203e61fc37403167ca7584879ad675"
|
||||
integrity sha512-K5KQCXWVz+harnyC+UVM/J9eJWCgjYRqFeZoZf2NgP0iFbuuw/RgMZv3MA34b/OEpGnstl3oiOUtZzD3tJ+CBw==
|
||||
dependencies:
|
||||
hast-util-sanitize "^2.0.0"
|
||||
hast-util-sanitize "^3.0.0"
|
||||
hast-util-to-html "^7.0.0"
|
||||
mdast-util-to-hast "^8.2.0"
|
||||
xtend "^4.0.1"
|
||||
mdast-util-to-hast "^10.0.0"
|
||||
|
||||
remark-parse@^9.0.0:
|
||||
version "9.0.0"
|
||||
|
|
@ -10930,7 +10895,7 @@ remove-trailing-separator@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
|
||||
integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
|
||||
|
||||
repeat-string@^1.0.0, repeat-string@^1.5.2, repeat-string@^1.5.4:
|
||||
repeat-string@^1.0.0, repeat-string@^1.5.2:
|
||||
version "1.6.1"
|
||||
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
|
||||
integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
|
||||
|
|
@ -12364,11 +12329,6 @@ tree-kill@^1.2.2:
|
|||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||
|
||||
trim-lines@^1.0.0:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.3.tgz#839514be82428fd9e7ec89e35081afe8f6f93115"
|
||||
integrity sha512-E0ZosSWYK2mkSu+KEtQ9/KqarVjA9HztOSX+9FDdNacRAq29RRV6ZQNgob3iuW8Htar9vAfEa6yyt5qBAHZDBA==
|
||||
|
||||
trim-newlines@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
|
||||
|
|
@ -13431,7 +13391,7 @@ xmlhttprequest-ssl@~1.6.2:
|
|||
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz#03b713873b01659dfa2c1c5d056065b27ddc2de6"
|
||||
integrity sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==
|
||||
|
||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
|
||||
xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
|
|
|||
Loading…
Reference in a new issue