Skip to content

Commit

Permalink
Merge pull request #24 from hummal/develop
Browse files Browse the repository at this point in the history
1.3.0
  • Loading branch information
philipp-winterle authored May 30, 2021
2 parents de94bbc + 506940a commit fafccd6
Show file tree
Hide file tree
Showing 27 changed files with 5,949 additions and 11,029 deletions.
39 changes: 19 additions & 20 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,26 @@
name: Node.js CI

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
push:
branches: [master]
pull_request:
branches: [master]

jobs:
build:
build:
runs-on: ubuntu-latest

runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.x, 14.x, 15.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

strategy:
matrix:
node-version: [10.x, 12.x, 14.x, 15.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm run build --if-present
- run: npm test
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: yarn
- run: yarn run build --if-present
- run: yarn test
48 changes: 24 additions & 24 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@
name: Node.js Package

on:
release:
types: [created]
release:
types: [created]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- run: npm ci
- run: npm test
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- run: yarn
- run: yarn test

publish-npm:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
registry-url: https://registry.npmjs.org/
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
publish-npm:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
registry-url: https://registry.npmjs.org/
- run: yarn
- run: yarn publish
env:
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.idea
node_modules
tmp/*
tmp/*
yarn-error.log
22 changes: 0 additions & 22 deletions gulpfile.js

This file was deleted.

26 changes: 17 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
"use strict";
global.crittr_project_path = __dirname;

const log = require("signale");
const path = require("path");
const NODE_ENV = process.env.NODE_ENV || "production";

const log = require("signale");
const path = require("path");
const NODE_ENV = process.env.NODE_ENV || "production";
let IS_NPM_PACKAGE = false;
try {
IS_NPM_PACKAGE = !!require.resolve("crittr");
} catch (e) {}

const pathToCrittr = NODE_ENV === "development" && !IS_NPM_PACKAGE ? "src" : "lib";
const Crittr = require(path.join(__dirname, pathToCrittr, 'classes', 'Crittr.class.js'));
const pathToCrittr =
NODE_ENV === "development" && !IS_NPM_PACKAGE ? "lib" : "lib"; // Only keep for later browser support?
const Crittr = require(path.join(
__dirname,
pathToCrittr,
"classes",
"Crittr.class.js"
));

/**
*
Expand All @@ -21,20 +29,20 @@ module.exports = (options) => {
log.time("Crittr Run");

let crittr;
let resultObj = {critical: null, rest: null};
let resultObj = { critical: null, rest: null };

try {
crittr = new Crittr(options);
crittr = new Crittr(options);
} catch (err) {
reject(err);
}

try {
(resultObj = await crittr.run());
resultObj = await crittr.run();
} catch (err) {
reject(err);
}
resolve(resultObj);
log.timeEnd("Crittr Run");
});
};
};
32 changes: 31 additions & 1 deletion lib/Constants.js
Original file line number Diff line number Diff line change
@@ -1 +1,31 @@
const path=require("path"),package_json=require(path.join("..","package.json"));module.exports={PRINT_BROWSER_CONSOLE:!1,DROP_KEYFRAMES:!0,PUPPETEER_HEADLESS:!0,BROWSER_USER_AGENT:"Crittr "+package_json.version,BROWSER_CACHE_ENABLED:!0,BROWSER_JS_ENABLED:!0,BROWSER_CONCURRENT_TABS:10,DEVICE_WIDTH:1200,DEVICE_HEIGHT:1080,DEVICE_SCALE_FACTOR:1,DEVICE_IS_MOBILE:!1,DEVICE_HAS_TOUCH:!1,DEVICE_IS_LANDSCAPE:!1,TIMEOUT:3e4,PAGE_LOAD_TIMEOUT:2e3,PAGE_RENDER_TIMEOUT:300,PAGE_SCREENSHOT:!1,OUTPUT_REMAINING_CSS:!0,RULE_SEPARATOR:"-#-"};
const path = require("path");
const package_json = require(path.join("..", "package.json"));

module.exports = {
// DEFAULTS
PROJECT_DIR: path.resolve(".."),

// CRITTR BASED

PRINT_BROWSER_CONSOLE: false,
DROP_KEYFRAMES: true,
PUPPETEER_HEADLESS: true,
BROWSER_USER_AGENT: "Crittr " + package_json.version,
BROWSER_CACHE_ENABLED: true,
BROWSER_JS_ENABLED: true,
BROWSER_CONCURRENT_TABS: 10,
DEVICE_WIDTH: 1200,
DEVICE_HEIGHT: 1080,
DEVICE_SCALE_FACTOR: 1,
DEVICE_IS_MOBILE: false,
DEVICE_HAS_TOUCH: false,
DEVICE_IS_LANDSCAPE: false,
TIMEOUT: 30000,
PAGE_LOAD_TIMEOUT: 2000,
PAGE_RENDER_TIMEOUT: 300,
PAGE_SCREENSHOT: false,
OUTPUT_REMAINING_CSS: true,

// CODE BASED
RULE_SEPARATOR: "-#-",
};
152 changes: 151 additions & 1 deletion lib/classes/Ast.class.js
Original file line number Diff line number Diff line change
@@ -1 +1,151 @@
const _=require("lodash"),log=require("signale"),CONSTANTS=require("../Constants"),Rule=require("./Rule.class"),hash=require("object-hash"),REMOVEABLE_PROPS=["position"],cleanUnusedProperties=e=>{for(let s in e){REMOVEABLE_PROPS.includes(s)&&delete e[s];const t=e[s];(Array.isArray(t)||"object"==typeof t)&&cleanUnusedProperties(t)}},handleRule=(e,s)=>{if(!Rule.isComment(e))if(cleanUnusedProperties(e),Rule.isMediaRule(e)){const t=Ast.MEDIA_PREFIX+e.media,l=s.get(t),r=e.rules;if(l&&l.length>0){const e=r.filter(e=>{const s=hash.MD5(e);return!l.some(e=>e.hash===s)}).map(e=>({hash:hash.MD5(e),rule:e}));s.set(t,[...l,...e])}else s.set(t,r.map(e=>({hash:hash.MD5(e),rule:e})))}else{const t=Rule.generateRuleKey(e),l=s.get(t),r=hash.MD5(e);l?l.some(e=>e.hash===r)||l.push({hash:r,rule:e}):s.set(t,[{hash:r,rule:e}])}};class Ast{static generateRuleMap(e,s=new Map){if(e.type&&"stylesheet"===e.type&&e.stylesheet&&Array.isArray(e.stylesheet.rules)){const t=e.stylesheet.rules;for(const e of t)handleRule(e,s)}return s}static getAstOfRuleMap(e){const s={type:"stylesheet",stylesheet:{rules:[]}},t=s.stylesheet.rules;for(let[s,l]of e)if(s.includes(Ast.MEDIA_PREFIX)){const e=s.replace(Ast.MEDIA_PREFIX,"");t.push({type:"media",media:e,rules:l.map(e=>e.rule)})}else t.push(...l.map(e=>e.rule));return s}static isMediaObj(e){return e.includes(Ast.MEDIA_PREFIX)}}Ast.TYPES_TO_REMOVE=["comment"],Ast.MEDIA_PREFIX="@media ",module.exports=Ast;
const _ = require('lodash');
const log = require('signale');
const CONSTANTS = require('../Constants');
const Rule = require("./Rule.class");
const hash = require('object-hash');


// PRIVATE VARS
const REMOVEABLE_PROPS = [
"position"
];

// PRIVATE FUNCTIONS
const cleanUnusedProperties = (obj) => {
for (let prop in obj) {
if (REMOVEABLE_PROPS.includes(prop)) {
delete obj[prop];
}

const item = obj[prop];
if (Array.isArray(item) || typeof item === "object") {
cleanUnusedProperties(item);
}
}
};

const handleRule = (ruleObj, map) => {
// Ignore comments
if (!Rule.isComment(ruleObj)) {
cleanUnusedProperties(ruleObj); // Remove position. We don't need that any longer

// Handle MediaQuery
if (Rule.isMediaRule(ruleObj)) {
const media = Ast.MEDIA_PREFIX + ruleObj.media;
const mediaRulesArr = map.get(media);
const mRules = ruleObj.rules;

// There are already media rules in our set
if (mediaRulesArr && mediaRulesArr.length > 0) {
// Filter the rules of the proccessed media query for already existing and only return
// rules that does not exist in the mq map
const newRules = mRules.filter(mRule => {
const objHash = hash.MD5(mRule);
return !mediaRulesArr.some(ruleObj => ruleObj.hash === objHash)
}).map( mRule => {
const objHash = hash.MD5(mRule);
return {
hash: objHash,
rule: mRule
}
});
map.set(media, [...mediaRulesArr, ...newRules]);
} else {
// Fresh media rules can be created
map.set(media, mRules.map(mRule => {
const objHash = hash.MD5(mRule);
return {
hash: objHash,
rule: mRule
}
}));
}
} else {
const ruleKey = Rule.generateRuleKey(ruleObj);
const rulesArray = map.get(ruleKey);
const objHash = hash.MD5(ruleObj);

if (rulesArray) {
// If this rule object (hash) already exists in this ruleKey ignore else insert
if (!rulesArray.some(ruleObj => ruleObj.hash === objHash)) {
rulesArray.push({
hash: objHash,
rule: ruleObj
});
}
} else {
map.set(ruleKey, [
{
hash: objHash,
rule: ruleObj
}
]);
}
}
}
};

/**
* Rule Class with static functions to handle ast management
*
* @static
*/
class Ast {

static generateRuleMap(ast, ruleMap = new Map()) {
if (
ast.type &&
ast.type === "stylesheet" &&
ast.stylesheet &&
Array.isArray(ast.stylesheet.rules)
) {
const restRules = ast.stylesheet.rules;

for (const ruleObj of restRules) {
handleRule(ruleObj, ruleMap);
}
}

return ruleMap;
}

static getAstOfRuleMap(ruleMap) {
const ast = {
"type": "stylesheet",
"stylesheet": {
"rules": []
}
};
const astRules = ast.stylesheet.rules;

for (let [ruleKey, rulesObj] of ruleMap) {
// Is this rule a media query?
if (ruleKey.includes(Ast.MEDIA_PREFIX)) {
const mqStr = ruleKey.replace(Ast.MEDIA_PREFIX, "");
astRules.push({
type: "media",
media: mqStr,
rules: rulesObj.map(ruleObj => {
return ruleObj.rule;
})
})
} else {
astRules.push(...rulesObj.map(ruleObj => ruleObj.rule));
}
}

return ast;
}

static isMediaObj(ruleKey) {
return ruleKey.includes(Ast.MEDIA_PREFIX);
}
}

Ast.TYPES_TO_REMOVE = [
"comment"
];

Ast.MEDIA_PREFIX = "@media ";

module.exports = Ast;
Loading

0 comments on commit fafccd6

Please sign in to comment.