Skip to content

Commit

Permalink
Merge pull request #3 from ArthusLiang/beta
Browse files Browse the repository at this point in the history
feat(beta): create
  • Loading branch information
ArthusLiang authored Apr 23, 2024
2 parents 27753c8 + e56084a commit 4cc2c77
Show file tree
Hide file tree
Showing 42 changed files with 503 additions and 90 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ This is a repo which helps to convert figma files to Website. This repo will dep
"banner": "🏷️", // node start with this text will be banner in page
"image": "🖼️" // node start with this text will be converted into image
},
"design_guidelines": {
"file": "YOUR FIGMA FILE ID for design_guidelines",
"guidelines": {
"file": "YOUR FIGMA FILE ID for guidelines",
"page": "✅",
"tab": "💻",
"banner": "🏷️",
Expand Down
18 changes: 13 additions & 5 deletions figma/config.json
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
{
"files": {
"home": {
"file": "KyR2f2vCKyUEdANvH9YbLO",
"page": "",
"tab": "💻",
"banner": "🏷️",
"image": "🖼️"
},
"components": {
"file": "Sz5B1aQgnXqsDkd79rMrgD",
"page": "",
"tab": "💻",
"banner": "🏷️",
"image": "🖼️"
},
"design_guidelines": {
"guidelines": {
"file": "CjU6wD6PxTbBOiPj28pa4p",
"page": "",
"tab": "💻",
"banner": "🏷️",
"image": "🖼️"
},
"home": {
"file": "KyR2f2vCKyUEdANvH9YbLO",
"support": {
"file": "crgmNpNVhNd7cAladwXGvs",
"page": "",
"tab": "💻",
"banner": "🏷️",
"image": "🖼️"
},
"momentum_philosophy": {
"philosophy": {
"file": "6ZoNCX3UOxQgqlU96tVt7S",
"page": "",
"tab": "💻",
Expand Down Expand Up @@ -54,6 +61,7 @@
"table_row":"table_row",
"table_cell":"table_cell"
},
"hyperlinkSeparator":"@@"
"hyperlinkSeparator":"@@",
"specialClass":"@class="
}
}
124 changes: 101 additions & 23 deletions figma/src/htmlConvertor/nodeConvertor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ConvertTagType, ExportFilePath, ILocaltion, IDomTreeNode, IHtmlArchor, IConfigSettings } from "../types";
import { ConvertTagType, ExportFilePath, ILocaltion, IDomTreeNode, IHtmlArchor, IConfigSettings, IConfigItem } from "../types";
import { IO } from '../io';
import { ComponentsLib } from './componentsLib';
import { publicResource } from '../api/publicResource';
Expand All @@ -7,7 +7,7 @@ const regTag = /^h\d$/i;
const regHttps = /^https?\:\/\//;
const regHtmlId = /\:|\;|\,/g;
const regNewline = /\n|\r/g;
const TABINDEX="8";
const TABINDEX="1";

export class NodeConvertor {

Expand All @@ -17,6 +17,7 @@ export class NodeConvertor {
imgUrls:Record<string, string>;
archors:Record<string, IHtmlArchor>;
configKey:string;
config:IConfigItem;
configSettings: IConfigSettings;
componentsLib:ComponentsLib;
parentLocaltion:ILocaltion | undefined;
Expand All @@ -26,13 +27,14 @@ export class NodeConvertor {
return names.join('_');
}

constructor(node:IDomTreeNode, configKey:string, configSettings: IConfigSettings, componentsLib:ComponentsLib, parentLocaltion?:ILocaltion) {
constructor(node:IDomTreeNode, configKey:string,config:IConfigItem, configSettings: IConfigSettings, componentsLib:ComponentsLib, parentLocaltion?:ILocaltion) {
this.figmaAPIData = node.figmaAPIData;
this.textComponentName = node.textComponentName;
this.type = node.type;
this.imgUrls = {};
this.archors = {};
this.configKey = configKey;
this.config = config;
this.configSettings = configSettings;
this.componentsLib = componentsLib;
this.parentLocaltion = parentLocaltion;
Expand All @@ -50,25 +52,44 @@ export class NodeConvertor {
}
}

private getImageName(name:string) {
let reg = new RegExp('^'+this.config.image);
return name.replace(reg,'');
}

private img() {
// use componentID
let imageID = this.componentsLib.getImageId(this.figmaAPIData);
// add imgUrls
let url = IO.getAssetsImgUrl(this.configKey, imageID, this.configSettings.exportImage.format);
//let url = path.join(this.assetBaseUrl, imageID);
this.imgUrls[imageID] = url;

this.cssLayout({
display: 'block'
}, true);
let ck = this.checkIfHasLink(this.figmaAPIData.name);
let href= ck.href;
let title;
//this.cssColor();
return `<img tabindex="${TABINDEX}" style="${this.css()}" alt="${this.figmaAPIData.name}" src=${url} />`;
if(ck.hasLink) {
this.styles['background-image'] = `url('${url}')`;
this.styles['background-repeat'] = 'no-repeat';
this.styles['background-position'] = 'center';
this.styles['overflow'] = 'hidden';
title = this.getImageName(ck.arr[0]);
return `<a${href} role="button" tabindex="${TABINDEX}" style="${this.css()}" aria-label="${title}" title="${ title }"></a>`;
} else {
title = this.getImageName(this.figmaAPIData.name);
return `<img tabindex="${TABINDEX}" style="${this.css()}" alt="${ title }" src=${url} />`;
}
}

private toHtmlId(id) {
return id.replace(regHtmlId, '_');
}

private shadowTextNode(content, styleData, differStyle) {
private shadowTextNode(content, styleData?, differStyle?) {
let tag = differStyle ? 'span' : '';
let urlAttr = '';
if(styleData && styleData.hyperlink
Expand All @@ -90,6 +111,7 @@ export class NodeConvertor {

private textInnerHTML(content) {
let chars = this.figmaAPIData.characterStyleOverrides;
// content.length != this.figmaAPIData.characterStyleOverrides.length
if(content && content.length>0 && chars && chars.length>0) {
let innerHTML = [];
let _currentStyle = chars[0];
Expand All @@ -110,6 +132,10 @@ export class NodeConvertor {
//shadowTextNode]
innerHTML.push(this.shadowTextNode(txt,this.figmaAPIData.styleOverrideTable[styleId],differStyles[styleId]));
}
if(content.length>chars.length) {
let lastText = content.slice(chars.length);
innerHTML.push(this.shadowTextNode(lastText));
}
return innerHTML.join('');
}
return content.replace(regNewline,'<br>');
Expand Down Expand Up @@ -142,11 +168,18 @@ export class NodeConvertor {
let tag = 'p';
let urlAttr = '';
let className = '';
let lowerName = (this.textComponentName || this.figmaAPIData.name).toLowerCase();

let classNames = [];
let lowerNodeNames = this.figmaAPIData.name.toLowerCase().split(this.configSettings.specialClass);
let lowerName = this.textComponentName? this.textComponentName.toLowerCase() : lowerNodeNames[0];
// className
if(this.componentsLib.isFontName(lowerName)) {
className = `class="${lowerName}"`;
classNames.push(lowerName);
}
if(lowerNodeNames.length>1) {
classNames.push(lowerNodeNames[1]);
}
if(classNames.length>0) {
className = `class="${classNames.join(' ')}"`;
}

// ifHasLink => a tag
Expand Down Expand Up @@ -184,16 +217,46 @@ export class NodeConvertor {
Object.assign(this.styles, this.cssFont());
let innerHTML = this.textInnerHTML(this.figmaAPIData.characters);


let splitedHTML = innerHTML.split('<br>');
//ul li
if(this.figmaAPIData.lineTypes && this.figmaAPIData.lineTypes.length>0 && this.figmaAPIData.lineTypes.indexOf('UNORDERED')!==-1) {
tag = 'ul';
let innerHTMLS = innerHTML.split('<br>').map((d, i)=>{
return `<li class='${this.figmaAPIData.lineTypes[i]||'None'} ${lowerName}'>${d}</li>`
let innerHTMLS = splitedHTML.map((d, i)=>{
return `<li role="listitem" class="${this.figmaAPIData.lineTypes[i]||'None'} ${lowerName}" tabindex="${TABINDEX}" aria-label="${d}" title="${d}">${d}</li>`
});
innerHTML = innerHTMLS.join('');
}
// disable auto split feature
/*
else if(splitedHTML.length>0 && tag === 'p') {
let innerHTMLS = splitedHTML.map((splitedHTMLLine)=>{
return `<${tag} ${className} ${urlAttr} id="${id}" tabindex="${TABINDEX}" aria-label="${content}" title="${content}" style="${this.css()}" >${splitedHTMLLine}</${tag}>`;
});
return innerHTMLS.join('');
}
*/
let role = 'document';
switch (tag) {
case 'ul':
role = 'list';
break;
case 'p':
role = 'document';
break;
case 'a':
role = 'link';
break;
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6':
role = 'heading';
break;
}

return `<${tag} ${className} ${urlAttr} id="${id}" tabindex="${TABINDEX}" aria-label="${content}" title="${content}" style="${this.css()}" >${innerHTML}</${tag}>`;
return `<${tag} ${className} role="${role}" ${urlAttr} id="${id}" tabindex="${TABINDEX}" aria-label="${content}" title="${content}" style="${this.css()}" >${innerHTML}</${tag}>`;

}

Expand All @@ -213,22 +276,37 @@ export class NodeConvertor {
}
}

private checkIfHasLink(name:string):any {
let arr = name.split(this.componentsLib.settings.hyperlinkSeparator);
let href ='';
let hasLink = false;
if(arr.length===2) {
hasLink = true;
if(regHttps.test(arr[1])) {
href = ` href="${arr[1]}" target="_blank"`;
} else {
href = ` href="${arr[1]}"`;
}
}
return {
hasLink: hasLink,
href: href,
arr: arr
};
}

private div(content:string='') {
let tag = 'div';
let className='';
let href= '';
if(this.figmaAPIData.name && ['table','table_row','table_cell'].indexOf(this.figmaAPIData.name.toLowerCase())!==-1) {
className = `class="${this.figmaAPIData.name.toLowerCase()}"`;
}
let linksArrFromName = this.figmaAPIData.name.split(this.componentsLib.settings.hyperlinkSeparator);
if(linksArrFromName.length===2){
let ck = this.checkIfHasLink(this.figmaAPIData.name);
let href= ck.href;
if(ck.hasLink) {
tag = 'a';
className = `class="block_link"`;
if(regHttps.test(linksArrFromName[1])) {
href = ` href="${linksArrFromName[1]}" target="_blank"`
} else {
href = ` href="${linksArrFromName[1]}"`
}
}
// override links if table elements
if(this.figmaAPIData.name && ['table','table_row','table_cell'].indexOf(this.figmaAPIData.name.toLowerCase())!==-1) {
className = `class="${this.figmaAPIData.name.toLowerCase()}"`;
}
this.cssLayout();
this.cssColor();
Expand Down
2 changes: 1 addition & 1 deletion figma/src/htmlConvertor/sectionConvertor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class SectionConvertor {
content = contentArr.join('');
}

let nc = new NodeConvertor(node, this.configKey, this.configSettings, this.componentsLib, parentLocaltion);
let nc = new NodeConvertor(node, this.configKey, this.config , this.configSettings, this.componentsLib, parentLocaltion);
let html = nc.html(content);
this.updateImgsAndArchors(nc.imgUrls, nc.archors);
return html;
Expand Down
1 change: 1 addition & 0 deletions figma/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface IConfigSettings {
fonts: Record<string,any>;
containers: Record<string, any>;
hyperlinkSeparator: string;
specialClass: string;
}

export interface IConfigItem {
Expand Down
26 changes: 18 additions & 8 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes, PreloadAllModules } from '@angular/router';

const routes: Routes = [{
path: 'design_guidelines',
path: 'guidelines',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule),
data: {
navIndex: 2,
nav: 'design_guidelines' }
nav: 'guidelines' }
},{
path: 'design_guidelines/:name',
path: 'guidelines/:name',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule),
data: {
nav: 'design_guidelines'
nav: 'guidelines'
}
},{
path: 'components',
Expand All @@ -23,18 +23,28 @@ const routes: Routes = [{
data: {
nav: 'components'
}
},{
path: 'develop',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule),
data: {
navIndex: 6,
nav: 'develop',
externalUrl: "https://momentum-design.github.io/momentum-design/en/"
}
},{
path: 'support',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule),
data: {
navIndex: 7,
nav: 'Support',
externalUrl: "https://form.asana.com/?k=nOjXcoSB1acIKrLJwHQZ9Q&d=5557457880942"
nav: 'support',
}
},{
path: 'momentum_philosophy',
path: 'philosophy',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule),
data: { navIndex: 1, nav: 'momentum_philosophy' }
data: {
navIndex: 1,
nav: 'philosophy'
}
},{
path: '',
loadChildren: () => import('./detail/detail.module').then(m => m.DetailModule),
Expand Down
10 changes: 8 additions & 2 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
<mm-nav></mm-nav>
<div class="main" [ngStyle]= "{'background-image': backgroundTopImageUrl }">
<mm-header></mm-header>
<div class="content" [ngStyle]= "{'background-image': backgroundBottomImageUrl }">
<div class="content">
<router-outlet></router-outlet>
<mm-footer></mm-footer>
<div class="article">
<div class="article_l"></div>
<div class="article_m">
<mm-footer role="structure"></mm-footer>
</div>
<div class="article_r"></div>
</div>
</div>
</div>
4 changes: 4 additions & 0 deletions src/app/app.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
height: auto;
}

.article {
margin: 0 !important;
}

mm-nav {
flex: none;
}
Expand Down
Loading

0 comments on commit 4cc2c77

Please sign in to comment.