Comparing version 1.0.0-development2 to 1.0.0-development3
@@ -187,3 +187,3 @@ /* | ||
// Indicates whether each individual test should be reported during the run | ||
// verbose: undefined, | ||
verbose: true, | ||
@@ -190,0 +190,0 @@ // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode |
181
js/index.js
@@ -0,1 +1,2 @@ | ||
const define = require('./define.js') | ||
const provide = require('./provide.js') | ||
@@ -5,2 +6,5 @@ const extract = require('./extract.js') | ||
const prefers = require('./prefers.js') | ||
const color = require('./color.js') | ||
const reference = require('./reference.js') | ||
const preset = require('./preset.js') | ||
@@ -10,9 +14,13 @@ // caranya bukan parse tapi menggunakan regexp | ||
const config = { | ||
provide: {}, | ||
preset: Object.assign({}, preset, options.preset), | ||
screen: Object.assign({}, screen, options.screen), | ||
prefers: Object.assign({}, prefers), | ||
color: Object.assign({}, color, options.color), | ||
define: {}, | ||
provide: {}, | ||
extract: {} | ||
} | ||
config.provide = provide(options.provide) | ||
config.define = define(options.define, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset}) | ||
config.provide = provide(options.provide, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset, define: config.define}) | ||
config.extract = extract(options.extract) | ||
@@ -22,9 +30,128 @@ | ||
Once (root, {Rule, Declaration, AtRule}) { | ||
root.walkAtRules(/^provide/i, rule => { | ||
root.walkDecls('ref', decl => { | ||
const refs = decl.value.trim() ? Array.from(new Set(decl.value.trim().split(/\s|\|/).filter(i => i !== ''))) : [] | ||
if(refs.length > 0) { | ||
const selectNodes = [] | ||
for(let ref of refs) { | ||
selectNodes.push(...reference(ref, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset})) | ||
} | ||
decl.replaceWith(...selectNodes) | ||
} else { | ||
decl.remove() | ||
} | ||
}) | ||
root.walkAtRules('template', rule => { ///^template/i | ||
const name = new Rule({ selector: '.'+rule.params.replace('.', '').trim() }) | ||
name.append(new Declaration({ prop: 'display', value: 'grid'})) | ||
if(rule.nodes) { | ||
for(let node of rule.nodes) { | ||
if(node.type === 'decl' && node.prop === 'areas') { | ||
name.append(new Declaration({ prop: 'grid-template-areas', value: node.value})) | ||
} else if(node.type === 'decl' && node.prop === 'y') { | ||
name.append(new Declaration({ prop: 'grid-template-rows', value: node.value})) | ||
} else if(node.type === 'decl' && node.prop === 'x') { | ||
name.append(new Declaration({ prop: 'grid-template-columns', value: node.value})) | ||
} else if(node.type === 'decl' && node.prop === 'layout') { | ||
name.append(new Declaration({ prop: 'grid-template', value: node.value})) | ||
} | ||
} | ||
rule.replaceWith(name) | ||
} else { | ||
rule.remove() | ||
} | ||
}) | ||
root.walkAtRules('set', rule => { | ||
const param = rule.params.trim() | ||
if(config.define[param] === undefined) { | ||
const selectNodes = [] | ||
for(let node of rule.nodes) { | ||
if(node.type === 'decl' && node.prop === 'props') { | ||
if(config.define[node.value.trim()]) { | ||
selectNodes.push(config.define[node.value.trim()].join(';')) | ||
} | ||
} else if(node.type === 'decl' && node.prop === 'ref') { | ||
const refs = node.value.trim() ? Array.from(new Set(node.value.trim().split(/\s|\|/).filter(i => i !== ''))) : [] | ||
for(let ref of refs) { | ||
selectNodes.push(...reference(ref, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset})) | ||
} | ||
} else { | ||
selectNodes.push(node) | ||
} | ||
} | ||
config.define[param] = selectNodes | ||
} | ||
rule.remove() | ||
}) | ||
root.walkAtRules('get', rule => { | ||
const param = rule.params.trim() | ||
if(config.define[param]) { | ||
const setRule = new Rule({selector: '.'+param}) | ||
setRule.append(...config.define[param]) | ||
if(rule.nodes) { | ||
for(let node of rule.nodes) { | ||
if(node.type === 'decl' && node.prop === 'emit') { | ||
const refs = node.value.trim() ? Array.from(new Set(node.value.trim().split(/\s|\|/).filter(i => i !== ''))) : [] | ||
for(let ref of refs) { | ||
setRule.append(...reference(ref, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset})) | ||
} | ||
} | ||
} | ||
} | ||
rule.replaceWith(setRule) | ||
} else { | ||
rule.remove() | ||
} | ||
}) | ||
root.walkDecls('props', decl => { | ||
const props = decl.value.trim() | ||
if(props) { | ||
const selectNodes = [] | ||
if(Array.isArray(config.define[props])) { | ||
Array.from(config.define[props]).forEach((item) => { | ||
selectNodes.push(item) | ||
}) | ||
} | ||
decl.replaceWith(selectNodes.join(';')) | ||
} else { | ||
decl.remove() | ||
} | ||
}) | ||
root.walkAtRules('prefers', rule => { | ||
const param = rule.params.trim() | ||
if(config.prefers[prefersParam]) { | ||
const media = new AtRule({name: 'media', params: config.prefers[prefersParam]}) | ||
media.append(node.nodes) | ||
rule.replaceWith(media) | ||
} else { | ||
rule.remove() | ||
} | ||
}) | ||
root.walkAtRules('screen', rule => { | ||
const param = rule.params.trim() | ||
if(config.screen[screenParam]) { | ||
const media = new AtRule({name: 'media', params: `(min-width: ${config.screen[screenParam]})`}) | ||
media.append(node.nodes) | ||
rule.replaceWith(media) | ||
} else { | ||
rule.remove() | ||
} | ||
}) | ||
root.walkAtRules('provide', rule => { | ||
const param = rule.params.trim() | ||
if(config.provide[param] === undefined) { | ||
const selectNodes = [] | ||
for(let node of rule.nodes) { | ||
if(node.name === 'prefers') { | ||
if(node.type === 'atrule' && node.name === 'prefers') { | ||
const prefersParam = node.params.trim() | ||
@@ -38,3 +165,3 @@ if(config.prefers[prefersParam]) { | ||
} | ||
} else if(node.name === 'screen') { | ||
} else if(node.type === 'atrule' && node.name === 'screen') { | ||
const screenParam = node.params.trim() | ||
@@ -48,2 +175,40 @@ if(config.screen[screenParam]) { | ||
} | ||
} else if(node.type === 'atrule' && node.name === 'get') { | ||
const getParam = node.params.trim() | ||
if(config.define[getParam]) { | ||
const setRule = new Rule({selector: '.'+getParam}) | ||
setRule.append(...config.define[getParam]) | ||
if(node.nodes) { | ||
for(let getNode of node.nodes) { | ||
if(getNode.type === 'decl' && getNode.prop === 'emit') { | ||
const refs = getNode.value.trim() ? Array.from(new Set(getNode.value.trim().split(/\s|\|/).filter(i => i !== ''))) : [] | ||
for(let ref of refs) { | ||
setRule.append(...reference(ref, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset})) | ||
} | ||
} | ||
} | ||
} | ||
selectNodes.push(setRule) | ||
} else { | ||
node.remove() | ||
} | ||
} if(node.type === 'rule') { | ||
const setRule = new Rule({selector: node.selector}) | ||
if(node.nodes) { | ||
for(let nd of node.nodes) { | ||
if(nd.type === 'decl' && nd.prop === 'props') { | ||
if(config.define[nd.value.trim()] !== undefined) { | ||
setRule.append(config.define[nd.value.trim()].join(';')) | ||
} | ||
} else if(nd.type === 'decl' && nd.prop === 'ref') { | ||
const refs = nd.value.trim() ? Array.from(new Set(nd.value.trim().split(/\s|\|/).filter(i => i !== ''))) : [] | ||
for(let ref of refs) { | ||
setRule.append(...reference(ref, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset})) | ||
} | ||
} else { | ||
setRule.append(nd) | ||
} | ||
} | ||
} | ||
selectNodes.push(setRule) | ||
} else { | ||
@@ -58,7 +223,7 @@ selectNodes.push(node) | ||
root.walkAtRules(/^inject/i, rule => { | ||
const param = rule.params.trim() //? rule.params.trim().split(/\s|\,/).filter(i => i !== '') : [] | ||
root.walkAtRules('inject', rule => { | ||
const param = rule.params.trim() | ||
if(config.provide[param]) { | ||
rule.replaceWith(config.provide[param]) | ||
rule.replaceWith(...config.provide[param]) | ||
} else { | ||
@@ -65,0 +230,0 @@ rule.remove() |
const postcss = require('postcss') | ||
const glob = require('glob') | ||
const fs = require('fs') | ||
const reference = require('./reference.js') | ||
function readPath(rp) { | ||
function readPath(rp, opts) { | ||
const provide = {} | ||
const data = fs.readFileSync(rp, 'utf8') | ||
const root = postcss.parse(data) | ||
for(let node of root.nodes) { | ||
if(node.name === 'provide') { | ||
provide[node.params.trim()] = node.nodes | ||
for(let rnode of root.nodes) { | ||
if(rnode.type === 'atrule' && rnode.name === 'provide') { | ||
const param = rnode.params.trim() | ||
if(param) { | ||
const selectNodes = [] | ||
for(let node of rnode.nodes) { | ||
if(node.type === 'atrule' && node.name === 'prefers') { | ||
const prefersParam = node.params.trim() | ||
if(opts.prefers[prefersParam]) { | ||
const media = postcss.atRule({name: 'media', params: opts.prefers[prefersParam]}) | ||
media.append(node.nodes) | ||
selectNodes.push(media) | ||
} else { | ||
node.remove() | ||
} | ||
} else if(node.type === 'atrule' && node.name === 'screen') { | ||
const screenParam = node.params.trim() | ||
if(opts.screen[screenParam]) { | ||
const media = postcss.atRule({name: 'media', params: `(min-width: ${opts.screen[screenParam]})`}) | ||
media.append(node.nodes) | ||
selectNodes.push(media) | ||
} else { | ||
node.remove() | ||
} | ||
} else if(node.type === 'atrule' && node.name === 'get') { | ||
const getParam = node.params.trim() | ||
if(opts.define[getParam]) { | ||
const setRule = postcss.rule({selector: '.'+getParam}) | ||
setRule.append(...opts.define[getParam]) | ||
if(node.nodes) { | ||
for(let getNode of node.nodes) { | ||
if(getNode.type === 'decl' && getNode.prop === 'emit') { | ||
const refs = getNode.value.trim() ? Array.from(new Set(getNode.value.trim().split(/\s|\|/).filter(i => i !== ''))) : [] | ||
for(let ref of refs) { | ||
setRule.append(...reference(ref, {screen: config.screen, prefers: config.prefers, color: config.color, preset: config.preset})) | ||
} | ||
} | ||
} | ||
} | ||
selectNodes.push(setRule) | ||
} else { | ||
node.remove() | ||
} | ||
} if(node.type === 'rule') { | ||
const setRule = postcss.rule({selector: node.selector}) | ||
if(node.nodes) { | ||
for(let nd of node.nodes) { | ||
if(nd.type === 'decl' && nd.prop === 'props') { | ||
if(opts.define[nd.value.trim()] !== undefined) { | ||
setRule.append(opts.define[nd.value.trim()].join(';')) | ||
} | ||
} else if(nd.type === 'decl' && nd.prop === 'ref') { | ||
const refs = nd.value.trim() ? Array.from(new Set(nd.value.trim().split(/\s|\|/).filter(i => i !== ''))) : [] | ||
for(let ref of refs) { | ||
setRule.append(...reference(ref, {screen: opts.screen, prefers: opts.prefers, color: opts.color, preset: opts.preset})) | ||
} | ||
} else { | ||
setRule.append(nd) | ||
} | ||
} | ||
} | ||
selectNodes.push(setRule) | ||
} else { | ||
selectNodes.push(node) | ||
} | ||
} | ||
provide[param] = selectNodes | ||
} | ||
} | ||
} | ||
return provide | ||
} | ||
module.exports = (paths) => { | ||
module.exports = (paths, opts) => { | ||
let provide = {} | ||
const coreFiles = fs.readdirSync(__dirname.toString().replace('js', 'css') + '/provide/') | ||
const coreFiles = fs.readdirSync(__dirname.toString().replace('js', 'css') + '/provides/') | ||
if(coreFiles) { | ||
for(let file of coreFiles) { | ||
provide = Object.assign({}, provide, readPath(__dirname.toString().replace('js', 'css') + '/provide/' + file)) | ||
provide = Object.assign({}, provide, readPath(__dirname.toString().replace('js', 'css') + '/provides/' + file, opts)) | ||
} | ||
@@ -30,3 +97,3 @@ } | ||
for(let file of files) { | ||
provide = Object.assign({}, provide, readPath(file)) | ||
provide = Object.assign({}, provide, readPath(file, opts)) | ||
} | ||
@@ -38,3 +105,3 @@ } else if(Array.isArray(paths)) { | ||
for(let file of files) { | ||
provide = Object.assign({}, provide, readPath(file)) | ||
provide = Object.assign({}, provide, readPath(file, opts)) | ||
} | ||
@@ -41,0 +108,0 @@ } |
@@ -7,6 +7,6 @@ module.exports = { | ||
'xl': '1280px', //1200px | ||
'\\2xl': '1440px', //1400px | ||
'\\3xl': '1920px', //1800px | ||
'\\4xl': '2560px', //2400px | ||
'\\5xl': '3440px', //3400px | ||
'2xl': '1440px', //1400px | ||
'3xl': '1920px', //1800px | ||
'4xl': '2560px', //2400px | ||
'5xl': '3440px', //3400px | ||
} |
{ | ||
"name": "alga-css", | ||
"version": "1.0.0-development2", | ||
"description": "Alga CSS is an alternative toolkit based on Tailwind CSS and Bootstrap 5", | ||
"main": "dist/alga-v1.min.css", | ||
"version": "1.0.0-development3", | ||
"description": "Alga CSS is a scoped-first CSS toolkit for quickly compose or share any design between components", | ||
"main": "js/index.js", | ||
"unpkg": "dist/alga-v1.min.css", | ||
@@ -7,0 +7,0 @@ "scripts": { |
<p align="center"> | ||
<a href="https://tedirghazali.gitbook.io" target="_blank" rel="noopener noreferrer"> | ||
<a href="https://algacss.gitlab.io/docs/" target="_blank" rel="noopener noreferrer"> | ||
<img width="180" src="alga-css-logo.png" alt="Alga CSS logo"> | ||
</a> | ||
</p> | ||
<p align="center"> | ||
<a href="https://npmcharts.com/compare/alga-css?minimal=true"><img src="https://img.shields.io/npm/dm/alga-css.svg?sanitize=true" alt="Downloads"></a> | ||
<a href="https://www.npmjs.com/package/alga-css"><img src="https://img.shields.io/npm/v/alga-css.svg?sanitize=true" alt="Version"></a> | ||
<a href="https://www.npmjs.com/package/alga-css"><img src="https://img.shields.io/npm/l/alga-css.svg?sanitize=true" alt="License"></a> | ||
</p> | ||
<br/> | ||
# Alga CSS (formerly tailstrap) | ||
Alga CSS is an alternative toolkit based on Tailwind CSS and Bootstrap 5 classes. This is not a framework but just CSS for my Vue components | ||
# Alga CSS | ||
Alga CSS is a scope-first CSS toolkit for quickly compose or share any design between components | ||
No doubt about the current class names are very confusing because we write the value first and before the colon. So, now we provide a new way to create perfect css names by using dot/period (.) for breakpoint and colon (:) for value. | ||
```html | ||
<!-- current class name --> | ||
<div class="smaller(start:flex)"></div> | ||
All the main features: | ||
1. Created for scoped CSS | ||
2. As a PostCSS plugin | ||
3. Composing or mixing CSS components | ||
4. Provide/inject a large CSS component | ||
5. Custom CSS utility/helper (preset, define, color, screen, etc.) | ||
6. Extract classes from HTML (Petite-Vue, Alpine.js), Astro, Vue, Svelte, and JSX as well | ||
<!-- new class name --> | ||
<div class="xs.flexStart"></div> | ||
## Composable CSS Component (@set, @get, @props and @ref) | ||
<!-- future class name --> | ||
<div class="smaller{flexStart;flexColumn;itemsCenter}"></div> | ||
<div class="xs{flexStart;flexColumn;itemsCenter}"></div> | ||
## Advanced CSS Component (@provide, @inject, @prefers, @screen) | ||
<!-- right now only support single class name --> | ||
<div class="smaller{flexStart}"></div> | ||
<!-- my expectation of class name in the future --> | ||
<div class="smaller{[bg,txt].hex(#168243);bd.rgb(22,130,67);[m,p].value(1rem)}"></div> | ||
<style> | ||
.smaller\{\[bg\,txt\]\.hex\(\#168243\)\;bd\.rgb\(22\,130\,67\)\;\[m\,p\]\.value\(1rem\)\} { | ||
background-color: #168243; | ||
color: #168243; | ||
border-color: rgb(22, 130, 67); | ||
margin: 1rem; | ||
padding: 1rem; | ||
} | ||
</style> | ||
``` | ||
## CSS Utility/Helper |
const postcss = require('postcss') | ||
const algacss = require('../js/') | ||
async function run (input, output, opts = { }) { | ||
async function execute(arg = { input: 'a {}', output: 'a {}', options: {} }) { | ||
let result = await postcss([ | ||
algacss(opts) | ||
]).process(input, { from: undefined }) | ||
expect(result.css).toEqual(output) | ||
algacss(arg.options) | ||
]).process(arg.input, { from: undefined }) | ||
expect(result.css).toEqual(arg.output) | ||
expect(result.warnings()).toHaveLength(0) | ||
} | ||
test('does something', async () => { | ||
await run('a{ }', 'a{ }', { }) | ||
test('First impression working with posecss', async () => { | ||
await execute() | ||
}) | ||
@@ -22,3 +22,3 @@ | ||
}) | ||
]).process('@inject dot;', { from: undefined }) | ||
]).process('@get page;', { from: undefined }) | ||
console.log(result.css) | ||
@@ -25,0 +25,0 @@ }) |
Sorry, the diff of this file is not supported yet
133
70869
5680188
32
3