Flask에서 MD 문서 랜더링 + 디렉토리 하위경로 dict로 파싱해서 Jinja...

Flask에서 MD 문서 랜더링 + 디렉토리 하위경로 dict로 파싱해서 Jinja...

디렉토리 하위 경로를 dict 형태로 파싱하기

최종 목표 : md 문서가 있는 디렉토리 경로를 읽어와 웹페이지에서 마크다운 문서를 랜더하는것.

디렉토리 받아서 하위 경로 DICT + list 형태로 자동 파싱해주는 코드 만들기

def readdir(dir): tdir = {} ret = {} tdir['dir'] = [] for file,key in dir.items() : if key == None : tdir['dir'].append(file) else : ret = readdir(key) ret['fname'] = file tdir['dir'].append(ret) return tdir def dirparser(rootdir): dir = {} res = os.walk(rootdir) rootdir = rootdir.rstrip(os.sep) start = rootdir.rfind(os.sep) + 1 for path, dirs, files in res: folders = path[start:].split(os.sep) subdir = dict.fromkeys(files) parent = reduce(dict.get, folders[:-1], dir) # print(type(subdir)) parent[folders[-1]] = subdir return readdir(dir) rdir = "dir" print(dirparser(rdir))

{ 'dir': [ {'dir': ['doctest1.md', 'doctest1_copy.md', {'dir': ['서포트+로그+타입 copy.md', '서포트+로그+타입.md'], 'fname': 'folder1'}, {'dir': ['서포트+로그+타입 copy.md', '서포트+로그+타입.md'], 'fname': 'folder13'}, {'dir': ['doctest1_copy_2.md', {'dir': [ 'doctest1_copy_3.md', {'dir': [], 'fname': 'f1'}, {'dir': [], 'fname': 'f2'} ], 'fname': 'folder2_1'} ], 'fname': 'folder2'} ], 'fname': 'docs'} ] }

None이 아닌 경우 -> dir.items() 에 의해 k1,k2로 구분되어 반복문 돌아감

k2가 None인 경우 -> k1을 출력

아닌 경우 -> dir.items()에 의해 ~

None인 경우-> 이름을 출력

파싱 된다. 이제 해야하는것

None인 경우 - 'name' : 'fname + 들어갈때도 파일이름 저장은 공통적으로 필요함.

아닌 경우 - dir : 'dict' 형식으로 세팅 필요함.

딕셔너리 반환하는 식으로 인자 체크 가능?

[ name : file dir : [ { name : file dir : {} }, ] ]

저 name과 dir가 들어있는 딕셔너리가 통째로 반환되어야함.

맨 마지막의 dir은 (None을 만나는 경우) -> 파일 이름만 반환되고 dir는 비어있을(None이 될) 예정.

그리고 어쨋든 None이 아니면 현재 디렉토리 구조가 있다는 이야기 -> 폴더 이름을 만들어야한다.

== None인 경우 파일이라는 뜻.

현재 디렉토리 탐색이 끝났는데 dir이 비어있는경우

-> 더 내려갈 하위 디렉토리가 없음. 현재 디렉토리 이름이 현재 dict의 fname 요소가 되어야함.

반환받은 요소를 검사할 필요가 있나? -> 반환받은 dir 요소의 dict가 비어있는 경우, 해당 dir요소는 최 하위 디렉토리라는 의미가 되므로, 가지고 있는 이름을 fname으로 지정해줘야 한다. -> 아님.

그냥 요소를 반환받을때 반환받은 dict에 fame 추가해주면됨.;; 간단하게 생각하자

jinja에서의 결과물 출력 방식

'fname' : 'foldername' , 'dir' : [ 'filename', {'dir' : [] , 'fname' : 'f1' }, {'dir' : [] , 'fname' : 'f2' }, ]

폴더이름은 디렉토리당 한번씩만 출력됨 dir 내부 요소에 폴더랑 파일이 모두 포함됨. 요소 타입이 string일 경우 파일명 → 그냥 출력하면됨 string이 아닌경우 디렉토리 → 반복문 진행 fname이 없는 경우 → 이 경우도 그냥 출력

{% for d1 in dir['dir'] %} name1 : {{ d1['fname'] }} {% for d2 in d1['dir'] %} {% if d2['fname'] %} name2 : {{ d2['fname'] }} {% else %} file2 : {{ d2 }} {% endif %} {% for d3 in d2['dir'] %} {% if d3['fname'] %} name3 : {{ d3['fname'] }} {% else %} file3 : {{ d3 }} {% endif %} {% for d4 in d3['dir'] %} {% if d4['fname'] %} name4 : {{ d4['fname'] }} {% else %} file4 : {{ d4 }} {% endif %} {% endfor %} {% endfor %} {% endfor %} {% endfor %}

파일을 불러오기 위해서는 디렉토리 경로도 표기해줘야한다.

이건 파싱함수 코드를 좀 바꿔야할듯. 디렉토리를 내려갈 때 마다 상위 디렉토리 이름을 누적 표기하는 식으로 해보자.

{% for d1 in dir['dir'] %} name1 : {{ d1['fname'] }} {% for d2 in d1['dir'] %} {% set dname1 = d1['fname']+"/" %} {% if d2['fname'] %} name2 : {{ dname1+d2['fname'] }} {% else %} file2 : {{ dname1+d2 }} {% endif %} {% for d3 in d2['dir'] %} {% set dname2 = dname1+d2['fname']+"/" %} {% if d3['fname'] %} name3 : {{ dname2+d3['fname'] }} {% else %} file3 : {{ dname2+d3 }} {% endif %} {% for d4 in d3['dir'] %} {% set dname3 = dname2+d3['fname']+"/" %} {% if d4['fname'] %} name4 : {{ dname3+d4['fname'] }} {% else %} file4 : {{ dname3+d4 }} {% endif %} {% endfor %} {% endfor %} {% endfor %} {% endfor %}

혹은 경우에 따라 파일에만 전체 디렉토리가 나오게 할수도 있다.

{% for d1 in dir['dir'] %} name1 : {{ d1['fname'] }} {% for d2 in d1['dir'] %} {% set dname1 = d1['fname']+"/" %} {% if d2['fname'] %} name2 : {{ d2['fname'] }} {% else %} file2 : {{ dname1+d2 }} {% endif %} {% for d3 in d2['dir'] %} {% set dname2 = dname1+d2['fname']+"/" %} {% if d3['fname'] %} name3 : {{ d3['fname'] }} {% else %} file3 : {{ dname2+d3 }} {% endif %} {% for d4 in d3['dir'] %} {% set dname3 = dname2+d3['fname']+"/" %} {% if d4['fname'] %} name4 : {{ d4['fname'] }} {% else %} file4 : {{ dname3+d4 }} {% endif %} {% endfor %} {% endfor %} {% endfor %} {% endfor %}

flaks에서 markdown 문서 출력하기

pip install Flask-markdown

flask-markdown 패키지 설치

이후 init 파일에 flask app 추가

app = Flask(__name__,static_url_path='/static') ~~~~ Markdown(app,extensions=['nl2br','fenced_code'])

app 추가되었으면 view 문서에서 아래와 같이 작성

mf = open(rootpath+'\\'+fname,"r",encoding='UTF8') md = mf.read() #md = "## Your Markdown Here " return render_template('docbase.html',dir=r,doc=fname,md=md)

랜더할때 그냥 인자로 읽어들인 마크다운 텍스트 내용을 그대로 넘겨주면 된다.

file path : {{ doc }} {% if md %} {{ md|markdown }} {% else %} {% endif %}

html 템플릿 파일은 받아온 내용을 그대로 markdown 형태로 출력하면 됨.

### MD TEST DOC 1. 마크다운 테스트 문서입니다 2. 마크다운 텍스트? - 마크당우우우우운 - 마아아읔 다운 markdown code highlights test

그러면 저렇게 나온다.

파일 오픈시 'cp949' 인코딩 에러

"UnicodeDecodeError: 'cp949' codec can't decode byte 0xe2 in position 6987: illegal multibyte sequence"

파일 입출력시 위와같은 에러가 날떄가 있는데, 파일을 읽을때 인코딩이 잘못되어 발생하는 에러다.

mf = open(rootpath+'\\'+fname,"r",**encoding='UTF8'**)

encoding='UTF8' 로 인코딩 명시해주면 해결

from http://my-repo.tistory.com/92 by ccl(A) rewrite - 2021-10-02 20:26:58