vue-inbrowser-compiler-utils
Advanced tools
Comparing version 4.50.0 to 4.52.0
# Change Log | ||
## 4.52.0 | ||
### Minor Changes | ||
- [#1374](https://github.com/vue-styleguidist/vue-styleguidist/pull/1374) [`c38b94a3`](https://github.com/vue-styleguidist/vue-styleguidist/commit/c38b94a3ce7c0ce72e7f2f842b54ee9f1758fdea) Thanks [@elevatebart](https://github.com/elevatebart)! - Split utils package to avoid dependency for docgen | ||
### Patch Changes | ||
- Updated dependencies [[`c38b94a3`](https://github.com/vue-styleguidist/vue-styleguidist/commit/c38b94a3ce7c0ce72e7f2f842b54ee9f1758fdea)]: | ||
- vue-inbrowser-compiler-independent-utils@4.52.0 | ||
## 4.50.0 | ||
@@ -4,0 +15,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { EvaluableComponent } from './types'; | ||
import { EvaluableComponent } from 'vue-inbrowser-compiler-independent-utils'; | ||
export declare function compileTemplateForEval(compiledComponent: EvaluableComponent): void; |
export { Vue2, isVue3, compileScript, createApp, h, compileTemplate } from 'vue-inbrowser-compiler-demi'; | ||
export { default as addScopedStyle } from './addScopedStyle'; | ||
export { cleanName, addScopedStyle, parseComponent, isCodeVueSfc, getDefaultExample, EvaluableComponent, } from 'vue-inbrowser-compiler-independent-utils'; | ||
export { default as adaptCreateElement, concatenate } from './adaptCreateElement'; | ||
export { default as parseComponent, VsgSFCDescriptor } from './parseComponent'; | ||
export { default as isCodeVueSfc } from './isCodeVueSfc'; | ||
export { default as cleanName } from './cleanName'; | ||
export { default as getDefaultExample } from './getDefaultExample'; | ||
export * from './types'; | ||
export * from './compileTemplateForEval'; |
@@ -6,2 +6,3 @@ 'use strict'; | ||
var vueInbrowserCompilerDemi = require('vue-inbrowser-compiler-demi'); | ||
var vueInbrowserCompilerIndependentUtils = require('vue-inbrowser-compiler-independent-utils'); | ||
var camelCase = require('camelcase'); | ||
@@ -13,74 +14,3 @@ | ||
/* eslint-disable no-control-regex */ | ||
// used to make CSS selectors remain scoped properly | ||
function scoper(css, suffix) { | ||
const re = /([^\r\n,{}]+)(,(?=[^}]*{)|s*{)/g; | ||
// `after` is going to contain eithe a comma or an opening curly bracket | ||
css = css.replace(re, function (full, selector, after) { | ||
// if non-rule delimiter | ||
if (selector.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) { | ||
return selector + after; | ||
} | ||
// don't scope the part of the selector after ::v-deep | ||
const arrayDeep = /(.*)(::v-deep|>>>|\/deep\/)(.*)/g.exec(selector); | ||
if (arrayDeep) { | ||
const [, beforeVDeep, , afterVDeep] = arrayDeep; | ||
selector = beforeVDeep; | ||
after = (afterVDeep + after).trim(); | ||
} | ||
// deal with :scope pseudo selectors | ||
if (selector && selector.match(/:scope/)) { | ||
selector = selector.replace(/([^\s]*):scope/, function (ful, cutSelector) { | ||
if (cutSelector === '') { | ||
return '> *'; | ||
} | ||
return '> ' + cutSelector; | ||
}); | ||
} | ||
selector = selector.split(/\s+/).filter(part => !!part).map(part => { | ||
// combinators | ||
if (/^[>~+]$/.test(part)) { | ||
return part; | ||
} | ||
// deal with other pseudo selectors | ||
const [main, ...rest] = part.split(/:{1,2}/); | ||
let pseudo = rest.map(piece => `:${piece}`).join(''); | ||
return main + suffix + pseudo; | ||
}).join(' '); | ||
return selector + ' ' + after; | ||
}); | ||
return css; | ||
} | ||
const noop = () => { }; | ||
/** | ||
* Adds a style block to the head to load the styles. | ||
* uses the suffix to scope the styles | ||
* @param {string} css css code to add the the head | ||
* @param {string} suffix string to add to each selector as a scoped style to avoid conflicts | ||
* @returns a function that discard the added style element (if there is one) | ||
*/ | ||
function addScopedStyle(css, suffix) { | ||
// protect server side rendering | ||
if (typeof document === 'undefined') { | ||
return noop; | ||
} | ||
const head = document.head || document.getElementsByTagName('head')[0]; | ||
const newstyle = document.createElement('style'); | ||
newstyle.dataset.cssscoper = 'true'; | ||
const csses = scoper(css, `[data-${suffix}]`); | ||
const styleany = newstyle; | ||
if (styleany.styleSheet) { | ||
styleany.styleSheet.cssText = csses; | ||
} | ||
else { | ||
newstyle.appendChild(document.createTextNode(csses)); | ||
} | ||
head.appendChild(newstyle); | ||
return () => { | ||
head.removeChild(newstyle); | ||
}; | ||
} | ||
/** | ||
* Groups attributes passed to a React pragma to the VueJS fashion | ||
@@ -228,132 +158,2 @@ * @param h the VueJS createElement function passed in render functions | ||
// highest priority first | ||
const PARTS = ['script', 'template']; | ||
function parseComponent(code) { | ||
// reinitialize regexp after each tour | ||
const partsRE = PARTS.reduce((ret, part) => { | ||
ret[part] = new RegExp(`<${part}[^>]*>((.|\\n|\\r)+)</${part}>`, 'g'); | ||
return ret; | ||
}, {}); | ||
const descriptor = {}; | ||
let codeCleaned = `${code}`; | ||
// extract all parts | ||
PARTS.forEach(part => { | ||
const res = partsRE[part].exec(codeCleaned); | ||
if (res) { | ||
const partFound = res[0]; | ||
const linesBeforePart = code.split(partFound)[0]; | ||
const paddingLinesNumber = linesBeforePart.split('\n').length; | ||
descriptor[part] = Array(paddingLinesNumber).join('\n') + res[1]; | ||
// once we have extracted one part, | ||
// remove it from the analyzed string | ||
const linesOfPart = partFound.split('\n').length; | ||
codeCleaned = codeCleaned.replace(partFound, Array(linesOfPart).join('\n')); | ||
} | ||
}); | ||
// we assume that | ||
const styleRE = /<style[^>]*>((.|\n|\r)*?)<\/style>/g; | ||
let styleAnalyzed = ''; | ||
const stylesWithWrapper = []; | ||
let stylePart = styleRE.exec(codeCleaned); | ||
let styles; | ||
while (stylePart) { | ||
styleAnalyzed += stylePart[1]; | ||
if (!styles) { | ||
styles = []; | ||
} | ||
const styleWithWrapper = stylePart[0]; | ||
stylesWithWrapper.push(styleWithWrapper); | ||
const linesBeforePart = code.split(styleWithWrapper)[0]; | ||
const paddingLinesNumber = linesBeforePart.split('\n').length; | ||
styles.push(Array(paddingLinesNumber).join('\n') + styleAnalyzed); | ||
stylePart = styleRE.exec(codeCleaned); | ||
} | ||
if (styles) { | ||
descriptor.styles = styles; | ||
let j = styles.length; | ||
while (j--) { | ||
codeCleaned = codeCleaned.replace(stylesWithWrapper[j], '').trim(); | ||
} | ||
} | ||
return codeCleaned.trim().length ? {} : descriptor; | ||
} | ||
/** | ||
* Determines if the given code is a VueSfc file | ||
* It does not throw if the code is invalid, just returns `false` | ||
* @param code JavaScript or vue code to analyze | ||
*/ | ||
function isCodeVueSfc(code) { | ||
const parts = parseComponent(code); | ||
return !!parts.script || !!parts.template; | ||
} | ||
function cleanName(name) { | ||
return name.replace(/[^A-Za-z0-9-]/g, ''); | ||
} | ||
function getDefaultText() { | ||
return 'Default Example Usage'; | ||
} | ||
function getDefaultNumber() { | ||
return '42'; | ||
} | ||
function getDefaultBoolean() { | ||
return 'true'; | ||
} | ||
function getDefaultArray() { | ||
return '[1, 2, 3]'; | ||
} | ||
function getDefaultFunction() { | ||
return '() => void'; | ||
} | ||
function getDefaultDate() { | ||
return 'new Date(\'2012-12-12\')'; | ||
} | ||
function getDefaultObject() { | ||
return '{}'; | ||
} | ||
function getDefault(prop) { | ||
if (!prop || !prop.type) { | ||
return getDefaultText(); | ||
} | ||
else if (prop.values && prop.values.length) { | ||
return prop.values[0]; | ||
} | ||
else if (prop.type.name === 'string') { | ||
return getDefaultText(); | ||
} | ||
else if (prop.type.name === 'number') { | ||
return getDefaultNumber(); | ||
} | ||
else if (prop.type.name === 'boolean') { | ||
return getDefaultBoolean(); | ||
} | ||
else if (prop.type.name === 'object') { | ||
return getDefaultObject(); | ||
} | ||
else if (prop.type.name === 'array') { | ||
return getDefaultArray(); | ||
} | ||
else if (prop.type.name === 'func') { | ||
return getDefaultFunction(); | ||
} | ||
else if (prop.type.name === 'date') { | ||
return getDefaultDate(); | ||
} | ||
return getDefaultText(); | ||
} | ||
var getDefaultExample = (doc) => { | ||
const { displayName, props, slots } = doc; | ||
const cleanedName = cleanName(displayName); | ||
const propsAttr = props | ||
? props | ||
.filter(p => p.required) | ||
.map(p => ` ${!p || !p.type || p.type.name === 'string' ? '' : ':'}${p.name}="${getDefault(p)}"`) | ||
: []; | ||
return `<${cleanedName}${propsAttr.join(' ')}${!slots || !slots.filter(s => s.name === 'default') | ||
? ' />' | ||
: `>${getDefaultText()}</${cleanedName}>`}`; | ||
}; | ||
const EXAMPLE_FILENAME = 'example.vue'; | ||
@@ -415,9 +215,24 @@ function compileTemplateForEval(compiledComponent) { | ||
}); | ||
Object.defineProperty(exports, 'addScopedStyle', { | ||
enumerable: true, | ||
get: function () { return vueInbrowserCompilerIndependentUtils.addScopedStyle; } | ||
}); | ||
Object.defineProperty(exports, 'cleanName', { | ||
enumerable: true, | ||
get: function () { return vueInbrowserCompilerIndependentUtils.cleanName; } | ||
}); | ||
Object.defineProperty(exports, 'getDefaultExample', { | ||
enumerable: true, | ||
get: function () { return vueInbrowserCompilerIndependentUtils.getDefaultExample; } | ||
}); | ||
Object.defineProperty(exports, 'isCodeVueSfc', { | ||
enumerable: true, | ||
get: function () { return vueInbrowserCompilerIndependentUtils.isCodeVueSfc; } | ||
}); | ||
Object.defineProperty(exports, 'parseComponent', { | ||
enumerable: true, | ||
get: function () { return vueInbrowserCompilerIndependentUtils.parseComponent; } | ||
}); | ||
exports.adaptCreateElement = adaptCreateElement; | ||
exports.addScopedStyle = addScopedStyle; | ||
exports.cleanName = cleanName; | ||
exports.compileTemplateForEval = compileTemplateForEval; | ||
exports.concatenate = concatenate; | ||
exports.getDefaultExample = getDefaultExample; | ||
exports.isCodeVueSfc = isCodeVueSfc; | ||
exports.parseComponent = parseComponent; |
import { isVue3, compileScript, compileTemplate } from 'vue-inbrowser-compiler-demi'; | ||
export { Vue2, compileScript, compileTemplate, createApp, h, isVue3 } from 'vue-inbrowser-compiler-demi'; | ||
export { addScopedStyle, cleanName, getDefaultExample, isCodeVueSfc, parseComponent } from 'vue-inbrowser-compiler-independent-utils'; | ||
import camelCase from 'camelcase'; | ||
/* eslint-disable no-control-regex */ | ||
// used to make CSS selectors remain scoped properly | ||
function scoper(css, suffix) { | ||
const re = /([^\r\n,{}]+)(,(?=[^}]*{)|s*{)/g; | ||
// `after` is going to contain eithe a comma or an opening curly bracket | ||
css = css.replace(re, function (full, selector, after) { | ||
// if non-rule delimiter | ||
if (selector.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) { | ||
return selector + after; | ||
} | ||
// don't scope the part of the selector after ::v-deep | ||
const arrayDeep = /(.*)(::v-deep|>>>|\/deep\/)(.*)/g.exec(selector); | ||
if (arrayDeep) { | ||
const [, beforeVDeep, , afterVDeep] = arrayDeep; | ||
selector = beforeVDeep; | ||
after = (afterVDeep + after).trim(); | ||
} | ||
// deal with :scope pseudo selectors | ||
if (selector && selector.match(/:scope/)) { | ||
selector = selector.replace(/([^\s]*):scope/, function (ful, cutSelector) { | ||
if (cutSelector === '') { | ||
return '> *'; | ||
} | ||
return '> ' + cutSelector; | ||
}); | ||
} | ||
selector = selector.split(/\s+/).filter(part => !!part).map(part => { | ||
// combinators | ||
if (/^[>~+]$/.test(part)) { | ||
return part; | ||
} | ||
// deal with other pseudo selectors | ||
const [main, ...rest] = part.split(/:{1,2}/); | ||
let pseudo = rest.map(piece => `:${piece}`).join(''); | ||
return main + suffix + pseudo; | ||
}).join(' '); | ||
return selector + ' ' + after; | ||
}); | ||
return css; | ||
} | ||
const noop = () => { }; | ||
/** | ||
* Adds a style block to the head to load the styles. | ||
* uses the suffix to scope the styles | ||
* @param {string} css css code to add the the head | ||
* @param {string} suffix string to add to each selector as a scoped style to avoid conflicts | ||
* @returns a function that discard the added style element (if there is one) | ||
*/ | ||
function addScopedStyle(css, suffix) { | ||
// protect server side rendering | ||
if (typeof document === 'undefined') { | ||
return noop; | ||
} | ||
const head = document.head || document.getElementsByTagName('head')[0]; | ||
const newstyle = document.createElement('style'); | ||
newstyle.dataset.cssscoper = 'true'; | ||
const csses = scoper(css, `[data-${suffix}]`); | ||
const styleany = newstyle; | ||
if (styleany.styleSheet) { | ||
styleany.styleSheet.cssText = csses; | ||
} | ||
else { | ||
newstyle.appendChild(document.createTextNode(csses)); | ||
} | ||
head.appendChild(newstyle); | ||
return () => { | ||
head.removeChild(newstyle); | ||
}; | ||
} | ||
/** | ||
* Groups attributes passed to a React pragma to the VueJS fashion | ||
@@ -219,132 +149,2 @@ * @param h the VueJS createElement function passed in render functions | ||
// highest priority first | ||
const PARTS = ['script', 'template']; | ||
function parseComponent(code) { | ||
// reinitialize regexp after each tour | ||
const partsRE = PARTS.reduce((ret, part) => { | ||
ret[part] = new RegExp(`<${part}[^>]*>((.|\\n|\\r)+)</${part}>`, 'g'); | ||
return ret; | ||
}, {}); | ||
const descriptor = {}; | ||
let codeCleaned = `${code}`; | ||
// extract all parts | ||
PARTS.forEach(part => { | ||
const res = partsRE[part].exec(codeCleaned); | ||
if (res) { | ||
const partFound = res[0]; | ||
const linesBeforePart = code.split(partFound)[0]; | ||
const paddingLinesNumber = linesBeforePart.split('\n').length; | ||
descriptor[part] = Array(paddingLinesNumber).join('\n') + res[1]; | ||
// once we have extracted one part, | ||
// remove it from the analyzed string | ||
const linesOfPart = partFound.split('\n').length; | ||
codeCleaned = codeCleaned.replace(partFound, Array(linesOfPart).join('\n')); | ||
} | ||
}); | ||
// we assume that | ||
const styleRE = /<style[^>]*>((.|\n|\r)*?)<\/style>/g; | ||
let styleAnalyzed = ''; | ||
const stylesWithWrapper = []; | ||
let stylePart = styleRE.exec(codeCleaned); | ||
let styles; | ||
while (stylePart) { | ||
styleAnalyzed += stylePart[1]; | ||
if (!styles) { | ||
styles = []; | ||
} | ||
const styleWithWrapper = stylePart[0]; | ||
stylesWithWrapper.push(styleWithWrapper); | ||
const linesBeforePart = code.split(styleWithWrapper)[0]; | ||
const paddingLinesNumber = linesBeforePart.split('\n').length; | ||
styles.push(Array(paddingLinesNumber).join('\n') + styleAnalyzed); | ||
stylePart = styleRE.exec(codeCleaned); | ||
} | ||
if (styles) { | ||
descriptor.styles = styles; | ||
let j = styles.length; | ||
while (j--) { | ||
codeCleaned = codeCleaned.replace(stylesWithWrapper[j], '').trim(); | ||
} | ||
} | ||
return codeCleaned.trim().length ? {} : descriptor; | ||
} | ||
/** | ||
* Determines if the given code is a VueSfc file | ||
* It does not throw if the code is invalid, just returns `false` | ||
* @param code JavaScript or vue code to analyze | ||
*/ | ||
function isCodeVueSfc(code) { | ||
const parts = parseComponent(code); | ||
return !!parts.script || !!parts.template; | ||
} | ||
function cleanName(name) { | ||
return name.replace(/[^A-Za-z0-9-]/g, ''); | ||
} | ||
function getDefaultText() { | ||
return 'Default Example Usage'; | ||
} | ||
function getDefaultNumber() { | ||
return '42'; | ||
} | ||
function getDefaultBoolean() { | ||
return 'true'; | ||
} | ||
function getDefaultArray() { | ||
return '[1, 2, 3]'; | ||
} | ||
function getDefaultFunction() { | ||
return '() => void'; | ||
} | ||
function getDefaultDate() { | ||
return 'new Date(\'2012-12-12\')'; | ||
} | ||
function getDefaultObject() { | ||
return '{}'; | ||
} | ||
function getDefault(prop) { | ||
if (!prop || !prop.type) { | ||
return getDefaultText(); | ||
} | ||
else if (prop.values && prop.values.length) { | ||
return prop.values[0]; | ||
} | ||
else if (prop.type.name === 'string') { | ||
return getDefaultText(); | ||
} | ||
else if (prop.type.name === 'number') { | ||
return getDefaultNumber(); | ||
} | ||
else if (prop.type.name === 'boolean') { | ||
return getDefaultBoolean(); | ||
} | ||
else if (prop.type.name === 'object') { | ||
return getDefaultObject(); | ||
} | ||
else if (prop.type.name === 'array') { | ||
return getDefaultArray(); | ||
} | ||
else if (prop.type.name === 'func') { | ||
return getDefaultFunction(); | ||
} | ||
else if (prop.type.name === 'date') { | ||
return getDefaultDate(); | ||
} | ||
return getDefaultText(); | ||
} | ||
var getDefaultExample = (doc) => { | ||
const { displayName, props, slots } = doc; | ||
const cleanedName = cleanName(displayName); | ||
const propsAttr = props | ||
? props | ||
.filter(p => p.required) | ||
.map(p => ` ${!p || !p.type || p.type.name === 'string' ? '' : ':'}${p.name}="${getDefault(p)}"`) | ||
: []; | ||
return `<${cleanedName}${propsAttr.join(' ')}${!slots || !slots.filter(s => s.name === 'default') | ||
? ' />' | ||
: `>${getDefaultText()}</${cleanedName}>`}`; | ||
}; | ||
const EXAMPLE_FILENAME = 'example.vue'; | ||
@@ -382,2 +182,2 @@ function compileTemplateForEval(compiledComponent) { | ||
export { adaptCreateElement, addScopedStyle, cleanName, compileTemplateForEval, concatenate, getDefaultExample, isCodeVueSfc, parseComponent }; | ||
export { adaptCreateElement, compileTemplateForEval, concatenate }; |
{ | ||
"name": "vue-inbrowser-compiler-utils", | ||
"version": "4.50.0", | ||
"version": "4.52.0", | ||
"description": "use this with vue-inbrowser-compiler to allow jsx compilation", | ||
@@ -17,3 +17,4 @@ "module": "lib/vue-inbrowser-compiler-utils.esm.js", | ||
"camelcase": "^5.3.1", | ||
"vue-inbrowser-compiler-demi": "^4.50.0" | ||
"vue-inbrowser-compiler-demi": "^4.50.0", | ||
"vue-inbrowser-compiler-independent-utils": "^4.52.0" | ||
}, | ||
@@ -20,0 +21,0 @@ "devDependencies": { |
import { compileScript, compileTemplate, isVue3 } from 'vue-inbrowser-compiler-demi' | ||
import { EvaluableComponent } from './types' | ||
import { EvaluableComponent } from 'vue-inbrowser-compiler-independent-utils' | ||
@@ -4,0 +4,0 @@ const EXAMPLE_FILENAME = 'example.vue' |
@@ -9,9 +9,11 @@ export { | ||
} from 'vue-inbrowser-compiler-demi' | ||
export { default as addScopedStyle } from './addScopedStyle' | ||
export { | ||
cleanName, | ||
addScopedStyle, | ||
parseComponent, | ||
isCodeVueSfc, | ||
getDefaultExample, | ||
EvaluableComponent, | ||
} from 'vue-inbrowser-compiler-independent-utils' | ||
export { default as adaptCreateElement, concatenate } from './adaptCreateElement' | ||
export { default as parseComponent, VsgSFCDescriptor } from './parseComponent' | ||
export { default as isCodeVueSfc } from './isCodeVueSfc' | ||
export { default as cleanName } from './cleanName' | ||
export { default as getDefaultExample } from './getDefaultExample' | ||
export * from './types' | ||
export * from './compileTemplateForEval' |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42247
4
16
737
+ Addedvue-inbrowser-compiler-independent-utils@4.71.1(transitive)