Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd3a5ab7

Browse files
committed
version 0.0.1
1 parentfa4181f commitd3a5ab7

File tree

8 files changed

+353
-49
lines changed

8 files changed

+353
-49
lines changed

‎.gitignore‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
node_modules
1+
node_modules
2+
exp*
3+
dist

‎bin/cli.ts‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env node
2+
3+
import{Command}from"commander";
4+
import{divJs}from"../div";
5+
6+
constprogram=newCommand("div");
7+
8+
program
9+
.version("0.0.1")
10+
.description("Div.js")
11+
.requiredOption(
12+
"-p, --patterns <patterns>",
13+
"HTML search patterns, comma-separated"
14+
)
15+
.requiredOption("-d, --destination <path>","Destination base path")
16+
.option("-b, --base <path>","Base search path",process.cwd())
17+
.option("-i, --ignore <patterns>","Ignore patterns, comma-separated","")
18+
.action((options)=>{
19+
consthtmlSearchPatterns:string[]=options.patterns.split(",");
20+
constdestinationBasePath:string=options.destination;
21+
constbaseSearchPath:string=options.base;
22+
constignorePatterns:string[]=options.ignore
23+
?options.ignore.split(",")
24+
:[];
25+
26+
divJs(
27+
htmlSearchPatterns,
28+
destinationBasePath,
29+
baseSearchPath,
30+
ignorePatterns
31+
).catch(console.error);
32+
});
33+
34+
program.parse(process.argv);

‎div.ts‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import{globSync}from"glob";
2+
import{divider}from"./lib/divider";
3+
import{batchProcess}from"./lib/utils";
4+
5+
exportasyncfunctiondivJs(
6+
htmlSearchPatterns:string[],
7+
destinationBasePath:string,
8+
baseSearchPath:string=process.cwd(),
9+
ignorePatterns:string[]=[]
10+
):Promise<void>{
11+
ignorePatterns=[
12+
...ignorePatterns,
13+
"./node_modules/**",
14+
`./${destinationBasePath}/**`,
15+
];
16+
17+
consthtmlFilePaths:string[]=globSync(htmlSearchPatterns,{
18+
cwd:baseSearchPath,
19+
absolute:true,
20+
ignore:ignorePatterns,
21+
});
22+
23+
constpromises=newArray();
24+
25+
for(consthtmlPathofhtmlFilePaths){
26+
constproc=()=>{
27+
returndivider(htmlPath,destinationBasePath);
28+
};
29+
30+
promises.push(proc);
31+
}
32+
33+
constMPP:number=100;//memory per process
34+
awaitbatchProcess(promises,MPP);
35+
}

‎lib/divider.ts‎

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
import{Element,load}from"cheerio";
2+
import{parse,stringify}from"css";
3+
importMQSfrom"css-mediaquery";
4+
import{readFileSync}from"fs";
5+
import{readFile,writeFile}from"fs/promises";
6+
import{cloneDeep}from"lodash";
7+
import{basename,dirname,join,relative,resolve}from"path";
8+
importconfigurationsfrom"../configLoader";
9+
import{screenCats}from"./options";
10+
import{makeDirf}from"./utils";
11+
const{ screenSizes}=configurations;
12+
13+
function_getCSSLinks(htmlFilePath:string):Promise<string[]>{
14+
htmlFilePath=resolve(htmlFilePath);//making abs path
15+
16+
constcssLinks:string[]=[];
17+
18+
returnnewPromise((resolve,reject)=>{
19+
readFile(htmlFilePath,{encoding:"utf8"})
20+
.then((htmlContent:string)=>{
21+
const$=load(htmlContent);
22+
23+
$('link[rel="stylesheet"]').each((_index:number,element:Element)=>{
24+
cssLinks.push(
25+
join(dirname(htmlFilePath),$(element).attr("href")??"")
26+
);
27+
});
28+
29+
resolve(cssLinks);
30+
})
31+
.catch(reject);
32+
});
33+
}
34+
35+
function_writeCSS(
36+
newCssFilePath:string,
37+
stylesheet:Record<string,any>
38+
):Promise<void>{
39+
returnnewPromise((resolve,reject)=>{
40+
makeDirf(dirname(newCssFilePath));
41+
42+
writeFile(newCssFilePath,stringify(stylesheet),{encoding:"utf8"})
43+
.then(resolve)
44+
.catch(reject);
45+
});
46+
}
47+
48+
function_replaceCSSLinks(
49+
htmlPath:string,
50+
destinationPath:string,
51+
newcssLinks:string[]
52+
):Promise<void>{
53+
returnnewPromise((resolve,reject)=>{
54+
readFile(htmlPath,{encoding:"utf8"})
55+
.then((htmlString:string)=>{
56+
const$=load(htmlString);
57+
58+
//remove old links
59+
$('link[rel="stylesheet"]').remove();
60+
61+
for(constcssLinkofnewcssLinks){
62+
constmediaquery:string=`screen and (max-width:${
63+
/*@ts-ignore */
64+
screenSizes[basename(cssLink,".css").slice(-2)]
65+
}px)`;
66+
67+
constcsstag=$(
68+
`<link rel="stylesheet" href="${cssLink}" media="${mediaquery}">`
69+
);
70+
71+
$("head").append(csstag);
72+
}
73+
74+
makeDirf(dirname(destinationPath));
75+
76+
//write to files
77+
writeFile(destinationPath,$.html()??"")
78+
.then(resolve)
79+
.catch(reject);
80+
})
81+
.catch(reject);
82+
});
83+
}
84+
85+
exportasyncfunctiondivider(
86+
htmlFilePath:string,
87+
destinationBasePath:string
88+
){
89+
constdestinationHtmlPath:string=join(
90+
destinationBasePath,
91+
relative(process.cwd(),htmlFilePath)
92+
);
93+
94+
//getting css link from html
95+
constoldCssLinks:string[]=await_getCSSLinks(htmlFilePath);
96+
97+
//combined CSS metas
98+
letcombinedCSSContent:string="";
99+
letcombinedFileName:string="";
100+
101+
oldCssLinks.forEach((cssLink:string)=>{
102+
constcssContent:string=readFileSync(cssLink,{encoding:"utf8"});
103+
104+
combinedFileName=`${combinedFileName}-${basename(cssLink,".css")}`;
105+
combinedCSSContent=combinedCSSContent+"\n"+cssContent;
106+
});
107+
108+
//setting reciept watermark in css filename
109+
constwatermark:string="~div-js";
110+
combinedFileName=combinedFileName+watermark;
111+
112+
//combined css getting splitted by diff screen dependency
113+
constrenderedCSS=parse(combinedCSSContent);
114+
115+
//get media blocks with min or max width conditions
116+
constcssWithMediaQueries=
117+
cloneDeep(renderedCSS).stylesheet?.rules.filter(
118+
(rule)=>
119+
rule.type==="media"&&
120+
/*@ts-ignore */
121+
(rule.media.includes("max-width")||rule.media.includes("min-width"))
122+
)??([]asany);
123+
124+
//Non-Device dependant stylesheet
125+
constcommonCSS=cloneDeep(renderedCSS);
126+
/*@ts-ignore */
127+
commonCSS.stylesheet.rules=commonCSS.stylesheet?.rules.filter((rule)=>{
128+
if(
129+
//retain all possible rules except media
130+
rule.type==="rule"||
131+
rule.type==="keyframes"||
132+
rule.type==="font-face"||
133+
rule.type==="supports"||
134+
rule.type==="page"||
135+
rule.type==="charset"||
136+
rule.type==="import"||
137+
rule.type==="document"||
138+
rule.type==="namespace"
139+
){
140+
returntrue;
141+
}elseif(
142+
//retain media css if that is not about max and min width
143+
rule.type==="media"&&
144+
/*@ts-ignore */
145+
!rule.media.includes("max-width")&&
146+
/*@ts-ignore */
147+
!rule.media.includes("min-width")
148+
){
149+
returntrue;
150+
}
151+
152+
returnfalse;
153+
})asany;
154+
155+
//Device dependant stylesheets
156+
constdeviceDependantStylesheets:Partial<Record<screenCats,any>>={};
157+
158+
//list for newly generated links
159+
constnewCssLinks:string[]=[];
160+
161+
//Iterations on Different ScreenSizes
162+
for(constscreenKeyofObject.keys(screenSizes)){
163+
//copy of original css
164+
deviceDependantStylesheets[screenKeyasscreenCats]=
165+
cloneDeep(renderedCSS);
166+
167+
//filter to retain device dependant stylesheet
168+
deviceDependantStylesheets[screenKeyasscreenCats].stylesheet.rules=
169+
cloneDeep(cssWithMediaQueries).filter((rule:any)=>{
170+
//emulating media query function
171+
constmediaQueryMatched:boolean=MQS.match(rule.media,{
172+
/*@ts-ignore */
173+
type:"screen",
174+
width:`${screenSizes[screenKeyasscreenCats]}px`,
175+
});
176+
177+
returnmediaQueryMatched;
178+
});
179+
180+
//combine common and deviceDependant
181+
deviceDependantStylesheets[screenKeyasscreenCats].stylesheet.rules=
182+
deviceDependantStylesheets[
183+
screenKeyasscreenCats
184+
].stylesheet.rules.concat(commonCSS.stylesheet?.rules??[]);
185+
186+
constdirNameofCSS:string=relative(
187+
process.cwd(),
188+
dirname(oldCssLinks[0])
189+
);
190+
191+
constnewCssFilePath:string=join(
192+
destinationBasePath,
193+
dirNameofCSS,
194+
`${combinedFileName}@${screenKey}.css`
195+
);
196+
197+
constrelativeCssPath:string=relative(
198+
dirname(destinationHtmlPath),
199+
newCssFilePath
200+
);
201+
202+
newCssLinks.push(relativeCssPath);
203+
204+
await_writeCSS(
205+
newCssFilePath,
206+
deviceDependantStylesheets[screenKeyasscreenCats]
207+
);
208+
}
209+
210+
returnnewPromise((resolve,reject)=>{
211+
//replace links
212+
_replaceCSSLinks(htmlFilePath,destinationHtmlPath,newCssLinks)
213+
.then(resolve)
214+
.catch(reject);
215+
});
216+
}

‎lib/options.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
typescreenCats="1X"|"2X"|"3X"|"4X"|"5X"|"6X"|"7X";
1+
exporttypescreenCats="1X"|"2X"|"3X"|"4X"|"5X"|"6X"|"7X";
22

33
exportinterfaceConfigurationOptions{
44
screenSizes:Partial<Record<screenCats,number>>;

‎lib/utils.ts‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1+
import{mkdirSync}from"fs";
2+
import{freemem}from"os";
3+
4+
exportfunctionmakeDirf(dirPath:string):void{
5+
mkdirSync(dirPath,{recursive:true});
6+
}
7+
18
exportasyncfunctionbatchProcess(
29
promises:(()=>Promise<any>)[],
3-
batchSize:number
10+
memoryPerProcess:number
411
):Promise<any[]>{
12+
constfreememInMB:number=Math.floor(freemem()/1024/1024);
13+
constbatchSize:number=Math.floor(freememInMB/memoryPerProcess);
14+
515
constpromiseBatches:(()=>Promise<any>)[][]=[];
616

717
for(leti:number=0;i<promises.length;i+=batchSize){

‎package.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name":"div-js",
2+
"name":"@iamspdarsan/div-js",
33
"displayName":"Div.js",
44
"version":"0.0.1",
55
"description":"Div.js is a tool designed to enhance web performance by splitting CSS into multiple files tailored for different devices. By delivering device-specific CSS files, Div.js minimizes network overhead, reduces network costs, and achieves faster load times.",
@@ -31,11 +31,11 @@
3131
"license":"Apache-2.0",
3232
"private":false,
3333
"scripts": {
34-
"dev":"cls && rimraf dist && tsc -p tscdev.json && ncp ./div.config.json ./dist/div.config.json",
34+
"dev":"cls && rimraf dist && tsc -p tscdev.json && ncp ./div.c.json ./dist/div.c.json",
3535
"dr":"yarn dev && yarn rp",
3636
"rp":"node ./dist/div.js",
3737
"test":"jest",
38-
"build":"cls && rimraf dist && tsc -p tsconfig.json && ncp ./div.config.json ./dist/div.config.json",
38+
"build":"cls && rimraf dist && tsc -p tsconfig.json && ncp ./div.c.json ./dist/div.c.json",
3939
"clean":"cls && rimraf dist",
4040
"deploy":"yarn test && yarn build && yarn publish --access public && git push"
4141
},
@@ -79,4 +79,4 @@
7979
"ts-node":"latest",
8080
"typescript":"latest"
8181
}
82-
}
82+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp