Coder Social home page Coder Social logo

07akioni / css-render Goto Github PK

View Code? Open in Web Editor NEW
199.0 4.0 22.0 956 KB

Generating CSS using JS with considerable flexibility and extensibility, at both server side and client side.

Home Page: css-render.vercel.app

License: MIT License

TypeScript 57.73% JavaScript 23.95% SCSS 17.17% Shell 0.95% HTML 0.20%
css-in-js css preprocessor style

css-render's Introduction

css-render · GitHub Liscense npm Total alerts codecov

Generating CSS using JS with considerable flexibility and extensibility, at both server side and client side.

It's mainly built for library builders (who wants make their library work without css import at small overhead). It's not recommend to use it in a webapp.

It is not designed to totally replace other style-related solutions, but to be a progressive tool which can just work as a supplementary of your style files or totally replace your .css files.

Docs

css-render

Why Using It

  1. You want to ship a library without css at a small price (gzip < 2kb).
  2. Reduce size compared with static css (which contains duplicate logic).
  3. You can't write sass-like or less-like css-in-js (eg. mixin in sass or less).
  4. You want to write style variables in JS.
  5. Support an simple SSR API (now only for vue3).

Comparasion with other CSS-in-JS framework

Main differences between css-render and styled-component, jss or emotion:

  1. It doesn't do the bindings between components and styles. It is more like a style generator with low level mount and unmount API.
  2. It's easier to write like a sass mixin or less mixin.

Examples

Realworld Example

Basic Example

$ npm install --save-dev css-render
import CssRender from 'css-render'
/**
 * CommonJS:
 * const { CssRender } = require('css-render')
 */

const {
  c
} = CssRender()

const style = c('body', ({ props }) => ({
  margin: 0,
  backgroundColor: props.backgroundColor
}), [
  c('&.dark', {
    backgroundColor: 'black'
  }),
  c('.container', {
    width: '100%'
  })
])

/** use it as string */
console.log(style.render({ backgroundColor: 'white' }))
/**
 * or mount on document.head. (the following lines only work in the browser.)
 */
style.mount()
// ...
style.unmount()
body {
  margin: 0;
  background-color: white;
}

body.dark {
  background-color: black;
}

body .container {
  width: 100%;
}

BEM Plugin Example

$ npm install --save-dev css-render @css-render/plugin-bem

You can use bem plugin to generate bem CSS like this:

import CssRender from 'css-render'
import bem from '@css-render/plugin-bem'
/**
 * CommonJS:
 * const { CssRender } = require('css-render')
 * const { plugin: bem } = require('@css-render/plugin-bem')
 */

const cssr = CssRender()
const plugin = bem({
  blockPrefix: '.c-'
})
cssr.use(plugin) // bind the plugin with the cssr instance
const {
  cB, cE, cM
} = plugin

const style = cB(
  'container',
  [
    cE(
      'left, right', 
      {
        width: '50%'
      }
    ),
    cM(
      'dark', 
      [
        cE(
          'left, right',
          {
            backgroundColor: 'black'
          }
        )
      ]
    )
  ]
)

/** use it as string */
console.log(style.render())
/**
 * or mount on document.head
 * the following lines only works in browser, don't call them in node.js
 */
style.mount()
// ...
style.unmount()
.c-container .c-container__left, .c-container .c-container__right {
  width: 50%;
}

.c-container.c-container--dark .c-container__left, .c-container.c-container--dark .c-container__right {
  background-color: black;
}

Packages

Name Cov
css-render codecov
@css-render/plugin-bem codecov
vue3-ssr codecov

css-render's People

Contributors

07akioni avatar dependabot-preview[bot] avatar dependabot[bot] avatar eagleoflqj avatar hitsuki9 avatar keuby avatar talljack avatar volankey avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

css-render's Issues

ShadowDom Support

Hi 07akioni,

I'm planing to use the naive-ui library in combination with custom-elements and a shadow-dom.
Unfortunately this combination is currently not possible, because the styles always get mounted to the main document (tusen-ai/naive-ui#2308).
So I had a look how to add support for this and came across this repository.

Since you are an active member in both repositories, I have the following questions.
Do you plan to continue using css-render in naive-ui and add support for custom-elements here as well?
If so, do you already have an idea how the API of css-render should look like (maybe the possibility to add a custom handler, like ssr)?

I'm asking to help out, not to ask when it's done 😉
In all cases thanks for you great work in both projects.

Best regards
NiewView

Feature: return an object with id keys and style values for vue3-ssr

Hi,

Would it be possible to have a function similar to collect in vue3-ssr but instead of returning a joined string of all the styles, it would be an object { [id]: styleString }?
Nuxt v3.7.0 has just updated how they manage SSR Head with unhead. Before we could return an object { headTags: collect() } in nuxtApp.ssrContext.renderMeta. Now we are using useServerHead({ style: [xxx] }).

So to integrate NaiveUI with Nuxt, we were creating a plugin like this:

import { setup } from '@css-render/vue3-ssr'

export default defineNuxtPlugin((nuxtApp) => {
  if (process.server) {
    const { collect } = setup(nuxtApp.vueApp)
    nuxtApp.ssrContext!.renderMeta = () => {
      return {
        headTags: collect(),
      }
    }
  }
})

But now, we have to do:

mport { setup } from '@css-render/vue3-ssr'

export default defineNuxtPlugin((nuxtApp) => {
    const { collect } = setup(nuxtApp.vueApp)
    useServerHead({
        style: () => {
            const stylesString = collect()
            const stylesArray = stylesString.split(/<\/style>/g).filter(style => style)
            return stylesArray.map((styleString: string) => {
                const match = styleString.match(/<style cssr-id="([^"]*)">([\s\S]*)/)
                if (match) {
                    const id = match[1]
                    return { 'cssr-id': id, children: match[2] }
                }
                return {}
            })
        }
    })
})

so it would be easier to have a function collectAsObject in setup that would return the map of ids and corresponding CSS styles.

Suport default units 'px'

Can you support omitting the default units 'px'? just like React. Thx~

c("body", {
  margin: 4,
});

output

body {
  margin: 4;
}

expect

body {
  margin: '4px'
}

render bug with `@media` and `@supports`

This is my code:

c('@media screen and (min-width: 640px)', [
  c('.scrollbar > .scrollbar__bar', {
    display: 'block',
  }),
]),

In the browser it was converted to:

@media screen and (min-width: 640px) .scrollbar > .scrollbar__bar {
  display: block;
}

The @supports syntax was also not rendered correctly.
And I tried changed them from wrapping CNode[], to use string instead and this time it rendered correctly:

c('@media screen and (min-width: 640px)', `
  .scrollbar > .scrollbar__bar {
     display: block;
  }
`)

使用naiveui+ViteSSR报document is not defined错误

TuSimple/naive-ui version (版本)

2.34.3

Vue version (Vue 版本)

3.2.47

Browser and its version (浏览器及其版本)

Chromium 102.0.5005.167

System and its version (系统及其版本)

Win11 22H2

Node version (Node 版本)

Reappearance link (重现链接)

https://github.com/Ocyss/QiuBlog/tree/ssr

Reappearance steps (重现步骤)

Using n-popover , n-tabs , n-menu all report errors
使用 n-popovern-tabsn-menu 都会报错

Expected results (期望的结果)

正常使用
Normal use

Actual results (实际的结果)

ReferenceError: document is not defined
    at queryElement (E:\Vue\QiuBlog\Blog\web\node_modules\css-render\lib\utils.js:17:5)
    at mount (E:\Vue\QiuBlog\Blog\web\node_modules\css-render\lib\mount.js:59:52)
    at Object.wrappedMount [as mount] (E:\Vue\QiuBlog\Blog\web\node_modules\css-render\lib\c.js:14:45)
    at setup (/node_modules/vueuc/es/binder/src/Follower.js:92:15)
    at callWithErrorHandling (E:\Vue\QiuBlog\Blog\web\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:171:22)
    at setupStatefulComponent (E:\Vue\QiuBlog\Blog\web\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:7194:29)
    at setupComponent (E:\Vue\QiuBlog\Blog\web\node_modules\@vue\runtime-core\dist\runtime-core.cjs.js:7149:11)
    at renderComponentVNode (E:\Vue\QiuBlog\Blog\web\node_modules\@vue\server-renderer\dist\server-renderer.cjs.js:628:17)
    at renderVNode (E:\Vue\QiuBlog\Blog\web\node_modules\@vue\server-renderer\dist\server-renderer.cjs.js:755:22)
    at renderComponentSubTree (E:\Vue\QiuBlog\Blog\web\node_modules\@vue\server-renderer\dist\server-renderer.cjs.js:719:13)

Remarks (补充说明)

mount.js: Add undefined check before referencing `window`

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch [email protected] for the project I'm working on.

This patch adds a small change to the if statement to check the window variable is not undefined before referencing it, following a similar pattern I've seen used in other projects. The reason for the change is that when building a server-side-rendered project using Vite, I get a "ReferenceError: window is not defined" on this line. It builds just fine with the modification in this patch.

Here is the diff that solved my problem:

diff --git a/node_modules/css-render/lib/mount.js b/node_modules/css-render/lib/mount.js
index e1523a0..a78142d 100644
--- a/node_modules/css-render/lib/mount.js
+++ b/node_modules/css-render/lib/mount.js
@@ -5,7 +5,7 @@ exports.mount = exports.unmount = exports.setCount = exports.getCount = void 0;
 const hash_1 = require("./hash");
 const render_1 = require("./render");
 const utils_1 = require("./utils");
-if (window) {
+if (typeof window !== "undefined" && window) {
     window.__cssrContext = {};
 }
 function getCount(el) {

This issue body was partially generated by patch-package.

[Nuxt] document not found

When running naive-ui with inline-theme-disabled an error occurs:

[Vue warn]: Unhandled error during execution of render function 
  at <Layout class="w-full h-screen" has-sider="" >
[nuxt] error caught during app initialization ReferenceError: document is not defined
    at queryElement (/home/ubuntu/main/.output/server/node_modules/css-render/lib/utils.js:17:5)
    at mount (/home/ubuntu/main/.output/server/node_modules/css-render/lib/mount.js:59:52)
    at Object.wrappedMount [as mount] (/home/ubuntu/main/.output/server/node_modules/css-render/lib/c.js:14:45)
    at renderCallback (file:///home/ubuntu/main/.nuxt/dist/server/_nuxt/use-css-vars-class-5be16d4a.js:35:38)
    at Proxy.onRender (file:///home/ubuntu/main/.nuxt/dist/server/_nuxt/use-css-vars-class-5be16d4a.js:48:71)
    at Proxy.render (file:///home/ubuntu/main/.nuxt/dist/server/_nuxt/Layout-5a99573f.js:122:68)
    at renderComponentRoot (/home/ubuntu/main/.output/server/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:906:44)
    at renderComponentSubTree (/home/ubuntu/main/.output/server/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:719:51)
    at renderComponentVNode (/home/ubuntu/main/.output/server/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:644:16)
    at ssrRenderComponent (/home/ubuntu/main/.output/server/node_modules/@vue/server-renderer/dist/server-renderer.cjs.js:94:12) {
  statusCode: 500,
  fatal: false,
  unhandled: false,
  statusMessage: undefined,
  __nuxt_error: true
}

the lines in question are:

const queriedTarget = queryElement(id)

and
export function queryElement (id: string): HTMLStyleElement | null {

this is only specific to Nuxt when running inline-theme-disabled with naive

SSR fails: document is not defined

While rendering the Tabs component from naive-ui in SSR mode, the process fails with this error:

[Vue warn]: Unhandled error during execution of setup function 
  at <XScroll ref="xScrollInstRef" onScroll=fn<debounced> >
ReferenceError: document is not defined
    at Object.queryElement (/dev/node_modules/css-render/lib/utils.js:17:5)
    at Object.mount (/dev/node_modules/css-render/lib/mount.js:62:35)
    at Object.wrappedMount [as mount] (/dev/node_modules/css-render/lib/c.js:14:35)
    at setup (/dev/node_modules/vueuc/lib/x-scroll/src/index.js:32:16)
    at callWithErrorHandling (/dev/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6650:22)

Line 32 of x-scroll is this in my environment:
image

Document not found

While building my application with vite-ssg build I get the refrence error that the document is not defined.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.