Less.js: Weniger kann gültige Werte für benutzerdefinierte Eigenschaften nicht analysieren (Beispiel: @apply polyfill)

Erstellt am 21. Okt. 2015  ·  34Kommentare  ·  Quelle: less/less.js

Dieser Code bricht ab:

paper-drawer-panel {
  --paper-drawer-panel-left-drawer: {
    background-color: red;
  };
}

Die geschweiften Klammern im Eigenschaftswert unterbrechen den Parser.

Ich möchte, dass WENIGER die von Polymer verwendete Syntax @apply .
https://www.polymer-project.org/1.0/docs/devguide/styling.html#custom -css-mixins

Auch versucht:

paper-drawer-panel {
  <strong i="14">@ruleset</strong>: {
    prop: value;
  };
  --paper-drawer-panel-left-drawer: %(~"%d", @ruleset);
}

Es hat den Parser nicht kaputt gemacht, sondern geliefert:

paper-drawer-panel {
  --paper-drawer-panel-left-drawer: ;
}

Das ist eindeutig kein wünschenswertes Verhalten.

bug feature request

Hilfreichster Kommentar

Wir haben eine Spezifikation dafür; eine Polyfüllung existiert; Chrome hat es implementiert. Polymer verwendet es bereits in einer Version 1.0; und Websites verwenden bereits Polymer.

Ich denke, es ist eine durchaus vernünftige Erwartung für Less, die Syntax auf einem Minimum zu unterstützen.

Weniger geht bereits durch @apply , --foo: bar; und var(--foo) . Das einzige, was fehlt, ist, dass Less die { ... } in --foo: { property: value; } mit der gleichen grundlegenden Verarbeitung wie andere CSS-Blöcke durchläuft. anstatt zum Stillstand zu kommen und einen Analysefehler zu werfen.

Alle 34 Kommentare

Ich befürchte, dass die Unterstützung von Nicht-CSS-Syntax den Rahmen sprengt. Also mein -1.

Beachten Sie in beiden Fällen, dass Sie beliebigen Code mit Escapezeichen in die Ausgabe ausgeben können. Z.B:

xpaper-drawer-panel {
  --paper-drawer-panel-left-drawer: ~"{background-color: red;}";
}

Oder auf mehr hackige mehrzeilige Weise:

paper-drawer-panel {
  -:~";--paper-drawer-panel-left-drawer: {";
    background-color: red;
    color: blue;
  -:~";}";
}

In komplexeren Situationen ist es auch immer möglich, <strong i="13">@import</strong> (inline) .


Bei Versuchen wie %(~"%d", @ruleset); - Nein, weniger Variablen sind keine Makros, sie werden nicht unabhängig vom Kontext erweitert, und speziell für unbenannte Regelsätze lautet die einzig richtige Syntax @ruleset() innerhalb eines Regelsatzkörpers und _not_ as ein Eigenschaftswert.

Nun, ich stimme Ihnen zu, dass nicht standardmäßige Syntax im Allgemeinen nicht unterstützt werden sollte.

Dies bedeutet jedoch, dass WENIGER in vielen Fällen nicht mit Polymer kompatibel ist.

Trotzdem danke für die Antwort. : +1:

Ich bin mir nicht sicher, ob dies einen Unterschied in Ihrer Entscheidung bei sieben Phasen macht, aber es gibt eine offene Spezifikation für eine @apply -Regel, http://tabatkins.github.io/specs/css-apply-rule/ #issue -882293bd.

Siehe auch https://github.com/Polymer/polymer/issues/1373, da es sich so anhört, als würde Google den Prozess wirklich durchsetzen.

Und SASS scheint sich mit diesem https://github.com/sass/sass/issues/1128 zu befassen

@ donny-dont Hinweis Ich entscheide nichts (ich habe den Vorschlag nicht geschlossen) - Ich bin nur ein Kritiker.

Nun, Tab Atkins hat _tens_ von CSS-Standardvorschlägen (mit dem Namen "Ideen") generiert, und obwohl Google-Leute dies vielleicht auch morgen in ihren Browser schieben, ist dies noch zu weit davon entfernt, selbst CSS-Entwurfssache zu werden (denken Sie daran, CSS vars nicht seit ungefähr zehn Jahren in die CSS-Welt eintreten?).

@ Sieben-Phasen-Max Entschuldigung für die Implikation. Ich wollte nur eine Notiz machen, dass Polymer den Mixin-Vorschlag vorantreibt und Chrome ihn wahrscheinlich umsetzen wird, sobald er @Jamtis nicht wirklich kommunizierte.

Ich bin ziemlich neu in der Verwendung von WENIGER. Gibt es in solchen Szenarien ein Plugin-System für den Parser? So etwas wie eine experimentelle Flagge, die Sie ein- und ausschalten können?

Ich öffne dies erneut, um doppelte Anfragen hier umleiten zu können.

/ sub

Wir haben eine Spezifikation dafür; eine Polyfüllung existiert; Chrome hat es implementiert. Polymer verwendet es bereits in einer Version 1.0; und Websites verwenden bereits Polymer.

Ich denke, es ist eine durchaus vernünftige Erwartung für Less, die Syntax auf einem Minimum zu unterstützen.

Weniger geht bereits durch @apply , --foo: bar; und var(--foo) . Das einzige, was fehlt, ist, dass Less die { ... } in --foo: { property: value; } mit der gleichen grundlegenden Verarbeitung wie andere CSS-Blöcke durchläuft. anstatt zum Stillstand zu kommen und einen Analysefehler zu werfen.

Ich denke, die vollständige Spezifikation von CSS-Variablen sollte von WENIGER unterstützt werden. Würde es lieben, wenn dies passiert!

@ Dantman

Wir haben eine Spezifikation dafür; eine Polyfüllung existiert; Chrome hat es implementiert. Polymer verwendet es bereits in einer Version 1.0; und Websites verwenden bereits Polymer.

Für mich ist das immer noch kein sehr zwingender Grund. Das bedeutet: Google, Google und Google verwenden dies. Nirgendwo sonst ist Interesse aufgetaucht, und es gibt keine Anzeichen dafür, dass es jemals welche geben wird.

@ donny-dont

Ich bin ziemlich neu in der Verwendung von WENIGER. Gibt es in solchen Szenarien ein Plugin-System für den Parser? So etwas wie eine experimentelle Flagge, die Sie ein- und ausschalten können?

Es gibt ein Plugin-System, aber keine direkte Unterstützung für das Ändern der Analyse. Das wäre also keine triviale Sache.

@ Dantman
Wir haben eine Spezifikation dafür; eine Polyfüllung existiert; Chrome hat es implementiert. Polymer verwendet es bereits in einer Version 1.0; und Websites verwenden bereits Polymer.

Für mich ist das immer noch kein sehr zwingender Grund. Das bedeutet: Google, Google und Google verwenden dies. Nirgendwo sonst ist Interesse aufgetaucht, und es gibt keine Anzeichen dafür, dass es jemals welche geben wird.

Diese Schlussfolgerung wäre sinnvoll, wenn wir über eine proprietärere und nicht unterstützte Syntax sprechen würden, die erheblich vom normalen CSS abweicht. Wir sprechen jedoch davon, dass weniger Analysefehler generiert, wenn Less die Verschachtelung bereits versteht und die fragliche Syntax perfekt in die auf CSS-Klammern basierenden Analyseregeln passt und das umgebende CSS nicht verletzt. Auch die anderen wichtigen CSS-Präprozessoren und Postprozessoren arbeiten daran es unterstützen oder schon arbeiten.

Diese Schlussfolgerung wäre sinnvoll, wenn wir über eine proprietärere und nicht unterstützte Syntax sprechen würden, die erheblich vom normalen CSS abweicht. Wir sprechen jedoch davon, dass weniger Analysefehler generiert, wenn Less die Verschachtelung bereits versteht und die fragliche Syntax perfekt in die auf CSS-Klammern basierenden Analyseregeln passt und das umgebende CSS nicht verletzt. Auch die anderen wichtigen CSS-Präprozessoren und Postprozessoren arbeiten daran es unterstützen oder schon arbeiten.

Nicht irrelevant. Es ist den losgelösten Regelsätzen von Less ziemlich ähnlich. Und es gibt Präzedenzfälle für andere "Pass-Through" -Stücke, die zu Less hinzugefügt wurden. Ich bin also nicht unbedingt dagegen. Nur skeptisch, wenn es im Moment einen Wert jenseits von Polymer gibt.

Die offizielle Unterstützung für CSS-Variablen finden Sie hier: http://caniuse.com/#feat = css-variables

Minimale Browserversion für die standardmäßige Unterstützung von CSS-Variablen

  • Chrome 49
  • Chrome für Android 51
  • Android Browser 51
  • Firefox für Android 47
  • Firefox 31
  • Safari 9.1
  • iOS Safari 9.3
  • Oper 36
  • Opera Mobile 37

Ohne Polyfill entspricht dies ungefähr 65% der weltweiten Browsernutzung.

Mit mehreren CSS-Variablen-Polyfills, Browsern, die sie implementieren, und großen Browser-Anbietern, die darauf drängen. Es scheint, dass dies eine wertvolle Funktion wäre.

Offizielle Spezifikation: https://drafts.csswg.org/css-variables/

@stramel Das hat nichts mit diesem Problem zu tun. CSS-Variablen werden bereits in Less unterstützt. Die Anfrage betrifft ungefähr @apply , was nicht Teil dieser Spezifikation ist.

BEARBEITEN: Es werden nicht alle benutzerdefinierten CSS-Eigenschaftswerte unterstützt (siehe unten).

@ Matthew-Dean Sorry, ich habe falsch verstanden. Unabhängig davon: +1: für CSS-Mixins / benutzerdefinierte Eigenschaftssätze

@ Matthew-Dean Was ist die Bar für weniger Unterstützung? Wenn ein anderer Browser implementiert ist, ist es dann gut zu gehen?

@ donny-dont Da Less ein Community-Projekt ist, gibt es keine spezielle Bar. Aber ja, etwas jenseits eines einzelnen Browsers würde es zu einer allgemeineren Funktion machen.

Nur wenn jemand danach sucht (wie ich): Sie können alle nicht standardmäßigen CSS von Polymer in eine separate Datei einfügen und diese mit dem Inline-Schlüsselwort in Ihre weniger-Datei importieren. Die weniger Datei muss eine Schnittstelle zwischen weniger Variablen und benutzerdefinierten Eigenschaften des Polymers bilden. Aber so will es Polymer sowieso. Stimmen Sie zu, dass Sie nicht jede Abweichung von Standards implementieren können.

Um dies noch einmal zu wiederholen, ich glaube, ich hatte leider einen engen Überblick über den Umfang des Problems.

Das heißt: Ja, @apply ist nur ein Vorschlag, ABER UNBEDINGT, _dies_ ist _nicht_ ungültiges CSS. Nicht mehr.

paper-drawer-panel {
  --paper-drawer-panel-left-drawer: {
    background-color: red;
  };
}

Mein Fehler war zu denken, dass @apply eine Erweiterung der Syntax der benutzerdefinierten Eigenschaften vorschlägt, dies ist jedoch nicht der Fall. Das obige _IS_ ist ein gültiger benutzerdefinierter Eigenschaftswert und sollte als solcher zur Unterstützung von Less hinzugefügt werden. Ich wünschte, ich hätte mir die Zeit genommen, tiefer in die Spezifikation einzutauchen. (Hier: https://www.w3.org/TR/css-variables/#syntax.)

Less hat das zentrale Ziel, gültiges CSS zu unterstützen, und die Syntax für benutzerdefinierte Eigenschaften ist ab sofort in jedem Browser vollständig implementiert. Die Spezifikation ist äußerst freizügig und erfordert möglicherweise einige große Änderungen in der Art und Weise, wie Eigenschaftswerte analysiert werden. Sie können fast alles hineinstecken. Wie verrückt man mit Werten werden kann und ob Browser dies zulassen, weiß ich nicht genau. Aber so wie ich die Spezifikation lese, ist meistens alles gültig, wenn es gut geformt ist. Das heißt, bis Sie auf ein Semikolon-Token der obersten Ebene stoßen, können Sie verrückt werden und alle möglichen Dinge in geschweifte Klammern oder Klammern einwickeln.

Dies bedeutet, dass JavaScript-Bibliotheken wie Polymer zunehmend CSS "hacken", um deklarative Eigenschaften / Werte dort zu platzieren, wo sie von JS gelesen werden können, was vor dieser CSS-Funktion wirklich nicht möglich war.

Also 👍 um so schnell wie möglich zu implementieren.

Entschuldigen Sie diejenigen, die darauf hinweisen wollten, dass dies eine gültige benutzerdefinierte Eigenschaftssyntax ist.

Ich markiere dies sowohl als Fehler- als auch als Funktionsanforderung, weil a) weniger Ansprüche darauf bestehen, benutzerdefinierte Eigenschaftswerte zu analysieren, aber manchmal fehlschlägt (aber es ist nicht klar, wann), aber b) die Arten von Werten, die weniger verarbeiten müssen, über das ursprüngliche Design von hinausgehen sogar CSS selbst, geschweige denn weniger, so ist es eine neue Funktion.

Ein weiterer Test, der zu Less-Tests für das Parsen von benutzerdefinierten Eigenschaften hinzugefügt werden kann. Dies ist ab heute ein absolut gültiges CSS.

.test {
  --custom-function: () => { let x = 1; window['NAMESPACE'].doSomething(x); };
}

Sobald sich etwas in () [] oder {} , können Sie im Wesentlichen beliebige Zeichen eingeben. Im obigen Beispiel würden Semikolons passieren. Es erfordert eine rekursive Analyse, bis geschweifte Klammern übereinstimmen und geschlossen werden (wenn / wenn sie geöffnet sind), bevor Sie auf ein schließendes Semikolon testen können.

Ich habe diese Arbeit hier begonnen, bin mir aber noch nicht sicher, ob dies korrekt ist. https://github.com/less/less.js/blob/edge/lib/less/parser/parser.js#L1326

_Hinweis: Um zu verdeutlichen, ob jemand verwirrt ist, wenn er sich die obige Zeile ansieht, würde dieses JavaScript nichts tun. CSS würde es nur als langen, unbekannten anonymen Wert betrachten.

Sobald sich etwas in () [] oder {} befindet, können Sie im Wesentlichen beliebige Zeichen eingeben.

mm, ist es? Für mich klingt https://www.w3.org/TR/css-variables/#syntax so, als ob jedes Token (außer den dort aufgeführten) überall dort sein kann (unabhängig von beiden Arten von Parens). Oder wird dies von einem anderen Absatz angenommen? Könnten Sie mich bitte darauf hinweisen, wo es um einen Charakter oder etwas Spezifisches über Werte innerhalb von Parens geht? (es sei denn, es ist natürlich url(...) )?

Mit anderen Worten, sind entweder --var: ?; , --var: (?); oder --var: [¾]; tatsächlich gültig?

Dies ist der relevante Abschnitt oben, den ich möglicherweise falsch interpretiere.

Die zulässige Syntax für benutzerdefinierte Eigenschaften ist äußerst zulässig. Die <declaration-value> -Produktion entspricht einer beliebigen Sequenz eines oder mehrerer Token, solange die Sequenz nicht <bad-string-token> , <bad-url-token> , nicht übereinstimmende <)-token> , <]-token> oder <}-token> oder <semicolon-token> Token der höchsten Ebene oder <delim-token> Token mit dem Wert "!".

Wichtige Imbissbuden sind also:

  1. Nur das Semikolon-Token der obersten Ebene ist von Bedeutung. Ich interpretiere das als "nicht innerhalb eines anderen passenden Paares"? Aber ich könnte falsch interpretieren, was "Top-Level" bedeutet.

  2. Vielleicht ist das auf dieser Seite angegebene JS-Beispiel irreführend ( -foo: if(x > 5) this.width = 10; ist gültig). Aber ein = Leerzeichen ist sicherlich kein typisches CSS-Token, noch ist this.width . Ohne Klarstellung und angesichts der zulässigen Fehlerbehebung in Browsern können wir meines Erachtens keinen Analysefehler für irgendetwas annehmen. Wir wissen bereits, dass die Syntax @apply gültig ist (mit einer Reihe von Regeln), auch wenn es eine benutzerdefinierte Anwendung gibt. Wir wissen also, dass benutzerdefinierte Eigenschaften mehrere Semikolons innerhalb von {} zulassen. Es ist daher logisch, dass diese Sprache etwas über die Zulässigkeit innerhalb der Übereinstimmung von () , [] , {} impliziert. Es gibt eine Menge, die wir hier nicht wissen, und ohne zu wissen, was in einer benutzerdefinierten Eigenschaft enthalten sein kann, müssen wir davon ausgehen, dass alles darin enthalten sein kann, solange es einer bestimmten Struktur folgt ("solange die Sequenz dies nicht tut Enthalten <bad-string-token> , <bad-url-token> , unübertroffene <)-token> , <]-token> oder <}-token> ") und geben Sie diese Eigenschaft an den Browser weiter. Ich glaube, die Absicht hier ist es, maximale Flexibilität für Entwickler zu schaffen und gleichzeitig die Mindestanforderungen für eine erfolgreiche Analyse zu schaffen.

Sie können dies also nicht tun:

.bar {
  --foo: {;
  --baz: ";
}

... weil die Syntax es Ihnen ermöglichen soll, alles einzufügen, einschließlich mehrerer Semikolons, aber sie möchte wissen können, wann Sie fertig sind. Hier kommen die passenden Anführungszeichen / Klammern / Klammern / Klammern ins Spiel. Solange Sie angeben können, dass Sie Ihre Syntax auf irgendeine Weise "geschlossen" haben, besteht hier meines Erachtens die Absicht, dass Sie innerhalb dieser Syntax das tun können, was Sie wollen.

Dazu:

sind entweder von --var:?;, --var: (?); oder --var: [¾]; gültig?

Ich weiß es nicht.

Sollten wir sie als gültig behandeln? IMO ja. Weil wir es nicht wissen / nicht wissen können, aber wir können es erfolgreich analysieren, ohne zu viel Mühe.

Was die mögliche Implementierung betrifft ... Es ist kein großes Problem, dort etwas zuzulassen ; aber dann sollten wir immer noch mindestens Zeichenfolgen, URLs und verschachtelte {} (da sie möglicherweise ; innen). Offensichtlich würde dies bedeuten, dass kein weniger Code enthalten ist .

Ein weiterer Schritt wäre, es (in der Analysephase) als eine Art DR (ohne seine äußeren {} ) zu behandeln, wobei nur mehr Token erlaubt sind (obwohl es wie ein Totweg aussieht, da Sie es können). t DR-Parser für so etwas wie --var: (1 > 2) / {whatever} foo; wiederverwenden)

Und schließlich kann ich für etwas Bequemeres ehrlich gesagt nichts anderes sehen, als einen voll funktionsfähigen CSS-Tokeniser mit einigen der weniger zulässigen Funktionen (Token und deren Auswertung) zu schreiben. Ein biiiiiiiig-Problem mit anderen Worten :(

Nur das Semikolon-Token der obersten Ebene ist von Bedeutung. Ich interpretiere das als "nicht innerhalb eines anderen passenden Paares"? Aber ich könnte falsch interpretieren, was "Top-Level" bedeutet.

Ja, ich bin mir ziemlich sicher, dass es um die Beendigung von ; . Dh wie in: --var: ";" url(;) {;}; ist gültig und --var: ; {} foo; nicht (die ersten ; als "Top-Level" beenden die Anweisung).
Ich bin mir allerdings nicht sicher, ob es nur (;) .

Offensichtlich würde dies bedeuten, dass kein weniger Code enthalten ist.

Mein einziger Gedanke ist, dass wir möglicherweise die Interpolationssyntax zulassen könnten, falls Sie benutzerdefinierte Eigenschaften generieren möchten. Aber vielleicht ist das eine Art "Runde 2, wenn es Interesse gibt" -Idee.

Ich bin mir aber nicht sicher, ob ich nur (;) bin.

Bin ich auch nicht? Ich glaube, dass in Spezifikationen häufig Parsing-Details irgendwo veröffentlicht werden (wie Token-Pfad-Diagramme), aber ich bin mir nicht sicher, ob sie in diesem Fall vorhanden sind. Als Stufe 1 - nur das Übereinstimmen von {} , () und Anführungszeichen und das Ablegen von Daten in einen anonymen Knoten, bis ein ; obersten Ebene in Ordnung zu sein scheint. Passende Klammern [] möglicherweise nicht erforderlich, werden aber auch erwähnt und sind ziemlich trivial, sobald alle anderen Teile vorhanden sind.

Ich denke nicht, dass wir irgendetwas speziell tokenisieren oder dies mit DR-Sachen mischen müssen. Schließlich könnte jemand am Ende Folgendes haben:

.weird {
  --php: ($x = 5 /* + 15 */ + 5; echo $x;);
  --example: [My DR will be --this: { 
    blah: nope;
    --never mind i gave up;
    no wait here it --is: {
      lol: cats;
    }
  }];
}

Mit anderen Worten, es wäre besser für Less, sich die Hände vom Umgang mit dem Inhalt benutzerdefinierter Eigenschaften zu wischen.

Außerdem ist es für einen Less-Plugin-Autor technisch machbar, ein Besucher-Plugin zu schreiben, das Teile nimmt und übereinstimmende benutzerdefinierte Eigenschaften über den Less-Parser zurücksendet, um neue Knoten zu erstellen. Alles, was wir wirklich tun sollten, ist, den Inhalt in einen Regelknoten zu kopieren und die Regel als benutzerdefinierte Eigenschaft zu markieren, und dann die Ausgabe genauso genau zu sichern.

Beachten Sie, dass DIESES als ungültig angesehen werden sollte, wenn wir das obige Beispiel ändern:

.weird {
  --example: [My DR will be --this: { 
    blah: nope;
    --never mind i gave up;
    no wait here it --is: {
      lol: cats;
   // missing matching }
  }];
}

"no Less code"

Wahrscheinlich, aber das bedeutet ein Downgrade - wie jetzt kann man schreiben:
--var: darken(red, 5%) + 1;
und es funktioniert, aber dann (um --fortran: read (*, *, iostat=ierr) radius, height; willen) wird es nicht :(

Wir können wahrscheinlich eine Option dafür haben (wie --oh-no-yet-another-option-for-custom-properties-to-be-parsed-one-way-or-another: on :)

Wahrscheinlich, aber dies bedeutet ein Downgrade - wie jetzt kann man schreiben - var: darken (rot, 5%); und es funktioniert, aber dann (um --fortran willen: lies (*, *, iostat = ierr) Radius, Höhe;) wird es nicht :(

🤔 Nun ... ja, ich verstehe, was du meinst. Deshalb könnte vielleicht eine Interpolation notwendig sein? Grundsätzlich könnten wir beim Parser Dinge behandeln, die ähnlich sind wie:

<strong i="8">@iostat</strong>: ierr;
--fortran: read (*, *, iostat=@{iostat}) radius, height;

// treat similar to:
--fortran: ~"read (*, *, iostat=@{iostat}) radius, height";

(Mit den oben genannten Einschränkungen der richtigen passenden Token?)

Ich meine ... die Alternative ist, dass wir grundsätzlich empfehlen, die Syntax zu umgehen. Wäre einfach schön für weniger Modifikationen des vorhandenen CSS-Codes.

Ja, Interpolation reicht aus. Obwohl es für eine DR-ähnliche Analyse als experimentelle Option immer noch schön wäre (ich bin mir ziemlich sicher, dass viele echte --var: darken(red, 5%); gegenüber imaginären --javascript: 1 = 2; bevorzugen, zumindest bis sich ein solches Hacken von benutzerdefinierten Eigenschaften verbreitet: )

Mit anderen Worten, ich bin in beiden Richtungen in Ordnung (getrennt oder gleichzeitig).

Ich denke, ich habe eine ziemlich robuste Implementierung / Lösung dafür. Ich habe in Tests eine Reihe von Codebeispielen aus diesem Thread verwendet. Daher werden benutzerdefinierte Eigenschaftswerte und unbekannte at-Regeln im Wesentlichen als maskierte Werte in Anführungszeichen behandelt, um eine Interpolation zu ermöglichen. Schauen Sie sich # 3213 an.

Fest.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen