Skip to content

Commit

Permalink
Merge a0135a3 into 8f1c70c
Browse files Browse the repository at this point in the history
  • Loading branch information
JPeer264 committed Sep 23, 2020
2 parents 8f1c70c + a0135a3 commit 97c60df
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 18 deletions.
26 changes: 26 additions & 0 deletions __tests__/replace.html.ts
Expand Up @@ -248,3 +248,29 @@ it('should ignore JSON | issue #70', () => {
`,
);
});

it('should replace vue class bindings | issue gulp-rcs#14', () => {
replaceHtmlMacro(
'.selector {} .another-selector {} .more-selectors {} #my-id {} #second-id {}',
`
<div :class='{ "selector another-selector": active }'></div>
<div v-bind:class="{ 'selector another-selector': active }"></div>
<div v-bind:id="{ 'my-id second-id': active }"></div>
<div :class="{
'selector another-selector': active,
'more-selectors': active,
'another-selector selector': active,
}"></div>
`,
`
<div :class="{ 'a b': active }"></div>
<div v-bind:class="{ 'a b': active }"></div>
<div v-bind:id="{ 'a b': active }"></div>
<div :class="{
'a b': active,
'c': active,
'b a': active,
}"></div>
`,
);
});
11 changes: 11 additions & 0 deletions __tests__/replace.string.ts
Expand Up @@ -104,12 +104,23 @@ it('replace multiple strings', () => {
});

it('does not replace the text', () => {
rcs.selectorsLibrary.set('.test');

const expectedString = '" test "';
const replacedString = rcs.replace.string('" test "', getRegex());

expect(replacedString).toBe(expectedString);
});

it('does force replace the text', () => {
rcs.selectorsLibrary.set('.test');

const expectedString = '" a "';
const replacedString = rcs.replace.string('" test "', getRegex(), { forceReplace: true });

expect(replacedString).toBe(expectedString);
});

it('replace multiple selectors', () => {
rcs.selectorsLibrary.set('.test');

Expand Down
56 changes: 40 additions & 16 deletions lib/replace/html.ts
Expand Up @@ -7,6 +7,7 @@ import selectorsLibrary from '../selectorsLibrary';
import replaceJs from './js';
import replaceCss from './css';
import htmlToAst from '../helpers/htmlToAst';
import replaceString from './string';

// todo jpeer: update options
export type EspreeOptions = any;
Expand Down Expand Up @@ -69,8 +70,12 @@ const replaceHtml = (code: string, opts: ReplaceHtmlOptions = {}): string => {
node.attrs.forEach((attr: Attr) => {
let selectorType: string | undefined;

const isVueClass = attr.name === 'v-bind:class' || attr.name === ':class';
const isVueId = attr.name === 'v-bind:id' || attr.name === ':id';

if (
attr.name === 'class'
|| isVueClass
|| options.triggerClassAttributes.some((item) => (
shouldTriggerAttribute(attr, item)
))
Expand All @@ -80,6 +85,7 @@ const replaceHtml = (code: string, opts: ReplaceHtmlOptions = {}): string => {

if (
attr.name === 'id'
|| isVueId
|| options.triggerIdAttributes.some((item) => (
shouldTriggerAttribute(attr, item)
))
Expand All @@ -97,22 +103,40 @@ const replaceHtml = (code: string, opts: ReplaceHtmlOptions = {}): string => {

// following will replace each whitespace
// seperated value with its renamed one
// eslint-disable-next-line no-param-reassign
attr.value = attr.value
.split(' ')
.map((value) => (
// renaming each value
selectorsLibrary
.get(`${selectorType}${value}`, {
source: {
file: opts.sourceFile || '',
line: node.sourceCodeLocation.startLine,
text: '',
},
})
.replace(new RegExp(`^\\${selectorType}`), '')
))
.join(' ');
if (isVueClass || isVueId) {
// eslint-disable-next-line no-param-reassign
attr.value = attr.value.replace(/'[\s\S]*?'|"[\s\S]*?"/g, (match) => {
const replacedString = replaceString(match, undefined, {
forceReplace: true,
source: {
file: opts.sourceFile || '',
line: node.sourceCodeLocation.startLine,
text: '',
},
});

// in case HTML has been written with wrong quotes
// turn them back as parse5 will serialize it correctly
return replacedString.replace(/"/g, "'");
});
} else {
// eslint-disable-next-line no-param-reassign
attr.value = attr.value
.split(' ')
.map((value) => (
// renaming each value
selectorsLibrary
.get(`${selectorType}${value}`, {
source: {
file: opts.sourceFile || '',
line: node.sourceCodeLocation.startLine,
text: '',
},
})
.replace(new RegExp(`^\\${selectorType}`), '')
))
.join(' ');
}
});
}
},
Expand Down
10 changes: 8 additions & 2 deletions lib/replace/string.ts
Expand Up @@ -10,11 +10,12 @@ export interface ReplaceStringOptions extends BaseLibraryOptions {
classOnly?: boolean;
isJSX?: boolean;
addSelectorType?: boolean;
forceReplace?: boolean;
}

const replaceString = (
string: string,
regex: RegExp,
regex?: RegExp,
options: ReplaceStringOptions = {},
): string => {
let result;
Expand Down Expand Up @@ -100,7 +101,12 @@ const replaceString = (

previousAttr = interestingValue;

if (surelySelector && !startWithSelector && (!prevEqual || !isAttributeInteresting)) {
if (
!options.forceReplace
&& surelySelector
&& !startWithSelector
&& (!prevEqual || !isAttributeInteresting)
) {
// expecting a selector, but got a tag name, let's return it unmodified
// except for "class=" or "id=" or "for="
return startSplitChar + tempElement;
Expand Down

0 comments on commit 97c60df

Please sign in to comment.