Less.js: Less falla al analizar valores válidos de propiedad personalizada (por ejemplo, @apply polyfill)

Creado en 21 oct. 2015  ·  34Comentarios  ·  Fuente: less/less.js

Este código se rompe:

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

Las llaves en el valor de la propiedad rompen el analizador.

Me gustaría que LESS admita la sintaxis @apply , tal como la usa Polymer.
https://www.polymer-project.org/1.0/docs/devguide/styling.html#custom -css-mixins

También probé:

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

No rompió el analizador, pero entregó:

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

que claramente no es un comportamiento deseable.

bug feature request

Comentario más útil

Tenemos una especificación para esto; existe un polyfill; Chrome lo ha implementado; Polymer ya lo está usando en una versión 1.0; y los sitios web ya utilizan Polymer.

Creo que es una expectativa perfectamente razonable que Less admita la sintaxis en un nivel mínimo.

Menos ya pasa @apply , --foo: bar; y var(--foo) . Lo único que falta es hacer que Less pase a través de { ... } en --foo: { property: value; } con el mismo procesamiento básico dado a otros bloques css; en lugar de detenerse bruscamente y generar un error de análisis.

Todos 34 comentarios

Me temo que el soporte de sintaxis que no es CSS está más allá del alcance de Less. Entonces mi -1.

De cualquier manera, tenga en cuenta que puede emitir cualquier código en la salida con escape. P.ej:

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

O de una manera multilínea más pirateada:

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

En situaciones más complejas, siempre es posible usar <strong i="13">@import</strong> (inline) .


En cuanto a intentos como %(~"%d", @ruleset); - No, las variables Less no son macros, no se expanden independientemente del contexto, y específicamente para conjuntos de reglas sin nombre, la única sintaxis adecuada es @ruleset() dentro de un cuerpo de conjunto de reglas y _no_ como un valor de propiedad.

Bueno, estoy de acuerdo con usted en que la sintaxis no estándar generalmente no debería ser compatible.

Sin embargo, esto significa que MENOS es incompatible con el polímero en muchos casos.

Gracias por la respuesta de todos modos. : +1:

No estoy seguro de si esto hace una diferencia en su decisión @ seven-phase-max pero hay una especificación abierta para una regla @apply , http://tabatkins.github.io/specs/css-apply-rule/ # edición -882293bd.

Consulte también https://github.com/Polymer/polymer/issues/1373, ya que parece que Google realmente va a impulsar el proceso.

Y SASS parece estar abordando esto https://github.com/sass/sass/issues/1128

@ donny-dont Nota que no decido nada (no cerré la propuesta), solo soy un crítico.

Bueno, Tab Atkins generó _tens_ de propuestas estándar de CSS (llamadas "ideas") y aunque los chicos de Google pueden introducir esto en su navegador incluso mañana, esto aún está demasiado lejos de convertirse en un borrador de CSS (recuerde CSS vars not entrando en el mundo CSS durante unos diez años?).

@ seven-phase-max disculpas por la implicación. Solo quería señalar que Polymer está impulsando la propuesta de mixin y es probable que Chrome la implemente una vez que esté configurada, lo cual fue algo que @Jamtis realmente no comunicó.

Soy bastante nuevo en el uso de MENOS, ¿hay algún tipo de sistema de complementos para el analizador en este tipo de escenarios? ¿Algo como una bandera experimental que puedes encender y apagar?

Estoy reabriendo esto para poder redirigir las solicitudes duplicadas aquí.

/sub

Tenemos una especificación para esto; existe un polyfill; Chrome lo ha implementado; Polymer ya lo está usando en una versión 1.0; y los sitios web ya utilizan Polymer.

Creo que es una expectativa perfectamente razonable que Less admita la sintaxis en un nivel mínimo.

Menos ya pasa @apply , --foo: bar; y var(--foo) . Lo único que falta es hacer que Less pase a través de { ... } en --foo: { property: value; } con el mismo procesamiento básico dado a otros bloques css; en lugar de detenerse bruscamente y generar un error de análisis.

Creo que la especificación completa de las variables CSS debería ser compatible con LESS. ¡Me encantaría que esto sucediera!

@dantman

Tenemos una especificación para esto; existe un polyfill; Chrome lo ha implementado; Polymer ya lo está usando en una versión 1.0; y los sitios web ya utilizan Polymer.

Para mí, esa todavía no es una razón muy convincente. Eso se traduce en: Google, Google y Google están usando esto. No ha habido ningún interés emergente en ningún otro lugar y no hay indicios de que alguna vez lo haya.

@ donny-dont

Soy bastante nuevo en el uso de MENOS, ¿hay algún tipo de sistema de complementos para el analizador en este tipo de escenarios? ¿Algo como una bandera experimental que puedes encender y apagar?

Hay un sistema de complementos, pero no hay soporte directo para cambiar el análisis. Entonces, eso no sería algo trivial.

@dantman
Tenemos una especificación para esto; existe un polyfill; Chrome lo ha implementado; Polymer ya lo está usando en una versión 1.0; y los sitios web ya utilizan Polymer.

Para mí, esa todavía no es una razón muy convincente. Eso se traduce en: Google, Google y Google están usando esto. No ha habido ningún interés emergente en ningún otro lugar y no hay indicios de que alguna vez lo haya.

Esa conclusión tendría sentido si estuviéramos hablando de una sintaxis más patentada y sin soporte que se desviara significativamente de CSS normal; pero estamos hablando de que Less genera errores de análisis cuando Less ya entiende el anidamiento y la sintaxis en cuestión encaja perfectamente dentro de las reglas de análisis basadas en la coincidencia de corchetes de CSS y no rompe el CSS circundante, y el otro preprocesador y posprocesador de CSS principal está trabajando apoyándolo o ya funciona.

Esa conclusión tendría sentido si estuviéramos hablando de una sintaxis más patentada y sin soporte que se desviara significativamente de CSS normal; pero estamos hablando de que Less genera errores de análisis cuando Less ya entiende el anidamiento y la sintaxis en cuestión encaja perfectamente dentro de las reglas de análisis basadas en la coincidencia de corchetes de CSS y no rompe el CSS circundante, y el otro preprocesador y posprocesador de CSS principal está trabajando apoyándolo o ya funciona.

No es irrelevante. Es bastante similar a los conjuntos de reglas independientes de Less. Y hay un precedente para otras cosas de "transferencia" agregadas a Less. Así que no estoy necesariamente en contra. Escéptico si hay valor más allá de Polymer en este momento.

El soporte oficial para variables CSS se enumera aquí: http://caniuse.com/#feat = css-variables

Versión mínima del navegador para compatibilidad con variables CSS predeterminada

  • Cromo 49
  • Chrome para Android 51
  • Navegador de Android 51
  • Firefox para Android 47
  • Firefox 31
  • Safari 9.1
  • iOS Safari 9.3
  • Ópera 36
  • Opera Mobile 37

Sin un polyfill, esto equivale aproximadamente a un uso global del navegador del 65%.

Con múltiples Polyfills variables CSS disponibles, los navegadores lo implementan y los grandes proveedores de navegadores lo impulsan. Parece que esta sería una característica valiosa.

Especificaciones oficiales: https://drafts.csswg.org/css-variables/

@stramel Eso no tiene nada que ver con este tema. Las variables CSS ya son compatibles con Less. La solicitud es de aproximadamente @apply , que no forma parte de esa especificación.

EDITAR: no se admiten todos los valores de propiedades personalizadas de CSS, consulte a continuación.

@ matthew-dean Lo siento, entendí mal. Independientemente: +1: para CSS Mixins / Custom Property Sets

@ matthew-dean ¿cuál es el listón para menos apoyo? Si se implementó otro navegador, ¿está listo para comenzar?

@ donny-dont Dado que Less es un proyecto comunitario, no hay una barra específica. Pero sí, algo más allá de un solo navegador lo convertiría en una función de uso más general.

Solo si alguien está buscando esto (como lo hice yo): puede poner todo el CSS no estándar de Polymer en un archivo separado e importarlo con la palabra clave en línea en su archivo less. El archivo menos tiene que interactuar entre menos variables y propiedades personalizadas del polímero. Pero esa es la forma en que Polymer lo quiere, de todos modos. Acepte que no puede implementar todas las desviaciones de los estándares.

Solo para revisar esto, creo que desafortunadamente tenía una visión limitada del alcance del problema.

Es decir: sí, @apply es solo una propuesta, PERO INDEPENDIENTEMENTE, _este_ no es un CSS inválido. Ya no.

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

Mi error fue pensar que @apply proponía una extensión de la sintaxis de propiedad personalizada, pero no lo es. El _ES_ anterior es un valor de propiedad personalizado válido y, como tal, debe agregarse a la compatibilidad con Less. Ojalá me hubiera tomado el tiempo de profundizar en la especificación. (Aquí: https://www.w3.org/TR/css-variables/#syntax.)

Less tiene el objetivo principal de admitir CSS válido, y la sintaxis de propiedad personalizada se implementa completamente en todos los navegadores a partir de ahora. La especificación es extremadamente permisiva y puede requerir grandes cambios en la forma en que se analizan los valores de propiedad. Puedes poner casi cualquier cosa en él. No estoy seguro de qué tan loco puede volverse con los valores y si los navegadores lo permitirán. Pero, de la forma en que leo la especificación, casi todo es válido si está bien formado. Es decir, hasta que encuentre una ficha de punto y coma de "nivel superior", puede volverse loco, envolviendo todo tipo de cosas entre llaves o paréntesis.

Esto significa que es cada vez más probable que las bibliotecas de JavaScript como Polymer "pirateen" CSS para colocar propiedades / valores declarativos donde JS los pueda leer, lo que en realidad no era posible antes de esta función de CSS.

Entonces 👍 a implementar lo antes posible.

Lo siento por aquellos que intentaron señalar que esta es una sintaxis de propiedad personalizada válida.

Estoy marcando esto como un error y una solicitud de función porque a) Less reclama analizar valores de propiedad personalizados, pero falla a veces (pero no está claro cuándo), pero b) los tipos de valores que Less necesita manejar están más allá del diseño original de incluso CSS en sí, y mucho menos Less, por lo que es una característica nueva.

Otra prueba que se puede agregar a Menos pruebas para el análisis de propiedades personalizadas. Este es un CSS perfectamente válido a partir de hoy.

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

Esencialmente, una vez que algo está en () [] o {} , puede volcar los caracteres que desee. Entonces, el punto y coma pasaría en el ejemplo anterior. Requiere un análisis recursivo hasta que las llaves coincidan y se cierren (si / cuando se abren) antes de poder probar el punto y coma de cierre.

Comencé ese trabajo aquí, pero aún no estoy seguro de si esto es correcto. https://github.com/less/less.js/blob/edge/lib/less/parser/parser.js#L1326

_Nota: para aclarar si alguien está confundido al mirar la línea anterior, este JavaScript no haría nada. CSS simplemente lo consideraría un valor anónimo largo y desconocido.

Esencialmente, una vez que algo está en () [] o {}, puede volcar los caracteres que desee.

mm, ¿verdad? Para mí, https://www.w3.org/TR/css-variables/#syntax parece que cualquier token (excepto los enumerados allí) puede estar en cualquier lugar (independientemente de cualquier tipo de parens). ¿O esto lo asume algún otro párrafo? ¿Podrías, por favor, señalarme dónde dice sobre cualquier carácter o algo específico sobre los valores dentro de los parens? (a menos que sea url(...) por supuesto)?

En otras palabras, ¿son válidos --var: ?; , --var: (?); o --var: [¾]; ?

Esta es la sección relevante en la parte superior, que puedo estar malinterpretando.

La sintaxis permitida para las propiedades personalizadas es extremadamente permisiva. La producción de <declaration-value> coincide con cualquier secuencia de uno o más tokens, siempre que la secuencia no contenga <bad-string-token> , <bad-url-token> , sin igual <)-token> , <]-token> , o <}-token> , o tokens <semicolon-token> nivel superior o tokens <delim-token> con un valor de "!".

Entonces, las conclusiones importantes son:

  1. Solo importa la ficha de punto y coma de nivel superior. ¿Interpreto que eso significa "no dentro de algún otro par coincidente"? Pero podría estar malinterpretando lo que significa "nivel superior".

  2. Tal vez el ejemplo de JS dado en esa página sea engañoso ( -foo: if(x > 5) this.width = 10; es válido). Pero un = sin espacio ciertamente no es un token CSS típico, ni lo es this.width . Sin aclaraciones, y dado lo permisiva que es la recuperación de errores en los navegadores, no creo que podamos asumir ningún error de análisis para nada. _Ya sabemos_ que la sintaxis @apply es válida (con un conjunto de reglas), incluso si tiene una aplicación personalizada. Entonces sabemos que las propiedades personalizadas permiten múltiples puntos y coma dentro de {} ; Por lo tanto, es lógico que este lenguaje implique algo sobre la naturaleza permisiva dentro de la coincidencia de () , [] , {} . Hay muchas cosas que no sabemos aquí, y sin saber _ qué_ puede ir en una propiedad personalizada, creo que debemos asumir que cualquier cosa puede entrar en ella, siempre que siga una estructura particular ("siempre que la secuencia contienen <bad-string-token> , <bad-url-token> , incomparable <)-token> , <]-token> , o <}-token> ") y pasan esa propiedad al navegador. Creo que la intención aquí es crear la máxima flexibilidad para los desarrolladores, mientras se crean los requisitos mínimos para un análisis exitoso.

Entonces, no puedes hacer esto:

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

... porque la sintaxis quiere permitirle poner cualquier cosa, incluidos varios puntos y coma, pero quiere saber cuándo ha terminado. Ahí es donde entran en juego las comillas / llaves / paréntesis / corchetes coincidentes. Siempre que pueda indicar que ha "cerrado" su sintaxis de alguna manera, creo que la intención aquí es que pueda hacer lo que quiera dentro de esa sintaxis.

En cuanto a esto:

son cualquiera de --var:?;, --var: (?); o --var: [¾]; ¿válido?

No sé.

¿Deberíamos tratarlos como válidos? En mi opinión, sí. Porque no podemos / no podemos saberlo, pero _podemos_ analizarlo correctamente sin demasiados problemas.

En cuanto a la posible implementación ... No es un gran problema permitir nada allí hasta ; pero aún así deberíamos manejar al menos cadenas, urls y {} anidados (ya que pueden contener ; adentro). Obviamente, esto significaría que no hay código Less dentro.

Un paso más allá sería tratarlo (en la etapa de análisis) como una especie de DR (sin su {} externo) con solo más tokens permitidos (aunque parece un camino muerto ya que puede ' t reutilizar DR-parser para algo como --var: (1 > 2) / {whatever} foo; )

Y finalmente, para algo más conveniente, honestamente, no puedo ver nada más que escribir un tokenizador CSS con todas las funciones con algunas de las características Less (tokens y luego su evaluación) permitidas. Un problema biiiiiiiig en otras palabras :(

Solo importa la ficha de punto y coma de nivel superior. ¿Interpreto que eso significa "no dentro de algún otro par coincidente"? Pero podría estar malinterpretando lo que significa "nivel superior".

Sí, estoy bastante seguro de que se trata de la terminación ; . Es decir, como en: --var: ";" url(;) {;}; es válido y --var: ; {} foo; no lo es (el primer ; al ser de "nivel superior" termina la declaración).
Sin embargo, no estoy seguro de solo (;) .

Obviamente, esto significaría que no hay código Less dentro.

Mi único pensamiento es que podríamos permitir la sintaxis de interpolación, en caso de que quisiera generar propiedades personalizadas. Pero tal vez sea una especie de idea de "ronda 2 si hay interés".

Sin embargo, no estoy seguro de solo (;).

¿Yo tampoco? Creo que las especificaciones a menudo tienen detalles de análisis publicados en algún lugar (como diagramas de ruta de token), pero no estoy seguro de si existe en este caso. Como etapa 1: solo se requiere la coincidencia de {} , () y comillas, y volcar cualquier cosa en un nodo anónimo hasta que un ; nivel superior parezca correcto. Los corchetes coincidentes [] pueden no ser necesarios, pero también se mencionan y es bastante trivial una vez que todas las demás piezas están allí.

No creo que necesitemos tokenizar nada especialmente, o mezclar esto con cosas de DR. Después de todo, alguien podría terminar con:

.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;
    }
  }];
}

En otras palabras, sería mejor que Less se limpiara las manos de lidiar con el contenido de las propiedades personalizadas.

Además, es técnicamente factible que un autor de complemento Less escriba un complemento de visitante que tome partes y envíe propiedades personalizadas coincidentes a través del analizador Less para crear nuevos nodos. Todo lo que deberíamos hacer es volcar el contenido en un nodo de reglas y marcar la regla como una propiedad personalizada, y luego volcar fielmente la salida.

Tenga en cuenta que si modificamos el ejemplo anterior, ESTO debería considerarse inválido:

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

"no menos código"

Probablemente, pero esto significa una degradación, como ahora se puede escribir:
--var: darken(red, 5%) + 1;
y funciona, pero luego (por el bien de --fortran: read (*, *, iostat=ierr) radius, height; ) no lo hará :(

Probablemente podamos tener una opción para esto (como --oh-no-yet-another-option-for-custom-properties-to-be-parsed-one-way-or-another: on :)

Probablemente, pero esto significa una degradación, como ahora se puede escribir --var: oscurecer (rojo, 5%); y funciona, pero luego (por el bien de --fortran: read (*, *, iostat = ierr) radius, height;) no lo hará :(

🤔 Bueno ... sí, entiendo lo que quieres decir, ¿por qué tal vez sea necesaria una interpolación de algún tipo? Básicamente, en el analizador podríamos tratar cosas similares a:

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

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

(¿Con las advertencias antes mencionadas de los tokens correspondientes adecuados?)

Quiero decir ... la alternativa es que esencialmente recomendamos escapar de la sintaxis. Sería bueno para menos modificaciones de código CSS en el lugar.

Sí, la interpolación funcionará. A pesar de que todavía sería bueno para una DR-ike sea interpretado como una opción experimental (estoy bastante seguro de que muchos preferirán reales --var: darken(red, 5%); para imaginaria --javascript: 1 = 2; al menos hasta tal propiedad personalizada piratería se generaliza: )

En otras palabras, estoy bien con ambas formas (por separado o simultáneamente).

Creo que tengo una implementación / solución bastante sólida para esto. Usé varios ejemplos de código de este hilo en las pruebas. Por lo tanto, los valores de propiedad personalizados y las reglas at desconocidas se tratan esencialmente como valores entrecomillados de escape para permitir la interpolación. Echa un vistazo al # 3213.

Reparado.

¿Fue útil esta página
0 / 5 - 0 calificaciones