Skip to content

Commit

Permalink
-
Browse files Browse the repository at this point in the history
  • Loading branch information
gdl-blue committed Nov 19, 2020
0 parents commit 6e824df
Show file tree
Hide file tree
Showing 196 changed files with 69,702 additions and 0 deletions.
148 changes: 148 additions & 0 deletions README.md
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 added animations/chick.tcv
Binary file not shown.
Binary file added animations/snow.tcv
Binary file not shown.
Binary file added banana.exe
Binary file not shown.
Binary file added beep.exe
Binary file not shown.
172 changes: 172 additions & 0 deletions bklnkrst.njs
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, '&amp;');
content = content.replace(/["]/gi, '&quot;');
content = content.replace(/[<]/gi, '&lt;');
content = content.replace(/[>]/gi, '&gt;');

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);
}
});
Loading

0 comments on commit 6e824df

Please sign in to comment.