Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable CSS Modules #1234

Conversation

ChristopherBiscardi
Copy link

This commit adds an option classNames which is a hash from class
name to string. This enables projects to pass in a set of matching
(scoped) classnames generated from CSS Modules.

If there is no hash passed in, or there is no specified class name, we
fall back to the default to keep backwards compatibility.

The following CSS file:

.hljs {
  display: block;
  overflow-x: auto;
  color: #00193a;
  composes: p1 from 'basscss-padding/index.css';
}

.hljs-keyword,
.hljs-selector-tag,
.hljs-title,
.hljs-section,
.hljs-doctag,
.hljs-name,
.hljs-strong {
  font-weight: bold;
}
...

Could produce the following example hash:

{
  hljs: '_css_mono_blue__hljs _node_modules_basscss_padding_index__p1',
  'hljs-keyword': '_css_mono_blue__hljs-keyword',
  'hljs-selector-tag': '_css_mono_blue__hljs-selector-tag',
  'hljs-title': '_css_mono_blue__hljs-title',
  'hljs-section': '_css_mono_blue__hljs-section',
  ...
}

which can then be passed in configure

hljs.configure({ classNames: hash })

This should also keep compatibility with any of the already-created color schemes
since we used the same class names to access the hash object. So a user
currently using solarized could process the style file with CSS Modules and
get scoped class names for pretty much free.

This commit adds an option `classNames` which is a hash from class
name to string. This enables projects to pass in a set of matching
(scoped) classnames generated from CSS Modules.

If there is no hash passed in, or there is no specified class name, we
fall back to the default to keep backwards compatibility.

The following CSS file:

```css
.hljs {
  display: block;
  overflow-x: auto;
  color: #00193a;
  composes: p1 from 'basscss-padding/index.css';
}

.hljs-keyword,
.hljs-selector-tag,
.hljs-title,
.hljs-section,
.hljs-doctag,
.hljs-name,
.hljs-strong {
  font-weight: bold;
}
...
```

Could produce the following example hash:

```javascript
{
  hljs: '_css_mono_blue__hljs _node_modules_basscss_padding_index__p1',
  'hljs-keyword': '_css_mono_blue__hljs-keyword',
  'hljs-selector-tag': '_css_mono_blue__hljs-selector-tag',
  'hljs-title': '_css_mono_blue__hljs-title',
  'hljs-section': '_css_mono_blue__hljs-section',
  ...
}
```
@mpiroc
Copy link

mpiroc commented Jan 15, 2017

What's blocking this change from being accepted?

@isagalaev
Copy link
Member

The universal answer is lack of time. It is also a change to the core, which we're reluctant to just blindly accept without a careful consideration. And as I'm reading through the description I should say that I don't understand what problem is it intended to solve.

@mpiroc
Copy link

mpiroc commented Jan 16, 2017

Thanks for the quick response. With CSS modules, you might write something like this:

// myComponent.js
import { hljsKeyword } from './my/styles.css'
...
<span class={hljsKeyworld}>{'myKeyword'}</span>

and the the generated output would look something like this:

// myGeneratedStylesheet.css
._css_mono_blue__hljs-keyword_whatever {
    ...
}

// index.html
<span class='_css_mono_blue__hljs-keyword_whatever'>myKeyword</span>

This allows you to write a separate stylesheet for each file/component without having to worry about class name conflicts.

The problem is that highlight.js is not aware of these generated filenames, so we would end up with something like this:

// myGeneratedStylesheet.css
._css_mono_blue__hljs-keyword_whatever {
    ...
}

// index.html
<span class='hljs-keyword'>myKeyword</span>

Which doesn't work, because the class names don't match. If we had a way to give highlight.js a mapping from the original class names to the generated class names, it would allow us to use highlight.js with css modules.

@ChristopherBiscardi
Copy link
Author

The universal answer is lack of time. It is also a change to the core, which we're reluctant to just blindly accept without a careful consideration.

👍

And as I'm reading through the description I should say that I don't understand what problem is it intended to solve.

I'm currently using my fork (published as hljs-modules to compose basscss classes and colors.css colors with PostCSS/CSSModules processing.

Sample CSS: pre PostCSS/CSSModules
/* Basscss Highlight */

@import "colors.css/src/_variables.css";

.hljs {
    background: color(#69c lightness(+30%));
    composes: p2 from 'basscss-padding/index.css';
    display: block;
    overflow-x: auto;
    color: #00193a;
    border-left: 2px solid #69c;
    -webkit-text-size-adjust: none;
}
@media only screen and (max-width: 480px) {
    .hljs {
        margin: 1rem -1rem;
    }
}

.hljs-comment,
.diff .hljs-header,
.hljs-javadoc {
  color: var(--hljs-comment);
  font-style: italic;
}

.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
  color: var(--hljs-keyword);
  font-weight: bold;
}

.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
  color: var(--hljs-number);
}

.hljs-string,
.hljs-tag .hljs-value,
.hljs-phpdoc,
.hljs-dartdoc,
.tex .hljs-formula {
  color: var(--hljs-string);
}

.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
  color: var(--hljs-title);
  font-weight: bold;
}

.hljs-list .hljs-keyword,
.hljs-subst {
  font-weight: normal;
}

.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
  color: var(--hljs-type);
  font-weight: bold;
}

.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rules .hljs-property,
.django .hljs-tag .hljs-keyword {
  color: var(--hljs-tag);
  font-weight: normal;
}

.hljs-attribute,
.hljs-variable,
.lisp .hljs-body {
  color: var(--hljs-attribute);
}

.hljs-regexp {
  color: var(--hljs-regexp);
}

.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
  color: var(--hljs-symbol);
}

.hljs-built_in {
  color: var(--hljs-built-in);
}

.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
  color: var(--hljs-preprocessor);
  font-weight: bold;
}

.hljs-deletion {
  background: var(--hljs-deletion);
}

.hljs-addition {
  background: var(--hljs-addition);
}

.diff .hljs-change {
  background: var(--hljs-change);
}

.hljs-chunk {
  color: var(--hljs-chunk);
}


/* Mapped colors */
:root {
  --hljs-comment: var(--gray);
  --hljs-keyword: var(--fuchsia);
  --hljs-number: var(--olive);
  --hljs-string: var(--purple);
  --hljs-title: var(--blue);
  --hljs-type: var(--navy);
  --hljs-tag: var(--navy);
  --hljs-attribute: var(--olive);
  --hljs-regexp: var(--olive);
  --hljs-symbol: var(--purple);
  --hljs-built-in: var(--navy);
  --hljs-preprocessor: var(--gray);
  --hljs-deletion: var(--fuchsia);
  --hljs-addition: var(--lime);
  --hljs-change: var(--navy);
  --hljs-chunk: var(--silver);
}
Then I can import that theme in js and use it to highlight code inside of markdown-it.
const css = require('./css/highlight.css');

function highlight (str, lang) {
  if(lang) {
    if (lang === 'css') {
      const output = midas.process(str);
      return `<pre class="${css['hljs']}">${output}</pre>`;
    } else if (hljs.getLanguage(lang)) {
      try {
        return `<pre class="${css['hljs']}"><code>${hljs.highlight(lang, str, true).value}</code></pre>`;
      } catch (__) {
        console.log('failed to highlight');
      }
    }
  }

  return `<pre class="${css['hljs']}"><code>${md.utils.escapeHtml(str)}</code></pre>`;
}

var md = require('markdown-it')({
  html: true,
  linkify: true,
  typographer: true,
  highlight: highlight,
});

So, using a PostCSS/CSS Modules toolchain, I can use composes from CSS Modules to combine external classes for themes (ex: basscss) and also use multiple themes on the same page (ex: different languages) without worrying about conflicting classnames.

@ChristopherBiscardi
Copy link
Author

closing this since it doesn't seem like it's on any sort of track to be merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants