derya
Version:
Multi-Parser & Code-Generator, developed with TypeScript on node.js.
670 lines (628 loc) • 27.6 kB
text/typescript
//Imports
import {Grabber, TableValues} from "./grabber";
import * as sys from "samara";
import * as uniques from "./ref/html_tags_unique.json";
//Constants
const generatedMethods:string = "//Generated-Methods";
const url_css_functions:string = "https://www.w3schools.com/cssref/css_functions.asp";
const url_css_properties:string = "https://www.w3schools.com/cssref/default.asp";
const url_css_selectors:string = "https://www.w3schools.com/cssref/css_selectors.asp";
const url_html_event_atts:string = "https://www.w3schools.com/TAGS/ref_eventattributes.asp";
const url_html_global_atts:string = "https://www.w3schools.com/TAGS/ref_standardattributes.asp";
const url_html_tags:string = "https://www.w3schools.com/TAGS/default.ASP";
//Classes
export class Generator{
//Declarations
//Constructor
constructor(){
}
//Methods
async createCSSFunctions(){
console.log("createCSSFunctions");
let grabber:Grabber = new Grabber(url_css_functions);
await grabber.read();
let tableValues:TableValues = grabber.getTable("<h2>CSS Functions</h2>");
let values:string[] = [];
for(let row of tableValues.rows){
//console.log("ROW0: " + row[0]);
let value:string = row[0];
value = sys.removeTags(value).trim().toLowerCase();
//console.log("VALUE: " + value);
values.push(value);
}
this.saveCSSFunctions(values);
}
async createCSSProperties(){
console.log("createCSSProperties");
let grabber:Grabber = new Grabber(url_css_properties);
await grabber.read();
let char:string = "A";
let count:number = 0;
let emptyProperties:string[] = [];
let properties:CSSProperty[] = [];
while(count < 26){
//console.log("CHAR: " + char);
if(grabber.sc.indexOf("<h2>" + char + "</h2>") > -1){
//console.log("CHAR: " + char);
let tableValues:TableValues = grabber.getTable("<h2>" + char + "</h2>");
for(let row of tableValues.rows){
//console.log("ROW: " + row[0]);
if(row[0].indexOf("href") > -1){
let url:string = "https://www.w3schools.com/cssref/" + this.extractHREF(row[0]);
//console.log("URL: " + url);
let grabber:Grabber = new Grabber(url);
await grabber.read();
let name = extractName(grabber.sc);
//console.log("NAME: " + name);
let tableValues:TableValues = grabber.getTable("<h2>Property Values</h2>");
let subValues:string[] = [];
for(let attValues of tableValues.rows){
let value:string = attValues[0];
if(value.indexOf("<") > -1){
//console.log("TTT: " + value);
if(value.indexOf("<br>") < 0){
value = "#" + sys.removeTags(value).trim().toLowerCase();
subValues.push(value);
}else{
let split:string[] = value.split("<br>");
for(let value of split){
value = value.trim().toLowerCase()
if(!sys.isNull(value)){
if(value.indexOf("<") > -1){
value = "#" + sys.removeTags(value).trim().toLowerCase();
subValues.push(value);
}else{
subValues.push(value.trim().toLowerCase());
}
}
}
}
}else{
subValues.push(value.trim().toLowerCase());
}
}
//console.log("VALUE: " + subValues);
properties.push(new CSSProperty(name, subValues));
}else{
emptyProperties.push(row[0]);
}
}
}
char = nextChar(char);
count++;
}
this.saveCSSProperties(properties, emptyProperties);
//console.log("PROPERTIES: " + properties);
//SubFunctions
function extractName(str:string):string{
str = str.substring(str.indexOf("<h1>"), str.length);
str = str.substring(str.indexOf("<span"), str.length);
str = str.substring(str.indexOf(">") + 1, str.length);
str = str.substring(0, str.indexOf("</span>"));
return str.trim().toLowerCase();
}
function nextChar(char:string):string{
return String.fromCharCode(char.charCodeAt(0) + 1);
}
}
async createCSSSelectors(){
console.log("createCSSSelectors");
let grabber:Grabber = new Grabber(url_css_selectors);
await grabber.read();
let tableValues:TableValues = grabber.getTable("<h2>CSS Selectors</h2>");
let values:string[] = [];
for(let row of tableValues.rows){
//console.log("ROW0: " + row[0]);
let value:string = row[0];
value = sys.removeTags(value).trim().toLowerCase();
//console.log("VALUE: " + value);
values.push(value);
}
this.saveCSSSelectors(values);
}
async createHTMLEventAttributes(){
console.log("createHTMLEventAttributes");
let grabber:Grabber = new Grabber(url_html_event_atts);
await grabber.read();
let events_window:string[] = extractEvents("<h2>Window Event Attributes</h2>");
let events_form:string[] = extractEvents("<h2>Form Events</h2>");
let events_keyboard:string[] = extractEvents("<h2>Keyboard Events</h2>");
let events_mouse:string[] = extractEvents("<h2>Mouse Events</h2>");
let events_drag:string[] = extractEvents("<h2>Drag Events</h2>");
let events_clipboard:string[] = extractEvents("<h2>Clipboard Events</h2>");
let events_media:string[] = extractEvents("<h2>Media Events</h2>");
let events_misc:string[] = extractEvents("<h2>Misc Events</h2>");
this.saveHTMLEventAttributes(events_window, events_form, events_keyboard, events_mouse, events_drag,
events_clipboard, events_media, events_misc);
//SubFunctions
function extractEvents(search:string):string[]{
let tableValues:TableValues = grabber.getTable(search);
let events:string[] = [];
for(let row of tableValues.rows){
let event:string = row[0];
if(event.indexOf("<") > -1){
event = event.substring(event.indexOf(">") + 1, event.length);
event = event.substring(0, event.indexOf("<"));
}
event = event.trim().toLowerCase();
events.push(event);
}
return events;
}
}
async createHTMLGlobalAttributes(){
console.log("createHTMLGlobalAttributes");
let grabber:Grabber = new Grabber(url_html_global_atts);
await grabber.read();
let tableValues:TableValues = grabber.getTable("<h2>HTML Global Attributes</h2>");
let values:HTMLAttribute[] = [];
for(let row of tableValues.rows){
let url:string = "https://www.w3schools.com/TAGS/" + this.extractHREF(row[0]);
let grabber:Grabber = new Grabber(url);
await grabber.read();
let name = extractName(grabber.sc);
let tableValues:TableValues = grabber.getTable("<h2>Attribute Values</h2>");
let subValues:string[] = [];
for(let attValues of tableValues.rows){
let attValue:string = attValues[0].toLowerCase();
if(attValue.indexOf("<") > -1){
attValue = "#" + sys.removeTags(attValue);
}
subValues.push(attValue);
}
values.push(new HTMLAttribute(name, subValues));
}
this.saveHTMLGlobalAttributes(values);
//SubFunctions
function extractName(str:string):string{
str = str.substring(str.indexOf("<h1>"), str.length);
str = str.substring(str.indexOf("<span"), str.length);
str = str.substring(str.indexOf(">") + 1, str.length);
str = str.substring(0, str.indexOf("</span>"));
return str.trim().toLowerCase();
}
}
async createHTMLTags(){
console.log("createHTMLTags");
let grabber:Grabber = new Grabber(url_html_tags);
await grabber.read();
let tableValues:TableValues = grabber.getTable("<h2>HTML Tags Ordered Alphabetically</h2>");
let values:HTMLTag[] = [];
for(let row of tableValues.rows){
if(row[1].indexOf("Not supported in HTML5.") < 0){
let url:string = "https://www.w3schools.com/TAGS/" + this.extractHREF(row[0]);
//console.log("URL: " + url);
if(!this.isForbiddenURL(url)){
let grabber:Grabber = new Grabber(url);
await grabber.read();
let name:string = extractName(grabber.sc);
//console.log("Name: " + name);
let closed:Boolean = isClosed(grabber.sc, name);
//console.log("Closed: " + closed);
let events:Boolean = supportsEvents(grabber.sc, name);
//console.log("Events: " + events);
let globals:Boolean = supportsGlobals(grabber.sc, name);
//console.log("Globals: " + globals);
let unique:Boolean = isUnique(name);
//console.log("Unique: " + unique);
let tag:HTMLTag = new HTMLTag(name, closed, events, globals, unique);
let tableValues:TableValues = grabber.getTable("<h2>Attributes</h2>");
for(let tableValue of tableValues.rows){
//console.log("ATTS: " + tableValue[0] + " || " + tableValue[1]);
let attname:string = tableValue[0];
attname = attname.substring(attname.indexOf(">") + 1, attname.length);
attname = attname.substring(0, attname.indexOf("<")).trim().toLowerCase();
//console.log("Attname: " + attname);
let split:string[] = tableValue[1].split("<br>");
let vals:string[] = [];
for(let val of split){
if(!sys.isNull(val)){
val = val.trim().toLowerCase();
if(val.indexOf("<") > -1){
val = "#" + sys.removeTags(val);
}
//console.log("Attval: " + val);
vals.push(val);
}
}
tag.addAttribute(new HTMLAttribute(attname, vals));
}
values.push(tag);
}
}
}
this.saveHTMLTags(values);
//SubFunctions
function extractName(sc:string):string{
sc = sc.substring(sc.indexOf("<h1>"), sc.length);
sc = sc.substring(sc.indexOf("<") + 4, sc.length);
sc = sc.substring(0, sc.indexOf(">"));
sc = sys.removeAll(sc, "!")
return sc.trim().toLowerCase();
}
function isClosed(sc:string, name:string):Boolean{
if(sc.indexOf("/" + name) > -1){
return true;
}else{
return false;
}
}
function isUnique(name:string):Boolean{
for(let tag of uniques.tags){
if(tag === name){
return true;
}
}
return false;
}
function supportsEvents(sc:string, name:string):Boolean{
if(sc.indexOf("<a href=\"ref_eventattributes.asp\">Event Attributes in HTML</a>") > -1){
return true;
}else{
return false;
}
}
function supportsGlobals(sc:string, name:string):Boolean{
if(sc.indexOf("<a href=\"ref_standardattributes.asp\">Global Attributes in HTML</a>") > -1){
return true;
}else{
return false;
}
}
}
extractHREF(str:string):string{
if(str.indexOf("href=\"") > -1){
str = str.substring(str.indexOf("href=\"") + 6, str.length);
str = str.substring(0, str.indexOf("\""));
}
return str;
}
generateSourcecode(){
console.log("generateSourcecode");
let adds:string[] = [];
let closes:string[] = [];
let opens:string[] = [];
let atts:string[] = [];
let styles:string[] = [];
let json = JSON.parse(sys.readFile("./lib/ref/html_tags.json"));
for(let tag of json.tags){
//console.log("TAG: " + tag.name);
if(tag.closed){
closes.push(tag.name);
opens.push(tag.name);
}else{
adds.push(tag.name);
}
for(let att of tag.attributes){
if(!exists(atts, att.name)){
//console.log("X1: " + att.name);
atts.push(att.name);
}
}
}
json = JSON.parse(sys.readFile("./lib/ref/html_event_attributes.json"));
for(let att of json.attributes){
if(!exists(atts, att.name)){
//console.log("X2: " + att.name);
atts.push(att.name);
}
}
json = JSON.parse(sys.readFile("./lib/ref/html_global_attributes.json"));
for(let att of json.attributes){
if(!exists(atts, att.name)){
//console.log("X3: " + att.name);
atts.push(att.name);
}
}
json = JSON.parse(sys.readFile("./lib/ref/css_properties.json"));
for(let prop of json.properties){
styles.push(prop.name);
}
for(let prop of json.emptyProperties){
styles.push(prop);
}
//Tags
let sc_add:sys.SourceObject = new sys.SourceObject();
for(let data of adds){
if(data !== "doctype"){
sc_add.add("add" + createName(data) + "():HTMLElement{", 1);
sc_add.add("return this.addTagUnsafe(\"" + data + "\");", 2);
sc_add.add("}", 1);
}
}
let sc_close:sys.SourceObject = new sys.SourceObject();
for(let data of closes){
sc_close.add("close" + createName(data) + "():HTMLElement{", 1);
sc_close.add("return this.closeTagUnsafe(\"" + data + "\");", 2);
sc_close.add("}", 1);
}
let sc_open:sys.SourceObject = new sys.SourceObject();
for(let data of opens){
sc_open.add("open" + createName(data) + "():HTMLElement{", 1);
sc_open.add("return this.openTagUnsafe(\"" + data + "\");", 2);
sc_open.add("}", 1);
}
let sc_ts:string = sys.readFile("./lib/html_sourcecode.ts");
sc_ts = sc_ts.substring(0, sc_ts.indexOf(generatedMethods) + generatedMethods.length);
sc_ts += "\n" + sc_add.getString();
sc_ts += "\n" + sc_close.getString();
sc_ts += "\n" + sc_open.getString();
sc_ts += "}";
sys.writeFile("./lib/html_sourcecode.ts", sc_ts);
//Attributes & Styles
let sc_att:sys.SourceObject = new sys.SourceObject();
for(let data of atts){
sc_att.add("addAttribute" + createName(data) + "(value:string):void{", 1);
sc_att.add("this.addAttributeUnsafe(\"" + data + "\", value);", 2);
sc_att.add("}", 1);
}
let sc_style:sys.SourceObject = new sys.SourceObject();
for(let data of styles){
sc_style.add("addStyle" + createName(data) + "(value:string):void{", 1);
sc_style.add("if(this.validateStyleValue(\"" + data + "\", value)){", 2);
sc_style.add("this.addStyleUnsafe(\"" + data + "\", value);", 3);
sc_style.add("}", 2);
sc_style.add("}", 1);
}
sc_ts = sys.readFile("./lib/html_element.ts");
sc_ts = sc_ts.substring(0, sc_ts.indexOf(generatedMethods) + generatedMethods.length);
sc_ts += "\n" + sc_att.getString();
sc_ts += "\n" + sc_style.getString();
sc_ts += "}";
sys.writeFile("./lib/html_element.ts", sc_ts);
//CSS-Properties
let sc_css:sys.SourceObject = new sys.SourceObject();
for(let data of styles){
sc_css.add("addProperty" + createName(data) + "(value:string):void{", 1);
sc_css.add("this.addPropertyUnsafe(\"" + data + "\", value);", 2);
sc_css.add("}", 1);
}
sc_ts = sys.readFile("./lib/css_element.ts");
sc_ts = sc_ts.substring(0, sc_ts.indexOf(generatedMethods) + generatedMethods.length);
sc_ts += "\n" + sc_css.getString();
sc_ts += "}";
sys.writeFile("./lib/css_element.ts", sc_ts);
//SubFunctions
function createName(str:string):string{
str = sys.removeAll(str, "@");
//str = sys.removeAll(str, "*");
if(str.indexOf("-") < 0){
str = sys.capitalizeFirstLetter(str);
}else{
let parts:string[] = str.split("-");
str = "";
for(let part of parts){
str += sys.capitalizeFirstLetter(part);
}
}
return str;
}
function exists(atts:string[], att:string):Boolean{
if(att.indexOf("*") > -1){
return true;
}
if(sys.isNull(att)){
return true;
}
for(let a of atts){
if(a === att){
return true;
}
}
return false;
}
}
isForbiddenURL(url:string):Boolean{
let forbidden:string[] = [];
forbidden.push("https://www.w3schools.com/TAGS/tag_comment.asp");
for(let f of forbidden){
if(f === url){
return true;
}
}
return false;
}
saveCSSFunctions(functions:string[]):void{
console.log("saveCSSFunctions");
let json = new sys.JSONObject();
json.addName("functions");
json.openArray();
for(let i:number = 0; i < functions.length; i++){
json.add("\"" + functions[i] + "\"");
i < functions.length - 1 ? json.addComma() : {};
}
json.closeArray();
sys.writeFile("./lib/ref/css_functions.json", json.getString());
}
saveCSSProperties(properties:any[], emptyProperties:string[]):void{
//console.log("saveCSSProperties");
console.log("TEST: " + properties.length + "/" + emptyProperties.length);
let json = new sys.JSONObject();
json.addName("properties");
json.openArray();
for(let i:number = 0; i < properties.length; i++){
json.openObject();
json.addValue("name", properties[i].name, true, true);
json.addName("values");
json.openArray();
let subValues = properties[i].values;
for(let o:number = 0; o < subValues.length; o++){
json.add("\"" + subValues[o] + "\"");
o < subValues.length - 1 ? json.addComma() : {};
}
json.closeArray();
json.closeObject();
i < properties.length - 1 ? json.addComma() : {};
}
json.closeArray();
json.addComma();
json.addName("emptyProperties");
json.openArray();
for(let i:number = 0; i < emptyProperties.length; i++){
json.add("\"" + emptyProperties[i] + "\"");
i < emptyProperties.length - 1 ? json.addComma() : {};
}
json.closeArray();
sys.writeFile("./lib/ref/css_properties.json", json.getString());
}
saveCSSSelectors(selectors:string[]):void{
console.log("saveCSSSelectors");
let json = new sys.JSONObject();
json.addName("selectors");
json.openArray();
for(let i:number = 0; i < selectors.length; i++){
json.add("\"" + selectors[i] + "\"");
i < selectors.length - 1 ? json.addComma() : {};
}
json.closeArray();
sys.writeFile("./lib/ref/css_selectors.json", json.getString());
}
saveHTMLEventAttributes(window:string[], form:string[], keyboard:string[], mouse:string[], drag:string[],
clipboard:string[], media:string[], misc:string[]):void{
console.log("saveHTMLEventAttributes");
let json = new sys.JSONObject();
json.addName("attributes");
json.openArray();
json.add(get("window", window));
json.add(get("form", form));
json.add(get("keyboard", keyboard));
json.add(get("mouse", mouse));
json.add(get("drag", drag));
json.add(get("clipboard", clipboard));
json.add(get("media", media));
json.add(get("misc", misc));
json.closeArray();
let str = json.getString();
str = sys.replaceAll(str, "},]", "}]");
sys.writeFile("./lib/ref/html_event_attributes.json", str);
//SubFunctions
function get(type:string, data:string[]):string{
let json = new sys.JSONObject();
for(let i:number = 0; i < data.length; i++){
json.openObject();
json.addValue("name", data[i], true, true);
json.addValue("type", type, true, false);
json.closeObject();
json.addComma()
//i < data.length - 1 ? json.addComma() : {};
}
let str = json.getString();
return str.substring(1, str.length - 1);
}
}
saveHTMLGlobalAttributes(values:HTMLAttribute[]):void{
console.log("saveHTMLGlobalAttributes");
let json = new sys.JSONObject();
json.addName("attributes");
json.openArray();
for(let i:number = 0; i < values.length; i++){
json.openObject();
json.addValue("name", values[i].name, true, true);
json.addName("types");
json.openArray();
let subValues = values[i].values;
for(let o:number = 0; o < subValues.length; o++){
json.add("\"" + subValues[o] + "\"");
o < subValues.length - 1 ? json.addComma() : {};
}
json.closeArray();
json.closeObject();
i < values.length - 1 ? json.addComma() : {};
}
json.closeArray();
sys.writeFile("./lib/ref/html_global_attributes.json", json.getString());
}
saveHTMLTags(values:HTMLTag[]):void{
console.log("saveHTMLTags");
let json = new sys.JSONObject();
json.addName("tags");
json.openArray();
for(let i:number = 0; i < values.length; i++){
json.openObject();
json.addValue("name", values[i].name, true, true);
json.addValue("closed", values[i].closed.toString(), false, true);
json.addValue("events", values[i].events.toString(), false, true);
json.addValue("globals", values[i].globals.toString(), false, true);
json.addValue("unique", values[i].unique.toString(), false, true);
json.addName("attributes");
json.openArray();
let subValues = values[i].attributes;
for(let o:number = 0; o < subValues.length; o++){
json.openObject();
json.addValue("name", subValues[o].name, true, true);
json.addName("types");
json.openArray();
let subSubValues = subValues[o].values;
for(let u:number = 0; u < subSubValues.length; u++){
json.add("\"" + subSubValues[u] + "\"");
u < subSubValues.length - 1 ? json.addComma() : {};
}
json.closeArray();
json.closeObject();
o < subValues.length - 1 ? json.addComma() : {};
}
json.closeArray();
json.closeObject();
i < values.length - 1 ? json.addComma() : {};
}
json.closeArray();
sys.writeFile("./lib/ref/html_tags.json", json.getString());
}
async start(download:Boolean){
console.log("Start Generator");
if(download){
console.log("Start Downloads");
await this.createHTMLGlobalAttributes();
await this.createHTMLTags();
await this.createHTMLEventAttributes();
await this.createCSSProperties();
await this.createCSSSelectors();
await this.createCSSFunctions();
}
console.log("Start Sourcecode-Generation");
this.generateSourcecode();
//TODO: All
}
}
//Internal Classes
class CSSProperty{
name:string;
values:string[];
//Constructor
constructor(name:string, values:string[]){
this.name = name;
this.values = values;
}
}
class HTMLAttribute{
//Declarations
name:string;
values:string[];
//Constructor
constructor(name:string, values:string[]){
this.name = name;
this.values = values;
}
}
class HTMLTag{
//Declarations
attributes:HTMLAttribute[];
closed:Boolean;
events:Boolean;
globals:Boolean;
name:string;
unique:Boolean;
//Constructor
constructor(name:string, closed:Boolean, events:Boolean, globals:Boolean, unique:Boolean){
this.name = name;
this.closed = closed;
this.events = events;
this.globals = globals;
this.unique = unique;
this.attributes = []
}
//Methods
addAttribute(attribute:HTMLAttribute):void{
this.attributes.push(attribute);
}
}