Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@storybook/docs-mdx

Package Overview
Dependencies
Maintainers
29
Versions
60
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@storybook/docs-mdx - npm Package Compare versions

Comparing version 0.0.1-canary.9a7e7e1.0 to 0.0.1-canary.c6b5d29.0

index.mjs

86

dist/esm/analyze.js

@@ -6,12 +6,21 @@ import * as t from '@babel/types';

import { toEstree } from 'hast-util-to-estree';
import cloneDeep from 'lodash/cloneDeep';
const getAttr = (elt, what) => {
const attr = elt.attributes.find(n => n.name.name === what);
return attr === null || attr === void 0 ? void 0 : attr.value;
return attr;
};
const getAttrValue = (elt, what) => {
var _getAttr;
return (_getAttr = getAttr(elt, what)) === null || _getAttr === void 0 ? void 0 : _getAttr.value;
};
const extractTitle = (root, varToImport) => {
const result = {
title: undefined,
of: undefined
of: undefined,
name: undefined,
isTemplate: false
};

@@ -34,22 +43,32 @@ let contents;

if (name === 'Meta') {
if (result.title) {
if (result.title || result.name || result.of) {
throw new Error('Meta can only be declared once');
}
const titleAttr = getAttr(child.openingElement, 'title');
const titleAttrValue = getAttrValue(child.openingElement, 'title');
if (titleAttr) {
if (t.isStringLiteral(titleAttr)) {
result.title = titleAttr.value;
if (titleAttrValue) {
if (t.isStringLiteral(titleAttrValue)) {
result.title = titleAttrValue.value;
} else {
throw new Error(`Expected string literal title, received ${titleAttr.type}`);
throw new Error(`Expected string literal title, received ${titleAttrValue.type}`);
}
}
const ofAttr = getAttr(child.openingElement, 'of');
const nameAttrValue = getAttrValue(child.openingElement, 'name');
if (ofAttr) {
if (t.isJSXExpressionContainer(ofAttr)) {
const of = ofAttr.expression;
if (nameAttrValue) {
if (t.isStringLiteral(nameAttrValue)) {
result.name = nameAttrValue.value;
} else {
throw new Error(`Expected string literal name, received ${nameAttrValue.type}`);
}
}
const ofAttrValue = getAttrValue(child.openingElement, 'of');
if (ofAttrValue) {
if (t.isJSXExpressionContainer(ofAttrValue)) {
const of = ofAttrValue.expression;
if (t.isIdentifier(of)) {

@@ -67,8 +86,27 @@ const importName = varToImport[of.name];

} else {
throw new Error(`Expected JSX expression, received ${ofAttr.type}`);
throw new Error(`Expected JSX expression, received ${ofAttrValue.type}`);
}
}
const isTemplateAttr = getAttr(child.openingElement, 'isTemplate');
if (isTemplateAttr) {
if (!isTemplateAttr.value) {
// no value, implicit true
result.isTemplate = true;
} else if (t.isJSXExpressionContainer(isTemplateAttr.value)) {
const isTemplate = isTemplateAttr.value.expression;
if (t.isBooleanLiteral(isTemplate)) {
result.isTemplate = isTemplate.value;
} else {
throw new Error(`Expected boolean isTemplate, received ${isTemplate.type}`);
}
} else {
throw new Error(`Expected JSX expression isTemplate, received ${isTemplateAttr.value.type}`);
}
}
}
}
} else if (t.isJSXExpressionContainer(child) && t.isStringLiteral(child.expression)) {// Skip string literals
} else if (t.isJSXExpressionContainer(child)) {// Skip string literals & other JSX expressions
} else {

@@ -152,13 +190,15 @@ throw new Error(`Unexpected JSX child: ${child.type}`);

const estree = store.toEstree(root); // toBabel mutates root, bug we don't need to clone it because
// we're not using it again
// const clone = cloneDeep(estree);
const babel = toBabel(estree);
const estree = store.toEstree(root);
const clone = cloneDeep(estree);
const babel = toBabel(clone);
const {
title,
of
of,
name,
isTemplate
} = extractTitle(babel, varToImport);
store.title = title;
store.of = of;
store.name = name;
store.isTemplate = isTemplate;
store.imports = Array.from(new Set(Object.values(varToImport)));

@@ -171,2 +211,4 @@ return root;

of: undefined,
name: undefined,
isTemplate: false,
imports: undefined,

@@ -181,2 +223,4 @@ toEstree

of,
name,
isTemplate,
imports = []

@@ -187,4 +231,6 @@ } = store;

of,
name,
isTemplate,
imports
};
};

@@ -10,9 +10,8 @@ import { dedent } from 'ts-dedent';

import { Meta } from '@storybook/blocks';
import meta, { Basic } from './Button.stories';
import * as ButtonStories from './Button.stories';
`);
expect(extractImports(ast)).toMatchInlineSnapshot(`
Object {
"Basic": "./Button.stories",
"ButtonStories": "./Button.stories",
"Meta": "@storybook/blocks",
"meta": "./Button.stories",
}

@@ -32,2 +31,4 @@ `);

"imports": Array [],
"isTemplate": false,
"name": undefined,
"of": undefined,

@@ -46,10 +47,28 @@ "title": "foobar",

});
it('duplicate titles', () => {
});
describe('name', () => {
it('string literal name', () => {
const input = dedent`
<Meta title="foobar" />
# hello
<Meta title="bz" />
<Meta name="foobar" />
`;
expect(() => analyze(input)).toThrowErrorMatchingInlineSnapshot(`"Meta can only be declared once"`);
expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [],
"isTemplate": false,
"name": "foobar",
"of": undefined,
"title": undefined,
}
`);
});
it('template literal name', () => {
const input = dedent`
# hello
<Meta name={\`foobar\`} />
`;
expect(() => analyze(input)).toThrowErrorMatchingInlineSnapshot(`"Expected string literal name, received JSXExpressionContainer"`);
});
});

@@ -60,16 +79,18 @@ describe('of', () => {

import { Meta } from '@storybook/blocks';
import meta, { Basic } from './Button.stories';
import * as ButtonStories from './Button.stories';
<Meta of={meta} />
<Meta of={ButtonStories} />
`;
expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [
"@storybook/blocks",
"./Button.stories",
],
"of": "./Button.stories",
"title": undefined,
}
`);
Object {
"imports": Array [
"@storybook/blocks",
"./Button.stories",
],
"isTemplate": false,
"name": undefined,
"of": "./Button.stories",
"title": undefined,
}
`);
});

@@ -84,3 +105,3 @@ it('missing variable', () => {

const input = dedent`
import meta, { Basic } from './Button.stories';
import * as ButtonStories from './Button.stories';

@@ -92,2 +113,61 @@ <Meta of="foobar" />

});
describe('isTemplate', () => {
it('boolean implicit', () => {
const input = dedent`
<Meta isTemplate />
`;
expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [],
"isTemplate": true,
"name": undefined,
"of": undefined,
"title": undefined,
}
`);
}); // For some reason these two tests throw with:
// "TypeError: this[node.value.type] is not a function"
// It's not clear why?
it('boolean expression, true', () => {
const input = dedent`
<Meta isTemplate={true} />
`;
expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [],
"isTemplate": true,
"name": undefined,
"of": undefined,
"title": undefined,
}
`);
});
it('boolean expression, false', () => {
const input = dedent`
<Meta isTemplate={false} />
`;
expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [],
"isTemplate": false,
"name": undefined,
"of": undefined,
"title": undefined,
}
`);
});
it('string literal', () => {
const input = dedent`
<Meta isTemplate="foo" />
`;
expect(() => analyze(input)).toThrowErrorMatchingInlineSnapshot(`"Expected JSX expression isTemplate, received StringLiteral"`);
});
it('other expression', () => {
const input = dedent`
<Meta isTemplate={1} />
`;
expect(() => analyze(input)).toThrowErrorMatchingInlineSnapshot(`"Expected boolean isTemplate, received NumericLiteral"`);
});
});
describe('errors', () => {

@@ -99,26 +179,68 @@ it('no title', () => {

expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [],
"of": undefined,
"title": undefined,
}
`);
Object {
"imports": Array [],
"isTemplate": false,
"name": undefined,
"of": undefined,
"title": undefined,
}
`);
});
it('Bad MDX formatting', () => {
const input = dedent`
import meta, { Basic } from './Button.stories';
import meta, { Basic } from './Button.stories';
<Meta of={meta} />/>
`;
<Meta of={meta} />/>
`;
expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [
"./Button.stories",
],
"of": undefined,
"title": undefined,
}
`);
Object {
"imports": Array [
"./Button.stories",
],
"isTemplate": false,
"name": undefined,
"of": undefined,
"title": undefined,
}
`);
});
it('duplicate meta, both title', () => {
const input = dedent`
<Meta title="foobar" />
<Meta title="bz" />
`;
expect(() => analyze(input)).toThrowErrorMatchingInlineSnapshot(`"Meta can only be declared once"`);
});
it('duplicate meta, different', () => {
const input = dedent`
import * as ButtonStories from './Button.stories';
<Meta title="foobar" />
<Meta of={ButtonStories} />
`;
expect(() => analyze(input)).toThrowErrorMatchingInlineSnapshot(`"Meta can only be declared once"`);
});
it('MDX comments', () => {
const input = dedent`
import meta, { Basic } from './Button.stories';
<Meta of={meta} />
{/* whatever */}
`;
expect(analyze(input)).toMatchInlineSnapshot(`
Object {
"imports": Array [
"./Button.stories",
],
"isTemplate": false,
"name": undefined,
"of": "./Button.stories",
"title": undefined,
}
`);
});
});
});

@@ -7,3 +7,5 @@ import * as t from '@babel/types';

of: any;
name: any;
isTemplate: any;
imports: any;
};
{
"name": "@storybook/docs-mdx",
"version": "0.0.1-canary.9a7e7e1.0",
"version": "0.0.1-canary.c6b5d29.0",
"description": "Storybook Docs MDX analyzer",

@@ -19,2 +19,3 @@ "repository": {

"*.d.ts",
"index.mjs",
"index.cjs"

@@ -39,5 +40,7 @@ ],

"@babel/traverse": "^7.12.11",
"@babel/types": "^7.14.8",
"@mdx-js/mdx": "^2.0.0",
"estree-to-babel": "^4.9.0",
"hast-util-to-estree": "^2.0.2"
"hast-util-to-estree": "^2.0.2",
"lodash": "^4.17.21"
},

@@ -50,5 +53,5 @@ "devDependencies": {

"@babel/preset-typescript": "^7.13.0",
"@babel/types": "^7.14.8",
"@jest/types": "^27.0.6",
"@types/jest": "^27.0.3",
"@types/lodash": "^4.14.182",
"@types/node": "^16.4.1",

@@ -55,0 +58,0 @@ "auto": "^10.3.0",

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc