-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6e824df
Showing
196 changed files
with
69,702 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
## 개요 | ||
바나나는 병아리 엔진 기반의 많은 편리한 기능 탑재를 목표로 하는 나무픽스 호환 엔진이다. | ||
banana is a wiki engine that supports many convinient features. (English is not supported yet) | ||
|
||
버전은 기존 엔진 버전 번호를 이어서 9부터 시작한다. *(참고로 기존 엔진은 더 이상 본인도 가지고 있지 않다. 삭제 후 이중 덮어쓰기하였다.)* | ||
|
||
실제 가동 사이트는 알파위키 *사문*에 주소를 남겼다. | ||
|
||
## 요구 환경 | ||
Windows 7(Node.js 7.6 이상) | ||
|
||
### Windows XP에서 호스팅하기 | ||
테스트해보지 않음, 본인 책임하에 사용, 시스템 복원 지점 생성 | ||
|
||
최신 프로그램을 XP에서 돌아가게 하는 패치들: | ||
- https://msfn.org/board/topic/176757-cancelled-by-the-author-extended-kernel-for-xp-extendedxp/ | ||
- https://www.betaarchive.com/forum/viewtopic.php?t=36763 | ||
|
||
### Windows Vista에서 호스팅하기 | ||
#### 32비트 | ||
아직은 없다. | ||
|
||
#### 64비트 | ||
[여기](https://www.youtube.com/watch?v=cJI6utFsFr4) 참조. | ||
|
||
## 기능 | ||
굵게 표시한 것을 모두 만들면 베타로 전환. | ||
- [X] **문서 읽기** | ||
- [X] **편집, 생성** | ||
- [X] **이동 및 삭제** | ||
- [X] **RAW, 비교, 편집 복구** | ||
- [X] **역링크** | ||
- [X] **문서 역사** | ||
- [X] **최근 변경, 최근 토론** | ||
- [X] **사용자별 기여 목록** | ||
- [X] **ACL** | ||
- [X] **로그인, 로그아웃, 가입** | ||
- [ ] **사용자 정보 수정 도구** (진행 중) | ||
- [X] **IP 차단** | ||
- [X] **사용자 차단** | ||
- [X] **권한 부여** | ||
- [X] **위키 설정 도구** | ||
- [ ] **편집요청(토론을 기반으로 만듬)** (진행 중) | ||
- [X] **화일 올리기 도구** | ||
- [ ] **화일 페이지** | ||
- [X] **검색** | ||
- [ ] **분류 페이지** | ||
- [X] API | ||
- [X] 플러그 인 | ||
- [X] 문서함(엔진에서는 "주시문서 목록"이라 부름) | ||
- [ ] 토론함 | ||
- [ ] 자동 로그인(진행 중) | ||
- [ ] 하위 위키(진행 중) | ||
- [ ] 다국어 지원(진행 중) | ||
- [ ] 로그인 내역 | ||
- [ ] 일관 편집, 생성, 및 삭제 | ||
|
||
## 삭제된 릴리즈 | ||
### \[4.5.9] 12.5.9 (알파) | ||
|
||
- 특수 방식으로 오류 번호 생성 | ||
|
||
### \[4.5.8] 12.5.8 (알파) | ||
- 표현 오류 수정 | ||
|
||
### \[4.5.7] 12.5.7 (알파) | ||
- 모든 주소에서의 접속 차단 가능 | ||
|
||
### \[4.5.6] 12.5.6 (알파) | ||
- 이동 관련 버그 수정 | ||
|
||
### \[4.5.5] 12.5.5 (알파) | ||
- 버그 수정 | ||
|
||
### \[4.5.4] 12.5.4 (알파) | ||
- session-file-store 사용으로 서버 재시작 시에도 로그인 상태 유지됨 | ||
|
||
### \[1.1.0] 9.1.0 (알파) | ||
- 기본적인 기능 | ||
- 문서 읽기 | ||
- 문서 편집 | ||
- 토론 | ||
- 토론 발제 | ||
- 댓글 달기 | ||
- 댓글 숨기기 | ||
- 토론 종경, 동결 | ||
- 토론 주제변경 | ||
- 토론 문서 변경 | ||
- 토론 삭제 | ||
- 로그인 | ||
- 계정 생성 | ||
- 문서 역사 | ||
- 최근 변경 내역 | ||
- 최근 토론 | ||
- 사용자 기여 목록(수정, 토론) | ||
|
||
## 사용하는 외부 라이브러리 | ||
### path | ||
[[라이선스]](https://github.com/jinder/path/blob/master/LICENSE) | ||
|
||
### captchapng | ||
[[NPM]](npmjs.com/package/captchapng) \[라이선스: BSD] \[저작권자: George Chan] | ||
|
||
### wait-console-input | ||
[[NPM]](https://www.npmjs.com/package/wait-console-input) [[라이선스]](https://github.com/peeyush-pant/wait-console-input/blob/master/LICENSE) | ||
|
||
### sha3 | ||
[[NPM]](https://www.npmjs.com/package/sha3) [[라이선스]](https://github.com/phusion/node-sha3/blob/master/LICENSE) | ||
|
||
### sqlite3 | ||
[[NPM]](https://www.npmjs.com/package/sqlite3) [[라이선스]](https://github.com/mapbox/node-sqlite3/blob/master/LICENSE) | ||
|
||
### express | ||
[[NPM]](https://www.npmjs.com/package/express) [[라이선스]](https://github.com/expressjs/express/blob/master/LICENSE) | ||
|
||
### swig | ||
[[NPM]](https://www.npmjs.com/package/swig) [[라이선스]](https://github.com/paularmstrong/swig/blob/master/LICENSE) | ||
- dateformatter.js 사용 (날짜를 시간대에 맞추기) | ||
|
||
### md5 | ||
[[NPM]](https://www.npmjs.com/package/md5) [[라이선스]](https://github.com/pvorb/node-md5/blob/master/LICENSE) | ||
|
||
### ip-range-check | ||
[[NPM]](https://www.npmjs.com/package/ip-range-check) [[라이선스]](https://github.com/danielcompton/ip-range-check/blob/master/LICENSE) | ||
|
||
### nodemailer | ||
[[NPM]](https://www.npmjs.com/package/nodemailer) [[라이선스]](https://github.com/nodemailer/nodemailer/blob/master/LICENSE) | ||
|
||
### jQuery, jQuery UI | ||
(C)저작권자 JS 파운데이션 및 기타 기여자들 [[라이선스]](https://jquery.org/license/) | ||
|
||
### ionicons | ||
(C) 저작권자 present Ionic (2015) / [[라이선스]](https://github.com/ionic-team/ionicons) (MIT) | ||
|
||
### nunjucks | ||
[[NPM]](https://www.npmjs.com/package/nunjucks) [[라이선스]](https://github.com/mozilla/nunjucks/blob/master/LICENSE) | ||
|
||
### js-namumark | ||
(C)저작권자 LiteHell(2017) / AGPL-3.0 / [[라이선스]](https://github.com/LiteHell/js-namumark/blob/master/LICENSE) | ||
* ~~일부 소스를 수정했읍니다 - 수정된 소스 코드는 [[이곳]](https://github.com/gdl-888/js-namumark)에서...~~ <-- 소스 변경은 취소했으며, 렌더링 끝난 HTML을 서버에서 다듬는 방식으로 변경 | ||
|
||
### jsdifflib | ||
(C)저작권자 cemerick 2007~2011 [[깃허브]](https://github.com/cemerick/jsdifflib) | ||
|
||
## 기타 라이선스 | ||
- 스킨 호환 관련: [the seed](https://theseed.io/License), [openNAMU](https://github.com/2du/openNAMU#%EB%9D%BC%EC%9D%B4%EC%84%A0%EC%8A%A4) | ||
|
||
- 대한민국 기준 프로그램코드역분석 법률에 따라 그 엔진을 모방하거나 이 엔진을 상업적으로 쓰면 안된다. |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
const sqlite3 = require('sqlite3').verbose(); | ||
const conn = new sqlite3.Database('./wikidata.db', (err) => {}); | ||
|
||
conn.query = function (sql, params) { | ||
var that = this; | ||
return new Promise(function (resolve, reject) { | ||
that.all(sql, params, function asyncSQLRun(error, rows) { | ||
if(error) { | ||
print(error); | ||
resolve(-1); | ||
} else { | ||
resolve(rows); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
conn.exec = function (sql, params) { | ||
var that = this; | ||
return new Promise(function (resolve, reject) { | ||
that.run(sql, params, function asyncSQLRun(error) { | ||
if(error) { | ||
print(error); | ||
resolve(-1); | ||
} else { | ||
resolve(0); | ||
} | ||
}); | ||
}); | ||
}; | ||
|
||
conn.commit = function() {}; | ||
conn.sd = []; | ||
|
||
const curs = { | ||
execute: async function executeSQL(sql = '', params = [], noerror = false) { | ||
if((sql).toUpperCase().startsWith("SELECT")) { | ||
const retval = await conn.query(sql, params); | ||
conn.sd = retval; | ||
|
||
return retval; | ||
} else { | ||
await conn.exec(sql, params); | ||
} | ||
|
||
return []; | ||
}, | ||
fetchall: function fetchSQLData() { | ||
return conn.sd; | ||
} | ||
}; | ||
|
||
const html = { | ||
escape: function(content = '') { | ||
content = content.replace(/[&]/gi, '&'); | ||
content = content.replace(/["]/gi, '"'); | ||
content = content.replace(/[<]/gi, '<'); | ||
content = content.replace(/[>]/gi, '>'); | ||
|
||
return content; | ||
} | ||
}; | ||
|
||
const print = console.log; | ||
|
||
function JSnamumark(title, content, initializeBacklinks = 0) { | ||
return new Promise((resolve, reject) => { | ||
try {(new (require('js-namumark'))(title, { | ||
wiki: { | ||
read: title => content.replace(/\r\n/g, '\n').replace(/\r/g, '\n').replace(/{{{[#][!]html/gi, '{{{') | ||
}, | ||
allowedExternalImageExts: [ 'jpg', 'jpeg', 'bmp', 'gif', 'png' ] | ||
})).parse(async (e, r) => { | ||
if(e) { | ||
print(e.stack); | ||
reject(e); | ||
return; | ||
} | ||
|
||
var htmlc = r['html']; | ||
|
||
htmlc = htmlc.replace( | ||
/\<div class=\"wiki[-]toc\" id=\"wiki[-]toc\"\>\<div class=\"wiki[-]toc[-]heading\"\>목차\<\/div\>((\<div class=\"wiki[-]toc[-]item wiki[-]toc[-]item[-]indent[-](\d+)\"\>\<a href=\"[#]heading[-](\d+)\"\>(\d+)[.]\<\/a\> (((?!\<\/div\>).)*)\<\/div\>)*)\<\/div\>\<\/div\>/g | ||
, '<div class=wiki-toc id=toc><div class=wiki-toc-heading>목차</div>$1</div>' | ||
); | ||
|
||
const jsdom = require("jsdom"); | ||
const { JSDOM } = jsdom; | ||
const { window } = new JSDOM(); | ||
const { document } = (new JSDOM(htmlc)).window; | ||
const $ = jQuery = require('jquery')(window); | ||
|
||
const qa = (q, f) => { | ||
for(el of document.querySelectorAll(q)) { | ||
f(el); | ||
} | ||
}; | ||
|
||
// 이미지에 링크 추가 | ||
qa('img', img => { | ||
const $img = $(img); | ||
|
||
if(!$img.attr('src')) return; | ||
const filename = decodeURIComponent($img.attr('src').replace(/^\/file\//, '')); | ||
$img.wrap('<a href="/files/' + encodeURIComponent(filename) + '"></a>'); | ||
|
||
img.outerHTML = $img[0].outerHTML; | ||
}); | ||
|
||
qa('h1 a[href="#wiki-toc"], h2 a[href="#wiki-toc"], h3 a[href="#wiki-toc"], h4 a[href="#wiki-toc"], h5 a[href="#wiki-toc"], h6 a[href="#wiki-toc"]', hlink => { | ||
hlink.setAttribute('href', '#toc'); | ||
const $heading = $(hlink).parent(); | ||
|
||
$heading.attr('class', 'wiki-heading'); | ||
const hnum = $heading.attr('id').replace('heading-', ''); | ||
$heading.attr('id', 's-' + hnum); | ||
|
||
hlink.parentNode.outerHTML = $heading[0].outerHTML; | ||
}); | ||
|
||
qa('div.wiki-toc#wiki-toc', t => t.setAttribute('id', 'toc')); | ||
|
||
htmlc = document.documentElement.outerHTML; | ||
|
||
var ctgr = ''; | ||
|
||
for(cate of r['categories']) { | ||
ctgr += ` | ||
<li class=wiki-link-internal><a class=wiki-internal-link href="/w/${encodeURIComponent('분류:' + cate)}">${html.escape(cate)}</a></li> | ||
`; | ||
} | ||
|
||
if(initializeBacklinks) { | ||
curs.execute("delete from backlink_category where title = ?", [title]) | ||
.then(x => { | ||
for(cate of r['categories']) { | ||
curs.execute("insert into backlink_category (title, category) values (?, ?)", [title, cate]); | ||
} | ||
}) | ||
.catch(console.error); | ||
|
||
curs.execute("delete from backlink where title = ?", [title]) | ||
.then(x => { | ||
qa('a.wiki-internal-link', el => { | ||
try { | ||
curs.execute("insert into backlink (title, link) values (?, ?)", [title, el.getAttribute('href').replace(/^\/wiki\//, '')]); | ||
} catch(e) { | ||
print(e.stack); | ||
} | ||
}); | ||
}) | ||
.catch(console.error); | ||
} | ||
|
||
if(ctgr.length) { | ||
ctgr = '<div class=wiki-category><h2>문서 분류</h2><ul>' + ctgr + '</ul></div>'; | ||
} | ||
|
||
resolve(ctgr + htmlc); | ||
}); | ||
} catch(e) { | ||
print(e.stack); | ||
resolve('<렌더링에 실패했읍니다 - ' + e + '>'); | ||
} | ||
}); | ||
} | ||
|
||
curs.execute("select title, content from documents").then(data => { | ||
for(doc of data) { | ||
JSnamumark(doc.title, doc.content, 1); | ||
} | ||
}); |
Oops, something went wrong.