2014-11-24 4 views
5

Ich versuche, eine LESS Mixin schreiben, die Teil einer Zeichenfolge verwendet, um einen Klassennamen zu bilden. Ich erwartete, in der Lage zu sein, replace() zu verwenden, um einen Wert für eine Variable zur Verfügung zu stellen, und dann die Variable in der Regel zu verwenden. Hier ist der Test, den ich schrieb, um zu überprüfen, dass es funktionieren würde:Verwirrt durch LESS replace() -Funktion Verhalten

.foo(@xyz) { 
    @pfx: replace(@xyz, "(.).*", "$1"); 

    [email protected]{pfx}-foo { margin: 0; } 
} 

.foo(abcdefghijklmnop); 

Wenn ich laufe, dass durch lessc (1.7.4) (bearbeiten - auch 2.1.0), es Art-of Werke, Erzeugen dies: So

.aaa-foo { 
    margin: 0; 
} 

, die replace() zupft richtig das erste Zeichen ("a") von der Saite, die ich in geben, aber statt

.a-foo 

es gibt mir

.aaa-foo 

Ich habe für die replace() Funktion an der Quelle sah und es ist schmutz einfach, so dass ich bin nur völlig verwirrt über das, was vor sich geht. (Ich habe die Regex als "^(.).*$" mit dem gleichen Ergebnis ausprobiert.)

ich den Test erweiterte ein wenig:

.foo(@xyz) { 
    @pfx: replace(@xyz, "(.).*", "$1"); 

    [email protected]{pfx}-foo { margin: 0; content: "@{pfx}"; } 
} 

.foo(abcdefghijklmnop); 

, die mir gibt:

.aaa-foo { 
    margin: 0; 
    content: "a"; 
} 

was bedeutet, dass der Regex ist funktioniert gut.

+0

did '.foo (abcdefghijklmnop);' erzeugen '.aaa-foo'? –

+0

@AmitJoki ja. Wenn ich es in '.foo (zebra)' ändere, gibt es mir '.zzz-foo'. – Pointy

+0

@AmitJoki Ich möchte wirklich, dass es '.a-foo' ist - es sieht aus wie LESS intern die Variable den richtigen Wert gibt, aber wenn es die Variable in diesem bestimmten Kontext verwendet (einen Klassennamen in einem Selektor machen) wiederholt es der Wert so. Es ist komisch. – Pointy

Antwort

2

versuchen, diese

.foo(@xyz) { 
    @props: ~`"@{arguments}"`; 

    @pfx: replace(@props, "^(.).*$", "$1"); 

    [email protected]{pfx}-foo { margin: 0; } 
} 

.foo(abcdefghijklmnop); 

EDIT

auch den Kommentar zu beantworten, möchten Sie eine Zeichenfolge übergeben zu ersetzen, tatsächlich eine einfachere Version zu verwenden, wäre .foo(~"abcdefghijklmnop"), die weniger zwingt den Parameter zu berücksichtigen als String ohne Ausgabe der Anführungszeichen.

+0

Verstehen Sie, warum dies einen Unterschied macht? Es funktioniert, aber ich verstehe nicht wie. – Pointy

+0

Ja, es wird ein wenig klarer, obwohl das Verhalten immer noch unerwünscht scheint. Ich würde lieber den 'e()' Ansatz verwenden, weil die eigentlichen Strings, die ich weitergeben werde, Dinge wie 'margin' oder' padding' sind, und Zitate mit '~" "' würden hässlich aussehen. Danke aber für die Einsicht; WENIGER ist nicht meine stärkste Fähigkeit :) – Pointy

2

Try this:

@pfx: e(replace(@xyz, "^(.).*$", "$1")); 

Oder diese:

@pfx: replace(~"@{xyz}", "^(.).*$", "$1"); 

Siehe Dokumentation für die e Funktion.

+0

Ja fand ich gerade dieses auch (über gelegentliches Experiment). Weißt du, warum das funktioniert und warum es nicht notwendig ist, damit '@ {p}' auf der rechten Seite der 'content:' Eigenschaft richtig funktioniert? – Pointy

+0

Ich nehme an, dass es etwas mit der String-Konvertierung zu tun hat. Aber ich kann hier nicht auf das eigentliche Problem hinweisen, um ehrlich zu sein. – haim770

+0

Hmm. Ähnlich verhält es sich mit der neuesten Version (2.1.0). Ich habe einen Fehler protokolliert, um zu sehen, was der Betreuer sagt; Ich bin weit davon entfernt, ein Experte für das Tool zu sein. – Pointy

2

Anscheinend sind ein paar Workarounds vorgesehen, aber wie es funktioniert, ist immer noch ein Mythos.

Der AST nach der Auswertung war völlig richtig, die wie folgt aussieht:

Element { combinator: { value: '', emptyOrWhitespace: true }, 
    value: '.', 
    index: 54, 
    currentFileInfo: 
    { filename: 'input', 
    relativeUrls: undefined, 
    rootpath: '', 
    currentDirectory: '', 
    entryPath: '', 
    rootFilename: 'input' } }, 
Element { combinator: { value: '', emptyOrWhitespace: true }, 
    value: 
    Quoted { escaped: undefined, 
    value: 'a', 
    quote: 'a', 
    index: undefined, 
    currentFileInfo: undefined }, 
    index: 55, 
    currentFileInfo: 
    { filename: 'input', 
    relativeUrls: undefined, 
    rootpath: '', 
    currentDirectory: '', 
    entryPath: '', 
    rootFilename: 'input' } }, 
Element { combinator: { value: '', emptyOrWhitespace: true }, 
    value: '-foo', 
    index: 61, 
    currentFileInfo: 
    { filename: 'input', 
    relativeUrls: undefined, 
    rootpath: '', 
    currentDirectory: '', 
    entryPath: '', 
    rootFilename: 'input' } } 

Aber wenn der CSS-Code zu erzeugen, die Dinge Süden schnell gehen.

Quoted.prototype.genCSS = function (context, output) { 
    if (!this.escaped) { 
     output.add(this.quote, this.currentFileInfo, this.index); 
    } 
    output.add(this.value); 
    if (!this.escaped) { 
     output.add(this.quote); 
    } 
}; 

Quoted Knoten ausgegeben wird der Wert mit Zitat um ihn herum, wenn es nicht entgangen ist. Während das Zitat das erste Zeichen des Wertes ist, sagen wir 'a' in diesem Fall.

Und wenn e() um replace gilt, weniger wird Anonymous Knoten im AST statt Quoted Knoten gesetzt, so wird kein Zitat ausgegeben werden.

+0

Wow. Nun, das ist eine Art von dem, was ich mir vorgestellt habe, nach der Art, wie 'Quoted()' Konstruktor aussieht. Die Funktion 'replace()' setzt das Zitat des Rückgabewerts auf den Wert des Anführungszeichens aus der ursprünglichen Zeichenfolge (oder der leeren Zeichenfolge). – Pointy

+0

Der AST ist falsch. Das von 'replace' für dieses Beispiel erstellte Angebotsobjekt ist ungültig. –

+0

Das 'Ersetzen' funktioniert gut. Aber dann wird der "Quoted" -Knoten in der Auswertungsprozedur selbst evaluieren. und das Zitat (noch '' '') wird an den Inhalt angehängt und dazu verwendet, einen neuen' Quoted' Knoten zu erzeugen. check https://github.com/less/less.js/blob/master/lib/less/tree/quoted.js#L45 – xiaoyi