CSS 사전 프로세서(예: SASS)를 처음부터 구축하는 방법
로드맵 그리기
우선 우리가 무엇을 해야 하는지 봅시다.확장자를 사용하여 이 언어를 DotDot이라고 합니다.점을 찍다
새로운 언어를 설계할 때, 때로는 디자인에 쓰는 것이 매우 좋다.만약 당신이 진정으로 흐르는 것이 있다면, 당신은 인코딩을 시작할 수 있습니다.
다음은 점 세션입니다.
x = 1
y = 5
x-y-z = 6
col-z = berry
@f{
border: 10px solid black;
border-radius: 50%;
}
.add{
color:white;
background-color: rgb(3, 4, 5);
}
#ad{
color: rgb(x, 4, 5);
}
.a div a{
color: ..col-z;
@f
}
다음과 같이 컴파일됩니다.
.add{
color: white;
background-color: rgb(3,4,5);
}
#ad{
color: rgb(1,4,5);
}
.a div a{
color: berry;
border: 10px solid black;
border-radius: 50%;
}
해부 설계
저희가 어떤 기능을 포함했는지 보여드릴게요.
변수
x = 1
y = 5
x-y-z = 6
col-z = berry
저희가 봤어요.
x = 1
y = 5
x-y-z = 6
col-z = berry
@f{
border: 10px solid black;
border-radius: 50%;
}
.add{
color:white;
background-color: rgb(3, 4, 5);
}
#ad{
color: rgb(x, 4, 5);
}
.a div a{
color: ..col-z;
@f
}
.add{
color: white;
background-color: rgb(3,4,5);
}
#ad{
color: rgb(1,4,5);
}
.a div a{
color: berry;
border: 10px solid black;
border-radius: 50%;
}
저희가 어떤 기능을 포함했는지 보여드릴게요.
변수
x = 1
y = 5
x-y-z = 6
col-z = berry
저희가 봤어요.rgb(x, 4, 5);
및 속성 값color: ..col-z;
어디속성의 변수 호출을 직접 표시합니다.기능
@f{
border: 10px solid black;
border-radius: 50%;
}
함수는 @ 기호로 표시됩니다.이러한 속성은 다음과 같은 경우에 포함되는 속성으로 확장됩니다..a div a{
color: ..col-z;
@f
}
이것은 이미 충분히 복잡하다.우리 시작합시다!import copy # we have just one import
우리는 원본을 변수로 삼는다source = '''
x = 1
y = 5
x-y-z = 6
col-z = berry
@f{
border: 10px solid black;
border-radius: 50%;
}
.add{
color:white;
background-color: rgb(3, 4, 5);
}
#ad{
color: rgb(x, 4, 5);
}
.a div a{
color: ..col-z;
@f
}
'''
상수 정의
우리는 상량을 한 종류에 묶을 것이다.
class SYM:
LEFT_BRACE = '{'
RIGHT_BRACE = '}'
LEFT_ROUND = '('
RIGHT_ROUND = ')'
NEW_LINE = '\n'
TAB = ' '
COLON = ':'
SEMI_COLON = ';'
SPACE = ' '
COMMA = ','
EQUAL = '='
UNION = '-'
DOT = '.'
AT = '@'
그리고 키워드를 정의하겠습니다.
KEYWORDS = (SYM.LEFT_BRACE, SYM.RIGHT_BRACE, SYM.NEW_LINE, SYM.TAB, SYM.COLON,
SYM.SEMI_COLON, SYM.SPACE, SYM.RIGHT_ROUND, SYM.LEFT_ROUND, SYM.COMMA, SYM.EQUAL)
Lexer 구축
lexer의 코드는 this lexer tutorial 에서 왔습니다.필요하다면 한번 보세요.여기서 우리는 get\u lexeme 방법을 사용하여 코드를 하나의 클래스로 변환합니다.이 방법은 우리에게 목록을 제공했다.위의dotdot 세션은 아래lexemes 변수의 목록으로 변환됩니다.
이것은 우리의 lexer 과정입니다.
class Lexer:
def __init__(self, source: str, KEYWORDS: list):
self.white_space = SYM.SPACE
self.KEYWORDS = KEYWORDS
self.lexeme = ''
self.lexemes = []
self.string = source
def get_lexemes(self) -> list:
for i, char in enumerate(self.string):
if char != self.white_space and char != SYM.NEW_LINE:
self.lexeme += char # adding a char each time
if (i+1 < len(self.string)): # prevents error
if self.string[i+1] == self.white_space or self.string[i+1] in KEYWORDS or self.lexeme in KEYWORDS or self.string[i+1] == SYM.NEW_LINE: # if next char == ' '
if self.lexeme != '':
self.lexemes.append(self.lexeme)
self.lexeme = ''
return self.lexemes
그리고 기본 변수를 설명합니다.
v = Lexer(source, KEYWORDS)
lexemes = v.get_lexemes()
lexemes.append('') # appending an unused last element to properly dump all values
어소는 지금
['x', '=', '1', 'y', '=', '5', 'x-y-z', '=', '6', 'col-z',
'=', 'berry', '@f', '{', 'border', ':', '10px', 'solid',
'black', ';', 'border-radius', ':', '50%', ';', '}', '.add',
'{', 'color', ':', 'white', ';', 'background-color', ':',
'rgb', '(', '3', ',', '4', ',', '5', ')', ';', '}', '#ad',
'{', 'color', ':', 'rgb','(', 'x', ',', '4', ',', '5', ')',
';', '}', '.a', 'div', 'a', '{', 'color', ':', '..col-z',
';', '@f', '}', '']
이런 분리 데이터가 있으면 처리하기가 훨씬 쉽다!
기억의 개념
다음은 모든 변수를 저장하기 위한 사전을 정의합니다.
memory = {}
어디
x = 1
앞으로 이렇게 될 거예요.
{'x':'1'}
그것을 되찾기 위해서 우리는 단지 할 수 있을 뿐이다
memory['x']
나무의 개념
저희가 트리라는 사전이 있어요.
tree = {}
변환된 코드를
{
'@f': {
'border': '10px solid black',
'border-radius': '50%'
},
'.add': {
'color':'white',
'background-color': 'rgb ( 3 , 4 , 5 )'
}, '#ad': {
'color': 'rgb ( x ,4 , 5 )'
},
'.a div a': {
'color': '..col-z',
'@f': ''
}
}
우리의 다음 단계는 바로 어소 목록을 이 사전으로 바꾸는 것이다
트리 생성
우리가 있는 위치를 추적하기 위해서, 우리는 일련의 진실/거짓 값을 추출하는 변수가 있을 것이다 (켜기/끄기)
소유자 설정
id_string = ''
last_id_string = ''
last_attribute = ''
current_attribute = ''
current_value = ''
len_lexemes = len(lexemes)
id 문자열은 #add와 같습니다.xa div 등
마지막 변수는 하위 섹션을 비우지 않은 변수만 포함합니다
플래그 설정
우리는 세 면의 깃발을 가지고 있을 것이다.
우리가 블록을 시작할 때, {를 만났을 때, 그것은 진짜가 되고,}를 만났을 때, 그것은 가짜가 된다
속성은 색상의 색상입니다: 검은색;
진행 중인 속성은 전달할 때 true로 바뀌고, 전달할 때 false로 바뀝니다.
value_진행 중인 것은 검사할 때true로 바뀝니다. 검사할 때false로 바뀝니다.
block_ongoing = False
attribute_ongoing = False
value_ongoing = False
우리는 목록에서 순환을 시작하고 위에서 설명한 표지를 실현할 것이다
for i, lex in enumerate(lexemes):
if i+1 < len_lexemes:
next_lexeme = lexemes[i+1]
prev_lexeme = lexemes[i-1]
if lex == SYM.LEFT_BRACE:
block_ongoing = True
attribute_ongoing = True
continue
elif lex == SYM.RIGHT_BRACE:
block_ongoing = False
statement_ongoing = False
attribute_ongoing = False
value_ongoing = False
continue
if lex == SYM.COLON:
value_ongoing = True
attribute_ongoing = False
continue
elif lex == SYM.SEMI_COLON:
value_ongoing = False
statement_ongoing = False
attribute_ongoing = True
continue
일단 우리가 표지판을 활성화하면, 우리는 할 일이 없고, 우리는 계속 전진해야 하기 때문에 계속해야 한다.
처리 변수
변수를 분배하기 위해서 우리는 = 기호를 기다린 후에 계속할 수 있다.
그리고 변수 이름이나 값을 검사할 때, 우리는 순환이 계속되는 것을 막기 위해continue를 사용합니다
if lex == SYM.EQUAL:
memory[prev_lexeme] = next_lexeme
continue
elif next_lexeme == SYM.EQUAL or prev_lexeme == SYM.EQUAL:
continue
트리 구축 위치
이제 저희가 로고를 사용할 거예요.
if not block_ongoing:
id_string += lex + ' '
elif block_ongoing:
if id_string:
tree[id_string.strip()] = {}
last_id_string = id_string.strip()
id_string = ''
여기서 우리가 처리하는 것은 블록 id입니다. 예를 들어 #add in #add {}입니다.저희가 해냈어요.
tree[id_string.strip()] = {}
여기 예시 나무가 하나 있어요.
{
'.add': {}
}
동일한 원칙을 사용하면 우리는 속성에 대해 이 조작을 실행할 것이다
if attribute_ongoing:
current_attribute += lex
elif not attribute_ongoing:
if current_attribute:
tree[last_id_string][current_attribute] = ''
last_attribute = current_attribute
current_attribute = ''
여기 예시 나무가 하나 있어요.
{
'.add': {
'color':''
}
}
가치
if value_ongoing:
current_value += lex + ' '
elif not value_ongoing:
if current_value:
tree[last_id_string][last_attribute] = current_value.strip()
last_value = current_value.strip()
current_value = ''
여기 예시 나무가 하나 있어요.
{
'.add': {
'color':'white'
}
}
이 부분은 우리의 트리 구축 블록을 끝냈다
값 바꾸기
이제 rgb()와 rgba() 등 함수의 변수 이름을 어떻게 바꾸는지 봅시다
def parseFunc(f):
v = f.split(SYM.LEFT_ROUND)
name = v[0]
vals = v[1][:-1].replace(SYM.SPACE, '')
values = vals.split(SYM.COMMA)
for i, v in enumerate(values):
if not v.isnumeric():
values[i] = memory[v]
return '{}({})'.format(name.strip(), ','.join(values))
여기서 우리는 메모리 사전의 x를 1로 바꾸고 rgb(x, 4, 5)를 rgb(1, 4, 5)로 바꿉니다.CSS 사전 프로세서를 처음부터 구축하기 위해서는 모든 상황을 고려해야 합니다.
트리를 최종 형식으로 변환
이제 우리는 위에서 정의한 함수를 포함하여 다시 트리를 훑어보고 함수를 전개해야 한다.
기술적으로 말하자면, 우리는 사전을 교체할 때 그것을 변경할 수 없다.우리는 인용을 깨뜨리기 위해 그것을 복제해야 한다.우리는 그것을 깊이 복제해야 한다.
ntree = copy.deepcopy(tree)
그리고 우리는 교체한다.
for block_name in ntree:
properties = ntree[block_name]
if block_name[0] == SYM.AT:
continue
현재, 만약 우리가 id의 첫 번째 기호를 @ 로 얻게 된다면, 우리는 그것을 건너뛰기만 하면 된다. 왜냐하면 우리는 확장된 정의를 필요로 하지 않기 때문이다.
for element in properties:
value = properties[element]
if SYM.LEFT_ROUND in value:
tree[block_name][element] = parseFunc(value)
다음에 우리는 값 중 rgb () 와 유사한 함수가 있다면.이 경우 함수 parseFunc를 사용합니다.
if SYM.DOT in value:
tree[block_name][element] = memory[value.strip(SYM.DOT)]
다음에 하나 볼게요.값에서, 우리는 메모리 사전에서 그것을 보고 교체합니다
if SYM.AT in element:
del tree[block_name][element]
tree[block_name].update(tree[element])
다음은 @ 기호를 블록의 키로 간주합니다. 이 블록의 사전에 사전을 추가하기만 하면 됩니다.
이것 또한 데이터 구조를 사용하는 것이 일반 문자열보다 우수하다는 장점을 나타낸다.
일반 Css로 컴파일
이제 우리는 그것을 일반적인 CSS로 컴파일할 수 있습니다. 우리는 지금 그것만 인쇄합니다. (당신은 인쇄에서 file=btw를 사용할 수 있습니다.)
for key in tree:
if key[0] == SYM.AT:
continue
print(key, '{', sep='')
for elem in tree[key]:
print('{}{}: {};'.format(SYM.TAB, elem, tree[key][elem]))
print('}\n')
생기다
.add{
color: white;
background-color: rgb(3,4,5);
}
#ad{
color: rgb(1,4,5);
}
.a div a{
color: berry;
border: 10px solid black;
border-radius: 50%;
}
It의 미래
이것은 안전망이 없고 쿨한 기능이 부족한 상황에서 이루어진 것이지만, 이것은 정상적인 프로그래밍 논리를 통해 쿨한 것을 설정할 수 있다는 것을 증명하기 위한 것이다.이것은 내가 평소에 링크드 인 파이썬에 있는 프로젝트다.
들여쓰기(예: 펜)를 기반으로 처음부터 CSS 프로세서를 구축하려면 this tutorial 를 사용하십시오.
다음은 무엇을 추가해야 합니까?댓글은 아래와 같습니다!
Github 링크: https://github.com/Abdur-rahmaanJ/dotdot
미러 켜짐 PythonMembersClub
unsplash에서 온 그림
- 아부두르 라흐만 자한겔
Reference
이 문제에 관하여(CSS 사전 프로세서(예: SASS)를 처음부터 구축하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/abdurrahmaanj/how-to-build-a-css-pre-processor-like-sass-from-scratch-33mc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
class SYM:
LEFT_BRACE = '{'
RIGHT_BRACE = '}'
LEFT_ROUND = '('
RIGHT_ROUND = ')'
NEW_LINE = '\n'
TAB = ' '
COLON = ':'
SEMI_COLON = ';'
SPACE = ' '
COMMA = ','
EQUAL = '='
UNION = '-'
DOT = '.'
AT = '@'
KEYWORDS = (SYM.LEFT_BRACE, SYM.RIGHT_BRACE, SYM.NEW_LINE, SYM.TAB, SYM.COLON,
SYM.SEMI_COLON, SYM.SPACE, SYM.RIGHT_ROUND, SYM.LEFT_ROUND, SYM.COMMA, SYM.EQUAL)
class Lexer:
def __init__(self, source: str, KEYWORDS: list):
self.white_space = SYM.SPACE
self.KEYWORDS = KEYWORDS
self.lexeme = ''
self.lexemes = []
self.string = source
def get_lexemes(self) -> list:
for i, char in enumerate(self.string):
if char != self.white_space and char != SYM.NEW_LINE:
self.lexeme += char # adding a char each time
if (i+1 < len(self.string)): # prevents error
if self.string[i+1] == self.white_space or self.string[i+1] in KEYWORDS or self.lexeme in KEYWORDS or self.string[i+1] == SYM.NEW_LINE: # if next char == ' '
if self.lexeme != '':
self.lexemes.append(self.lexeme)
self.lexeme = ''
return self.lexemes
v = Lexer(source, KEYWORDS)
lexemes = v.get_lexemes()
lexemes.append('') # appending an unused last element to properly dump all values
['x', '=', '1', 'y', '=', '5', 'x-y-z', '=', '6', 'col-z',
'=', 'berry', '@f', '{', 'border', ':', '10px', 'solid',
'black', ';', 'border-radius', ':', '50%', ';', '}', '.add',
'{', 'color', ':', 'white', ';', 'background-color', ':',
'rgb', '(', '3', ',', '4', ',', '5', ')', ';', '}', '#ad',
'{', 'color', ':', 'rgb','(', 'x', ',', '4', ',', '5', ')',
';', '}', '.a', 'div', 'a', '{', 'color', ':', '..col-z',
';', '@f', '}', '']
다음은 모든 변수를 저장하기 위한 사전을 정의합니다.
memory = {}
어디x = 1
앞으로 이렇게 될 거예요.{'x':'1'}
그것을 되찾기 위해서 우리는 단지 할 수 있을 뿐이다memory['x']
나무의 개념
저희가 트리라는 사전이 있어요.
tree = {}
변환된 코드를{
'@f': {
'border': '10px solid black',
'border-radius': '50%'
},
'.add': {
'color':'white',
'background-color': 'rgb ( 3 , 4 , 5 )'
}, '#ad': {
'color': 'rgb ( x ,4 , 5 )'
},
'.a div a': {
'color': '..col-z',
'@f': ''
}
}
우리의 다음 단계는 바로 어소 목록을 이 사전으로 바꾸는 것이다트리 생성
우리가 있는 위치를 추적하기 위해서, 우리는 일련의 진실/거짓 값을 추출하는 변수가 있을 것이다 (켜기/끄기)
소유자 설정
id_string = ''
last_id_string = ''
last_attribute = ''
current_attribute = ''
current_value = ''
len_lexemes = len(lexemes)
id 문자열은 #add와 같습니다.xa div 등
마지막 변수는 하위 섹션을 비우지 않은 변수만 포함합니다
플래그 설정
우리는 세 면의 깃발을 가지고 있을 것이다.
우리가 블록을 시작할 때, {를 만났을 때, 그것은 진짜가 되고,}를 만났을 때, 그것은 가짜가 된다
속성은 색상의 색상입니다: 검은색;
진행 중인 속성은 전달할 때 true로 바뀌고, 전달할 때 false로 바뀝니다.
value_진행 중인 것은 검사할 때true로 바뀝니다. 검사할 때false로 바뀝니다.
block_ongoing = False
attribute_ongoing = False
value_ongoing = False
우리는 목록에서 순환을 시작하고 위에서 설명한 표지를 실현할 것이다
for i, lex in enumerate(lexemes):
if i+1 < len_lexemes:
next_lexeme = lexemes[i+1]
prev_lexeme = lexemes[i-1]
if lex == SYM.LEFT_BRACE:
block_ongoing = True
attribute_ongoing = True
continue
elif lex == SYM.RIGHT_BRACE:
block_ongoing = False
statement_ongoing = False
attribute_ongoing = False
value_ongoing = False
continue
if lex == SYM.COLON:
value_ongoing = True
attribute_ongoing = False
continue
elif lex == SYM.SEMI_COLON:
value_ongoing = False
statement_ongoing = False
attribute_ongoing = True
continue
일단 우리가 표지판을 활성화하면, 우리는 할 일이 없고, 우리는 계속 전진해야 하기 때문에 계속해야 한다.
처리 변수
변수를 분배하기 위해서 우리는 = 기호를 기다린 후에 계속할 수 있다.
그리고 변수 이름이나 값을 검사할 때, 우리는 순환이 계속되는 것을 막기 위해continue를 사용합니다
if lex == SYM.EQUAL:
memory[prev_lexeme] = next_lexeme
continue
elif next_lexeme == SYM.EQUAL or prev_lexeme == SYM.EQUAL:
continue
트리 구축 위치
이제 저희가 로고를 사용할 거예요.
if not block_ongoing:
id_string += lex + ' '
elif block_ongoing:
if id_string:
tree[id_string.strip()] = {}
last_id_string = id_string.strip()
id_string = ''
여기서 우리가 처리하는 것은 블록 id입니다. 예를 들어 #add in #add {}입니다.저희가 해냈어요.
tree[id_string.strip()] = {}
여기 예시 나무가 하나 있어요.
{
'.add': {}
}
동일한 원칙을 사용하면 우리는 속성에 대해 이 조작을 실행할 것이다
if attribute_ongoing:
current_attribute += lex
elif not attribute_ongoing:
if current_attribute:
tree[last_id_string][current_attribute] = ''
last_attribute = current_attribute
current_attribute = ''
여기 예시 나무가 하나 있어요.
{
'.add': {
'color':''
}
}
가치
if value_ongoing:
current_value += lex + ' '
elif not value_ongoing:
if current_value:
tree[last_id_string][last_attribute] = current_value.strip()
last_value = current_value.strip()
current_value = ''
여기 예시 나무가 하나 있어요.
{
'.add': {
'color':'white'
}
}
이 부분은 우리의 트리 구축 블록을 끝냈다
값 바꾸기
이제 rgb()와 rgba() 등 함수의 변수 이름을 어떻게 바꾸는지 봅시다
def parseFunc(f):
v = f.split(SYM.LEFT_ROUND)
name = v[0]
vals = v[1][:-1].replace(SYM.SPACE, '')
values = vals.split(SYM.COMMA)
for i, v in enumerate(values):
if not v.isnumeric():
values[i] = memory[v]
return '{}({})'.format(name.strip(), ','.join(values))
여기서 우리는 메모리 사전의 x를 1로 바꾸고 rgb(x, 4, 5)를 rgb(1, 4, 5)로 바꿉니다.CSS 사전 프로세서를 처음부터 구축하기 위해서는 모든 상황을 고려해야 합니다.
트리를 최종 형식으로 변환
이제 우리는 위에서 정의한 함수를 포함하여 다시 트리를 훑어보고 함수를 전개해야 한다.
기술적으로 말하자면, 우리는 사전을 교체할 때 그것을 변경할 수 없다.우리는 인용을 깨뜨리기 위해 그것을 복제해야 한다.우리는 그것을 깊이 복제해야 한다.
ntree = copy.deepcopy(tree)
그리고 우리는 교체한다.
for block_name in ntree:
properties = ntree[block_name]
if block_name[0] == SYM.AT:
continue
현재, 만약 우리가 id의 첫 번째 기호를 @ 로 얻게 된다면, 우리는 그것을 건너뛰기만 하면 된다. 왜냐하면 우리는 확장된 정의를 필요로 하지 않기 때문이다.
for element in properties:
value = properties[element]
if SYM.LEFT_ROUND in value:
tree[block_name][element] = parseFunc(value)
다음에 우리는 값 중 rgb () 와 유사한 함수가 있다면.이 경우 함수 parseFunc를 사용합니다.
if SYM.DOT in value:
tree[block_name][element] = memory[value.strip(SYM.DOT)]
다음에 하나 볼게요.값에서, 우리는 메모리 사전에서 그것을 보고 교체합니다
if SYM.AT in element:
del tree[block_name][element]
tree[block_name].update(tree[element])
다음은 @ 기호를 블록의 키로 간주합니다. 이 블록의 사전에 사전을 추가하기만 하면 됩니다.
이것 또한 데이터 구조를 사용하는 것이 일반 문자열보다 우수하다는 장점을 나타낸다.
일반 Css로 컴파일
이제 우리는 그것을 일반적인 CSS로 컴파일할 수 있습니다. 우리는 지금 그것만 인쇄합니다. (당신은 인쇄에서 file=btw를 사용할 수 있습니다.)
for key in tree:
if key[0] == SYM.AT:
continue
print(key, '{', sep='')
for elem in tree[key]:
print('{}{}: {};'.format(SYM.TAB, elem, tree[key][elem]))
print('}\n')
생기다
.add{
color: white;
background-color: rgb(3,4,5);
}
#ad{
color: rgb(1,4,5);
}
.a div a{
color: berry;
border: 10px solid black;
border-radius: 50%;
}
It의 미래
이것은 안전망이 없고 쿨한 기능이 부족한 상황에서 이루어진 것이지만, 이것은 정상적인 프로그래밍 논리를 통해 쿨한 것을 설정할 수 있다는 것을 증명하기 위한 것이다.이것은 내가 평소에 링크드 인 파이썬에 있는 프로젝트다.
들여쓰기(예: 펜)를 기반으로 처음부터 CSS 프로세서를 구축하려면 this tutorial 를 사용하십시오.
다음은 무엇을 추가해야 합니까?댓글은 아래와 같습니다!
Github 링크: https://github.com/Abdur-rahmaanJ/dotdot
미러 켜짐 PythonMembersClub
unsplash에서 온 그림
- 아부두르 라흐만 자한겔
Reference
이 문제에 관하여(CSS 사전 프로세서(예: SASS)를 처음부터 구축하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/abdurrahmaanj/how-to-build-a-css-pre-processor-like-sass-from-scratch-33mc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
id_string = ''
last_id_string = ''
last_attribute = ''
current_attribute = ''
current_value = ''
len_lexemes = len(lexemes)
block_ongoing = False
attribute_ongoing = False
value_ongoing = False
for i, lex in enumerate(lexemes):
if i+1 < len_lexemes:
next_lexeme = lexemes[i+1]
prev_lexeme = lexemes[i-1]
if lex == SYM.LEFT_BRACE:
block_ongoing = True
attribute_ongoing = True
continue
elif lex == SYM.RIGHT_BRACE:
block_ongoing = False
statement_ongoing = False
attribute_ongoing = False
value_ongoing = False
continue
if lex == SYM.COLON:
value_ongoing = True
attribute_ongoing = False
continue
elif lex == SYM.SEMI_COLON:
value_ongoing = False
statement_ongoing = False
attribute_ongoing = True
continue
변수를 분배하기 위해서 우리는 = 기호를 기다린 후에 계속할 수 있다.
그리고 변수 이름이나 값을 검사할 때, 우리는 순환이 계속되는 것을 막기 위해continue를 사용합니다
if lex == SYM.EQUAL:
memory[prev_lexeme] = next_lexeme
continue
elif next_lexeme == SYM.EQUAL or prev_lexeme == SYM.EQUAL:
continue
트리 구축 위치
이제 저희가 로고를 사용할 거예요.
if not block_ongoing:
id_string += lex + ' '
elif block_ongoing:
if id_string:
tree[id_string.strip()] = {}
last_id_string = id_string.strip()
id_string = ''
여기서 우리가 처리하는 것은 블록 id입니다. 예를 들어 #add in #add {}입니다.저희가 해냈어요.
tree[id_string.strip()] = {}
여기 예시 나무가 하나 있어요.
{
'.add': {}
}
동일한 원칙을 사용하면 우리는 속성에 대해 이 조작을 실행할 것이다
if attribute_ongoing:
current_attribute += lex
elif not attribute_ongoing:
if current_attribute:
tree[last_id_string][current_attribute] = ''
last_attribute = current_attribute
current_attribute = ''
여기 예시 나무가 하나 있어요.
{
'.add': {
'color':''
}
}
가치
if value_ongoing:
current_value += lex + ' '
elif not value_ongoing:
if current_value:
tree[last_id_string][last_attribute] = current_value.strip()
last_value = current_value.strip()
current_value = ''
여기 예시 나무가 하나 있어요.
{
'.add': {
'color':'white'
}
}
이 부분은 우리의 트리 구축 블록을 끝냈다
값 바꾸기
이제 rgb()와 rgba() 등 함수의 변수 이름을 어떻게 바꾸는지 봅시다
def parseFunc(f):
v = f.split(SYM.LEFT_ROUND)
name = v[0]
vals = v[1][:-1].replace(SYM.SPACE, '')
values = vals.split(SYM.COMMA)
for i, v in enumerate(values):
if not v.isnumeric():
values[i] = memory[v]
return '{}({})'.format(name.strip(), ','.join(values))
여기서 우리는 메모리 사전의 x를 1로 바꾸고 rgb(x, 4, 5)를 rgb(1, 4, 5)로 바꿉니다.CSS 사전 프로세서를 처음부터 구축하기 위해서는 모든 상황을 고려해야 합니다.
트리를 최종 형식으로 변환
이제 우리는 위에서 정의한 함수를 포함하여 다시 트리를 훑어보고 함수를 전개해야 한다.
기술적으로 말하자면, 우리는 사전을 교체할 때 그것을 변경할 수 없다.우리는 인용을 깨뜨리기 위해 그것을 복제해야 한다.우리는 그것을 깊이 복제해야 한다.
ntree = copy.deepcopy(tree)
그리고 우리는 교체한다.
for block_name in ntree:
properties = ntree[block_name]
if block_name[0] == SYM.AT:
continue
현재, 만약 우리가 id의 첫 번째 기호를 @ 로 얻게 된다면, 우리는 그것을 건너뛰기만 하면 된다. 왜냐하면 우리는 확장된 정의를 필요로 하지 않기 때문이다.
for element in properties:
value = properties[element]
if SYM.LEFT_ROUND in value:
tree[block_name][element] = parseFunc(value)
다음에 우리는 값 중 rgb () 와 유사한 함수가 있다면.이 경우 함수 parseFunc를 사용합니다.
if SYM.DOT in value:
tree[block_name][element] = memory[value.strip(SYM.DOT)]
다음에 하나 볼게요.값에서, 우리는 메모리 사전에서 그것을 보고 교체합니다
if SYM.AT in element:
del tree[block_name][element]
tree[block_name].update(tree[element])
다음은 @ 기호를 블록의 키로 간주합니다. 이 블록의 사전에 사전을 추가하기만 하면 됩니다.
이것 또한 데이터 구조를 사용하는 것이 일반 문자열보다 우수하다는 장점을 나타낸다.
일반 Css로 컴파일
이제 우리는 그것을 일반적인 CSS로 컴파일할 수 있습니다. 우리는 지금 그것만 인쇄합니다. (당신은 인쇄에서 file=btw를 사용할 수 있습니다.)
for key in tree:
if key[0] == SYM.AT:
continue
print(key, '{', sep='')
for elem in tree[key]:
print('{}{}: {};'.format(SYM.TAB, elem, tree[key][elem]))
print('}\n')
생기다
.add{
color: white;
background-color: rgb(3,4,5);
}
#ad{
color: rgb(1,4,5);
}
.a div a{
color: berry;
border: 10px solid black;
border-radius: 50%;
}
It의 미래
이것은 안전망이 없고 쿨한 기능이 부족한 상황에서 이루어진 것이지만, 이것은 정상적인 프로그래밍 논리를 통해 쿨한 것을 설정할 수 있다는 것을 증명하기 위한 것이다.이것은 내가 평소에 링크드 인 파이썬에 있는 프로젝트다.
들여쓰기(예: 펜)를 기반으로 처음부터 CSS 프로세서를 구축하려면 this tutorial 를 사용하십시오.
다음은 무엇을 추가해야 합니까?댓글은 아래와 같습니다!
Github 링크: https://github.com/Abdur-rahmaanJ/dotdot
미러 켜짐 PythonMembersClub
unsplash에서 온 그림
- 아부두르 라흐만 자한겔
Reference
이 문제에 관하여(CSS 사전 프로세서(예: SASS)를 처음부터 구축하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/abdurrahmaanj/how-to-build-a-css-pre-processor-like-sass-from-scratch-33mc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
if not block_ongoing:
id_string += lex + ' '
elif block_ongoing:
if id_string:
tree[id_string.strip()] = {}
last_id_string = id_string.strip()
id_string = ''
tree[id_string.strip()] = {}
{
'.add': {}
}
if attribute_ongoing:
current_attribute += lex
elif not attribute_ongoing:
if current_attribute:
tree[last_id_string][current_attribute] = ''
last_attribute = current_attribute
current_attribute = ''
{
'.add': {
'color':''
}
}
if value_ongoing:
current_value += lex + ' '
elif not value_ongoing:
if current_value:
tree[last_id_string][last_attribute] = current_value.strip()
last_value = current_value.strip()
current_value = ''
{
'.add': {
'color':'white'
}
}
이제 rgb()와 rgba() 등 함수의 변수 이름을 어떻게 바꾸는지 봅시다
def parseFunc(f):
v = f.split(SYM.LEFT_ROUND)
name = v[0]
vals = v[1][:-1].replace(SYM.SPACE, '')
values = vals.split(SYM.COMMA)
for i, v in enumerate(values):
if not v.isnumeric():
values[i] = memory[v]
return '{}({})'.format(name.strip(), ','.join(values))
여기서 우리는 메모리 사전의 x를 1로 바꾸고 rgb(x, 4, 5)를 rgb(1, 4, 5)로 바꿉니다.CSS 사전 프로세서를 처음부터 구축하기 위해서는 모든 상황을 고려해야 합니다.트리를 최종 형식으로 변환
이제 우리는 위에서 정의한 함수를 포함하여 다시 트리를 훑어보고 함수를 전개해야 한다.
기술적으로 말하자면, 우리는 사전을 교체할 때 그것을 변경할 수 없다.우리는 인용을 깨뜨리기 위해 그것을 복제해야 한다.우리는 그것을 깊이 복제해야 한다.
ntree = copy.deepcopy(tree)
그리고 우리는 교체한다.
for block_name in ntree:
properties = ntree[block_name]
if block_name[0] == SYM.AT:
continue
현재, 만약 우리가 id의 첫 번째 기호를 @ 로 얻게 된다면, 우리는 그것을 건너뛰기만 하면 된다. 왜냐하면 우리는 확장된 정의를 필요로 하지 않기 때문이다.
for element in properties:
value = properties[element]
if SYM.LEFT_ROUND in value:
tree[block_name][element] = parseFunc(value)
다음에 우리는 값 중 rgb () 와 유사한 함수가 있다면.이 경우 함수 parseFunc를 사용합니다.
if SYM.DOT in value:
tree[block_name][element] = memory[value.strip(SYM.DOT)]
다음에 하나 볼게요.값에서, 우리는 메모리 사전에서 그것을 보고 교체합니다
if SYM.AT in element:
del tree[block_name][element]
tree[block_name].update(tree[element])
다음은 @ 기호를 블록의 키로 간주합니다. 이 블록의 사전에 사전을 추가하기만 하면 됩니다.
이것 또한 데이터 구조를 사용하는 것이 일반 문자열보다 우수하다는 장점을 나타낸다.
일반 Css로 컴파일
이제 우리는 그것을 일반적인 CSS로 컴파일할 수 있습니다. 우리는 지금 그것만 인쇄합니다. (당신은 인쇄에서 file=btw를 사용할 수 있습니다.)
for key in tree:
if key[0] == SYM.AT:
continue
print(key, '{', sep='')
for elem in tree[key]:
print('{}{}: {};'.format(SYM.TAB, elem, tree[key][elem]))
print('}\n')
생기다
.add{
color: white;
background-color: rgb(3,4,5);
}
#ad{
color: rgb(1,4,5);
}
.a div a{
color: berry;
border: 10px solid black;
border-radius: 50%;
}
It의 미래
이것은 안전망이 없고 쿨한 기능이 부족한 상황에서 이루어진 것이지만, 이것은 정상적인 프로그래밍 논리를 통해 쿨한 것을 설정할 수 있다는 것을 증명하기 위한 것이다.이것은 내가 평소에 링크드 인 파이썬에 있는 프로젝트다.
들여쓰기(예: 펜)를 기반으로 처음부터 CSS 프로세서를 구축하려면 this tutorial 를 사용하십시오.
다음은 무엇을 추가해야 합니까?댓글은 아래와 같습니다!
Github 링크: https://github.com/Abdur-rahmaanJ/dotdot
미러 켜짐 PythonMembersClub
unsplash에서 온 그림
- 아부두르 라흐만 자한겔
Reference
이 문제에 관하여(CSS 사전 프로세서(예: SASS)를 처음부터 구축하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/abdurrahmaanj/how-to-build-a-css-pre-processor-like-sass-from-scratch-33mc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
ntree = copy.deepcopy(tree)
for block_name in ntree:
properties = ntree[block_name]
if block_name[0] == SYM.AT:
continue
for element in properties:
value = properties[element]
if SYM.LEFT_ROUND in value:
tree[block_name][element] = parseFunc(value)
if SYM.DOT in value:
tree[block_name][element] = memory[value.strip(SYM.DOT)]
if SYM.AT in element:
del tree[block_name][element]
tree[block_name].update(tree[element])
이제 우리는 그것을 일반적인 CSS로 컴파일할 수 있습니다. 우리는 지금 그것만 인쇄합니다. (당신은 인쇄에서 file=btw를 사용할 수 있습니다.)
for key in tree:
if key[0] == SYM.AT:
continue
print(key, '{', sep='')
for elem in tree[key]:
print('{}{}: {};'.format(SYM.TAB, elem, tree[key][elem]))
print('}\n')
생기다.add{
color: white;
background-color: rgb(3,4,5);
}
#ad{
color: rgb(1,4,5);
}
.a div a{
color: berry;
border: 10px solid black;
border-radius: 50%;
}
It의 미래
이것은 안전망이 없고 쿨한 기능이 부족한 상황에서 이루어진 것이지만, 이것은 정상적인 프로그래밍 논리를 통해 쿨한 것을 설정할 수 있다는 것을 증명하기 위한 것이다.이것은 내가 평소에 링크드 인 파이썬에 있는 프로젝트다.
들여쓰기(예: 펜)를 기반으로 처음부터 CSS 프로세서를 구축하려면 this tutorial 를 사용하십시오.
다음은 무엇을 추가해야 합니까?댓글은 아래와 같습니다!
Github 링크: https://github.com/Abdur-rahmaanJ/dotdot
미러 켜짐 PythonMembersClub
unsplash에서 온 그림
- 아부두르 라흐만 자한겔
Reference
이 문제에 관하여(CSS 사전 프로세서(예: SASS)를 처음부터 구축하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/abdurrahmaanj/how-to-build-a-css-pre-processor-like-sass-from-scratch-33mc
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(CSS 사전 프로세서(예: SASS)를 처음부터 구축하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/abdurrahmaanj/how-to-build-a-css-pre-processor-like-sass-from-scratch-33mc텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)