Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@vant/markdown-vetur

Package Overview
Dependencies
Maintainers
4
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vant/markdown-vetur - npm Package Compare versions

Comparing version
1.1.0
to
2.0.0-beta.0
+3
lib/formatter.d.ts
import { Articals } from './parser';
import { VueTag } from './type';
export declare function formatter(articals: Articals, tagPrefix?: string): VueTag | undefined;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("./utils");
function getComponentName(artical, tagPrefix) {
if (artical.content) {
return tagPrefix + utils_1.toKebabCase(artical.content.split(' ')[0]);
}
return '';
}
function formatter(articals, tagPrefix = '') {
if (!articals.length) {
return;
}
const tag = {
name: getComponentName(articals[0], tagPrefix),
slots: [],
events: [],
attributes: [],
};
const tables = articals.filter(artical => artical.type === 'table');
tables.forEach(item => {
const { table } = item;
const prevIndex = articals.indexOf(item) - 1;
const prevArtical = articals[prevIndex];
if (!prevArtical || !prevArtical.content || !table || !table.body) {
return;
}
const tableTitle = prevArtical.content;
if (tableTitle.includes('Props')) {
table.body.forEach(line => {
const [name, desc, type, defaultVal] = line;
tag.attributes.push({
name: utils_1.removeVersion(name),
default: defaultVal,
description: desc,
value: {
type: utils_1.formatType(type),
kind: 'expression',
},
});
});
return;
}
if (tableTitle.includes('Events')) {
table.body.forEach(line => {
const [name, desc] = line;
tag.events.push({
name: utils_1.removeVersion(name),
description: desc,
});
});
return;
}
if (tableTitle.includes('Slots')) {
table.body.forEach(line => {
const [name, desc] = line;
tag.slots.push({
name: utils_1.removeVersion(name),
description: desc,
});
});
}
});
return tag;
}
exports.formatter = formatter;
import { Options } from './type';
export declare function parseAndWrite(options: Options): Promise<void>;
declare const _default: {
parseAndWrite: typeof parseAndWrite;
};
export default _default;
declare type TableContent = {
head: string[];
body: string[][];
};
export declare type Artical = {
type: string;
content?: string;
table?: TableContent;
level?: number;
};
export declare type Articals = Artical[];
export declare function mdParser(input: string): Articals;
export {};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-cond-assign */
const TITLE_REG = /^(#+)\s+([^\n]*)/;
const TABLE_REG = /^\|.+\n\|\s*-+/;
const TD_REG = /\s*`[^`]+`\s*|([^|`]+)/g;
const TABLE_SPLIT_LINE_REG = /^\|\s*-/;
function readLine(input) {
const end = input.indexOf('\n');
return input.substr(0, end !== -1 ? end : input.length);
}
function splitTableLine(line) {
line = line.replace('\\|', 'JOIN');
const items = line.split('|').map(item => item.trim().replace('JOIN', '|'));
// remove pipe character on both sides
items.pop();
items.shift();
return items;
}
function tableParse(input) {
let start = 0;
let isHead = true;
const end = input.length;
const table = {
head: [],
body: [],
};
while (start < end) {
const target = input.substr(start);
const line = readLine(target);
if (!/^\|/.test(target)) {
break;
}
if (TABLE_SPLIT_LINE_REG.test(target)) {
isHead = false;
}
else if (!isHead && line.includes('|')) {
const matched = line.trim().match(TD_REG);
if (matched) {
table.body.push(splitTableLine(line));
}
}
start += line.length + 1;
}
return {
table,
usedLength: start,
};
}
function mdParser(input) {
const artical = [];
let start = 0;
const end = input.length;
while (start < end) {
const target = input.substr(start);
let match;
if ((match = TITLE_REG.exec(target))) {
artical.push({
type: 'title',
content: match[2],
level: match[1].length,
});
start += match.index + match[0].length;
}
else if ((match = TABLE_REG.exec(target))) {
const { table, usedLength } = tableParse(target.substr(match.index));
artical.push({
type: 'table',
table,
});
start += match.index + usedLength;
}
else {
start += readLine(target).length + 1;
}
}
return artical;
}
exports.mdParser = mdParser;
/// <reference types="node" />
import { PathLike } from 'fs';
export declare type VueSlot = {
name: string;
description: string;
};
export declare type VueEventArgument = {
name: string;
type: string;
};
export declare type VueEvent = {
name: string;
description?: string;
arguments?: VueEventArgument[];
};
export declare type VueAttribute = {
name: string;
default: string;
description: string;
value: {
kind: 'expression';
type: string;
};
};
export declare type VueTag = {
name: string;
slots?: VueSlot[];
events?: VueEvent[];
attributes?: VueAttribute[];
description?: string;
};
export declare type VeturTag = {
description?: string;
attributes: string[];
};
export declare type VeturTags = Record<string, VeturTag>;
export declare type VeturAttribute = {
type: string;
description: string;
};
export declare type VeturAttributes = Record<string, VeturAttribute>;
export declare type VeturResult = {
tags: VeturTags;
attributes: VeturAttributes;
};
export declare type Options = {
name: string;
path: PathLike;
test: RegExp;
version: string;
outputDir?: string;
tagPrefix?: string;
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
export declare function toKebabCase(input: string): string;
export declare function removeVersion(str: string): string;
export declare function formatType(type: string): string;
export declare function normalizePath(path: string): string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// myName -> my-name
function toKebabCase(input) {
return input.replace(/[A-Z]/g, (val, index) => (index === 0 ? '' : '-') + val.toLowerCase());
}
exports.toKebabCase = toKebabCase;
// name `v2.0.0` -> name
function removeVersion(str) {
return str.replace(/`(\w|\.)+`/g, '').trim();
}
exports.removeVersion = removeVersion;
// *boolean* -> boolean
function formatType(type) {
return type.replace(/\*/g, '');
}
exports.formatType = formatType;
function normalizePath(path) {
return path.replace(/\\/g, '/');
}
exports.normalizePath = normalizePath;
import { VueTag } from './type';
export declare function genVeturTags(tags: VueTag[]): Record<string, import("./type").VeturTag>;
export declare function genVeturAttributes(tags: VueTag[]): Record<string, import("./type").VeturAttribute>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function genVeturTags(tags) {
const veturTags = {};
tags.forEach(tag => {
veturTags[tag.name] = {
attributes: tag.attributes ? tag.attributes.map(item => item.name) : [],
};
});
return veturTags;
}
exports.genVeturTags = genVeturTags;
function genVeturAttributes(tags) {
const veturAttributes = {};
tags.forEach(tag => {
if (tag.attributes) {
tag.attributes.forEach(attr => {
veturAttributes[`${tag.name}/${attr.name}`] = {
type: attr.value.type,
description: `${attr.description}, 默认值: ${attr.default}`,
};
});
}
});
return veturAttributes;
}
exports.genVeturAttributes = genVeturAttributes;
import { VueTag, Options } from './type';
export declare function genWebTypes(tags: VueTag[], options: Options): {
$schema: string;
framework: string;
name: string;
version: string;
contributions: {
html: {
tags: VueTag[];
attributes: never[];
'types-syntax': string;
};
};
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// create web-types.json to provide autocomplete in JetBrains IDEs
function genWebTypes(tags, options) {
return {
$schema: 'https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json',
framework: 'vue',
name: options.name,
version: options.version,
contributions: {
html: {
tags,
attributes: [],
'types-syntax': 'typescript',
},
},
};
}
exports.genWebTypes = genWebTypes;
+28
-80
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fast_glob_1 = __importDefault(require("fast-glob"));
const path_1 = require("path");
const md_parser_1 = require("./md-parser");
const codegen_1 = require("./codegen");
const fs_1 = require("fs");
function parseText(input) {
const ast = md_parser_1.mdParser(input);
return codegen_1.codegen(ast);
const parser_1 = require("./parser");
const formatter_1 = require("./formatter");
const web_types_1 = require("./web-types");
const fs_extra_1 = require("fs-extra");
const utils_1 = require("./utils");
const vetur_1 = require("./vetur");
async function readMarkdown(options) {
const mds = await fast_glob_1.default(utils_1.normalizePath(`${options.path}/**/*.md`));
return mds
.filter(md => options.test.test(md))
.map(path => fs_extra_1.readFileSync(path, 'utf-8'));
}
exports.parseText = parseText;
const defaultOptions = {
maxDeep: Infinity,
tagPrefix: ''
};
function parse(options) {
options = {
...defaultOptions,
...options
};
const result = {
tags: {},
attributes: {}
};
function putResult(componentName, component) {
componentName = options.tagPrefix + componentName;
const attributes = Object.keys(component.attributes);
const tag = {
description: component.description,
attributes
};
result.tags[componentName] = tag;
attributes.forEach(key => {
result.attributes[`${componentName}/${key}`] = component.attributes[key];
});
}
function recursiveParse(options, deep) {
if (options.maxDeep && deep > options.maxDeep) {
return;
}
deep++;
const files = fs_1.readdirSync(options.path);
files.forEach(item => {
const currentPath = path_1.join(options.path.toString(), item);
const stats = fs_1.statSync(currentPath);
if (stats.isDirectory()) {
recursiveParse({
...options,
path: currentPath
}, deep);
}
else if (stats.isFile() && options.test.test(item)) {
const file = fs_1.readFileSync(currentPath);
const tags = parseText(file.toString());
if (tags.default) {
// one tag
putResult(currentPath.split('/').slice(-2)[0], tags.default);
}
else {
Object.keys(tags).forEach(key => {
putResult(key, tags[key]);
});
}
}
});
}
recursiveParse(options, 0);
return result;
}
exports.parse = parse;
function parseAndWrite(options) {
const { tags, attributes } = parse(options);
async function parseAndWrite(options) {
if (!options.outputDir) {
return;
throw new Error('outputDir can not be empty.');
}
const isExist = fs_1.existsSync(options.outputDir);
if (!isExist) {
fs_1.mkdirSync(options.outputDir);
}
fs_1.writeFileSync(path_1.join(options.outputDir, 'tags.json'), JSON.stringify(tags, null, 2));
fs_1.writeFileSync(path_1.join(options.outputDir, 'attributes.json'), JSON.stringify(attributes, null, 2));
const mds = await readMarkdown(options);
const datas = mds
.map(md => formatter_1.formatter(parser_1.mdParser(md), options.tagPrefix))
.filter(item => !!item);
const webTypes = web_types_1.genWebTypes(datas, options);
const veturTags = vetur_1.genVeturTags(datas);
const veturAttributes = vetur_1.genVeturAttributes(datas);
fs_extra_1.outputFileSync(path_1.join(options.outputDir, 'tags.json'), JSON.stringify(veturTags, null, 2));
fs_extra_1.outputFileSync(path_1.join(options.outputDir, 'attributes.json'), JSON.stringify(veturAttributes, null, 2));
fs_extra_1.outputFileSync(path_1.join(options.outputDir, 'web-types.json'), JSON.stringify(webTypes, null, 2));
}
exports.parseAndWrite = parseAndWrite;
exports.default = {
parse,
parseText,
parseAndWrite
};
exports.default = { parseAndWrite };
{
"name": "@vant/markdown-vetur",
"version": "1.1.0",
"version": "2.0.0-beta.0",
"description": "simple parse markdown to vue component description for vetur auto-completion",

@@ -19,3 +19,10 @@ "main": "lib/index.js",

"release": "npm run build && npm publish"
},
"dependencies": {
"fast-glob": "^3.2.2",
"fs-extra": "^9.0.0"
},
"devDependencies": {
"@types/fs-extra": "^8.1.0"
}
}
# Vant Markdown Vetur
将 .md 文件转换成能描述 vue 组件的 .json 文件,供 vscode 插件 *vetur* 读取,从而可以在 vue 模版语法中拥有自动补全的功能。
将 .md 文件转换成能描述 vue 组件的 .json 文件,供 WebStorm 和 vscode 的 `vetur` 插件读取,从而可以在 vue 模版语法中拥有自动补全的功能。

@@ -5,0 +5,0 @@ ## Install

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const FLAG_REG = /(.*?)\s*(Props|Event)/i;
function camelCaseToKebabCase(input) {
return input.replace(/[A-Z]/g, (val, index) => (index === 0 ? '' : '-') + val.toLowerCase());
}
function removeVersionTag(str) {
return str.replace(/`(\w|\.)+`/g, '').trim();
}
function getDescription(td, isProp) {
const desc = td[1] ? td[1].replace('<br>', '') : '';
const type = td[2] ? td[2].replace(/\*/g, '') : '';
const defaultVal = td[3] ? td[3].replace(/`/g, '') : '';
if (isProp) {
return `${desc}, 默认值: ${defaultVal}, 类型: ${type}`;
}
return desc;
}
function codegen(artical) {
const tags = {};
let tagDescription = '';
for (let i = 0, len = artical.length; i < len; i++) {
const item = artical[i];
if (item.type === 'title' && item.level === 2) {
if (item.content) {
tagDescription = item.content;
}
}
else if (item.type === 'table') {
const before = artical[i - 1];
if (!before || !before.content) {
continue;
}
const { table } = item;
const match = FLAG_REG.exec(before.content);
if (!match || !table) {
continue;
}
const key = camelCaseToKebabCase(match[1] || 'default');
const tag = tags[key] || {
description: tagDescription,
attributes: {}
};
tags[key] = tag;
const isProp = /Props/i.test(match[2]);
table.body.forEach(td => {
const name = removeVersionTag(td[0]);
const attr = {
description: getDescription(td, isProp),
type: isProp ? td[2].replace(/`/g, '').toLowerCase() : 'event'
};
tag.attributes[name] = attr;
});
}
}
return tags;
}
exports.codegen = codegen;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/* eslint-disable no-cond-assign */
const TITLE_REG = /^(#+)\s+([^\n]*)/;
const TABLE_REG = /^\|.+\n\|\s*-+/;
const TD_REG = /\s*`[^`]+`\s*|([^|`]+)/g;
const TABLE_SPLIT_LINE_REG = /^\|\s*-/;
function readLine(input) {
const end = input.indexOf('\n');
return input.substr(0, end !== -1 ? end : input.length);
}
function splitTableLine(line) {
line = line.replace('\\|', 'JOIN');
const items = line.split('|').map(item => item.trim().replace('JOIN', '|'));
// remove pipe character on both sides
items.pop();
items.shift();
return items;
}
function tableParse(input) {
let start = 0;
let isHead = true;
const end = input.length;
const table = {
head: [],
body: []
};
while (start < end) {
const target = input.substr(start);
const line = readLine(target);
if (!/^\|/.test(target)) {
break;
}
if (TABLE_SPLIT_LINE_REG.test(target)) {
isHead = false;
}
else if (!isHead && line.includes('|')) {
const matched = line.trim().match(TD_REG);
if (matched) {
table.body.push(splitTableLine(line));
}
}
start += line.length + 1;
}
return {
table,
usedLength: start
};
}
function mdParser(input) {
const artical = [];
let start = 0;
const end = input.length;
while (start < end) {
const target = input.substr(start);
let match;
if ((match = TITLE_REG.exec(target))) {
artical.push({
type: 'title',
content: match[2],
level: match[1].length
});
start += match.index + match[0].length;
}
else if ((match = TABLE_REG.exec(target))) {
const { table, usedLength } = tableParse(target.substr(match.index));
artical.push({
type: 'table',
table
});
start += match.index + usedLength;
}
else {
start += readLine(target).length + 1;
}
}
return artical;
}
exports.mdParser = mdParser;