- 問題:
- mce html editor:每次存檔都會多一行出來。
- https://www.w3school.com.cn/php/func_string_nl2br.asp
- 結果:
- 內文繫結時,使用了nl2br函式。
- 導致每次顯示都加上了
之類的語法。
kyle'sBlog
2025年5月9日 星期五
[筆記][PHP][MCE]MCE編輯器使用nl2br語法
2025年3月3日 星期一
[筆記][LINEBOT]訊息事件類別event type
參考:
- https://developers.line.biz/en/docs/messaging-api/
- ReceivedMessage.events[0].type
- event.message.type
主要事件類型:
- message - 使用者傳送訊息(文字、圖片、影片等)。
- follow - 使用者加為好友或解除封鎖後再次加回。
- unfollow - 使用者封鎖機器人。
- join - 機器人被加入群組或聊天室。
- leave - 機器人被移出群組或聊天室。
- memberJoined - 有新成員加入群組或聊天室。
- memberLeft - 有成員離開群組或聊天室。
- postback - 使用者點擊 Postback Action 按鈕(會附帶 postback.data)。
- beacon - 使用者進入 Beacon(LINE Beacon 訊號)。
- accountLink - 使用者點擊 LINE Login 並綁定帳號。
- things - 來自 LINE Things (IoT 相關) 的事件。
message 事件的子類型:
當 type 為 message 時,還會有 message.type 來指定訊息種類,例如:
- text - 文字訊息
- image - 圖片訊息
- video - 影片訊息
- audio - 音訊訊息
- file - 檔案訊息
- location - 位置訊息
- sticker - 貼圖訊息
2025年1月14日 星期二
[筆記]瀏覽器可以正常取得JSON資料,但使用C#_HttpClient取資料,執行緩慢。
問題:瀏覽器可以正常取得JSON資料,但使用C# HttpClient取資料,執行緩慢。
ChatGPT:其中一種原因。可能有使用Proxy。
解法:將Proxy關閉。
HttpClientHandler handler = new HttpClientHandler
{
Proxy = null,
UseProxy = false
};
HttpClient client = new HttpClient(handler);
HttpClientHandler handler = new HttpClientHandler
{
Proxy = null,
UseProxy = false
};
HttpClient client = new HttpClient(handler);
2024年11月10日 星期日
[筆記][GS]透過GoogleAppsScript(網頁應用程式)寫入檔案
需求:
- 類似表單訊息收集或是Log蒐集。
- 系統會在指定目錄下依照日期建立檔案(每天一個檔)
- 也可以指定要產生哪種類型的檔案。(csv excel等)
AI給的範例:
This file contains hidden or 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
// 建立或獲取指定資料夾 | |
function getOrCreateFolder(parentFolder, folderName) { | |
const folders = parentFolder.getFoldersByName(folderName); | |
if (folders.hasNext()) { | |
return folders.next(); | |
} else { | |
return parentFolder.createFolder(folderName); | |
} | |
} | |
// 取得或創建當天的檔案 | |
function getOrCreateDailyFile(format) { | |
const today = new Date(); | |
const year = today.getFullYear().toString(); | |
const month = Utilities.formatString("%02d", today.getMonth() + 1); | |
// 獲取或創建 GoogleAppsScript 目錄 | |
const rootFolders = DriveApp.getFoldersByName("GoogleAppsScript"); | |
let rootFolder; | |
if (rootFolders.hasNext()) { | |
rootFolder = rootFolders.next(); | |
} else { | |
rootFolder = DriveApp.createFolder("GoogleAppsScript"); | |
} | |
// 建立年份資料夾 | |
const yearFolder = getOrCreateFolder(rootFolder, year); | |
// 建立月份資料夾 | |
const monthFolder = getOrCreateFolder(yearFolder, `${year}-${month}`); | |
// 設定檔案名稱 (年-月-日) | |
const fileName = Utilities.formatDate(today, "GMT+8", "yyyy-MM-dd") + `.${format}`; | |
// 在月份資料夾中尋找今天的檔案 | |
let file; | |
const files = monthFolder.getFilesByName(fileName); | |
if (files.hasNext()) { | |
file = files.next(); | |
} else { | |
// 創建新的檔案 | |
if (format === 'xlsx') { | |
const spreadsheet = SpreadsheetApp.create(fileName); | |
DriveApp.getFileById(spreadsheet.getId()).moveTo(monthFolder); | |
const sheet = spreadsheet.getSheets()[0]; | |
sheet.getRange("A1:D1").setValues([["時間戳記", "訊息內容", "發送者", "其他資料"]]); | |
file = DriveApp.getFileById(spreadsheet.getId()); | |
} else { | |
file = monthFolder.createFile(fileName, "時間戳記,訊息內容,發送者,其他資料\n", MimeType.PLAIN_TEXT); | |
} | |
} | |
return file; | |
} | |
// 寫入數據的 doGet 函數 | |
function doGet(e) { | |
const action = e.parameter.action || 'write'; | |
const format = e.parameter.format || 'xlsx'; // 預設為 xlsx 格式 | |
if (action === 'read') { | |
return getSheetData(e); | |
} | |
try { | |
const params = e.parameter; | |
const file = getOrCreateDailyFile(format); | |
// 準備要寫入的數據 | |
const timestamp = new Date().toLocaleString("zh-TW", {timeZone: "Asia/Taipei"}); | |
const rowData = `${timestamp},${params.message || ""},${params.sender || ""},${params.extraData || ""}\n`; | |
if (format === 'xlsx') { | |
const spreadsheet = SpreadsheetApp.openById(file.getId()); | |
const sheet = spreadsheet.getSheets()[0]; | |
sheet.appendRow([timestamp, params.message || "", params.sender || "", params.extraData || ""]); | |
} else { | |
const content = file.getBlob().getDataAsString() + rowData; | |
file.setContent(content); | |
} | |
return ContentService.createTextOutput(JSON.stringify({ | |
status: "success", | |
message: "數據已成功儲存", | |
data: params | |
})).setMimeType(ContentService.MimeType.JSON); | |
} catch (error) { | |
return ContentService.createTextOutput(JSON.stringify({ | |
status: "error", | |
message: error.toString() | |
})).setMimeType(ContentService.MimeType.JSON); | |
} | |
} | |
// 讀取數據的函數 | |
function getSheetData(e) { | |
try { | |
const params = e.parameter; | |
const targetDate = params.date || Utilities.formatDate(new Date(), "GMT+8", "yyyy-MM-dd"); | |
const format = params.format || 'xlsx'; | |
// 解析目標日期 | |
const dateParts = targetDate.split('-'); | |
const year = dateParts[0]; | |
const month = dateParts[1]; | |
// 獲取 GoogleAppsScript 目錄 | |
const rootFolder = DriveApp.getFoldersByName("GoogleAppsScript").next(); | |
const yearFolder = rootFolder.getFoldersByName(year).next(); | |
const monthFolder = yearFolder.getFoldersByName(`${year}-${month}`).next(); | |
const files = monthFolder.getFilesByName(`${targetDate}.${format}`); | |
if (!files.hasNext()) { | |
return ContentService.createTextOutput(JSON.stringify({ | |
status: "error", | |
message: "找不到指定日期的檔案" | |
})).setMimeType(ContentService.MimeType.JSON); | |
} | |
const file = files.next(); | |
let data; | |
if (format === 'xlsx') { | |
const spreadsheet = SpreadsheetApp.openById(file.getId()); | |
const sheet = spreadsheet.getSheets()[0]; | |
data = sheet.getDataRange().getValues(); | |
} else { | |
const content = file.getBlob().getDataAsString(); | |
data = content.split('\n').map(line => line.split(',')); | |
} | |
// 將數據轉換為 JSON 格式 | |
const headers = data[0]; | |
const jsonData = data.slice(1).filter(row => row.length > 1).map(row => { | |
let obj = {}; | |
headers.forEach((header, index) => { | |
obj[header] = row[index]; | |
}); | |
return obj; | |
}); | |
return ContentService.createTextOutput(JSON.stringify({ | |
status: "success", | |
date: targetDate, | |
data: jsonData | |
})).setMimeType(ContentService.MimeType.JSON); | |
} catch (error) { | |
return ContentService.createTextOutput(JSON.stringify({ | |
status: "error", | |
message: error.toString() | |
})).setMimeType(ContentService.MimeType.JSON); | |
} | |
} |
2024年9月21日 星期六
markmap 範例
title: markmap markmap:
colorFreezeLevel: 2
Links
Related Projects
- coc-markmap for Neovim
- markmap-vscode for VSCode
- eaf-markmap for Emacs
Features
Note that if blocks and lists appear at the same level, the lists will be ignored.
Lists
- strong ~~del~~ italic ==highlight==
inline code
- [x] checkbox
- Katex: $x = {-b \pm \sqrt{b^2-4ac} \over 2a}$
- More Katex Examples
- Now we can wrap very very very very long text based on
maxWidth
option
Blocks
console.log('hello, JavaScript')
| Products | Price | |-|-| | Apple | 4 | | Banana | 2 |
2024年9月19日 星期四
[筆記][Markdown]在Blogger使用Markdown
參考:
目前本blogger簡易作法
引用:
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.6.4/showdown.min.js"></script><script>var converter = new showdown.Converter();var posts = document.querySelectorAll(".post-body,.snippet-item");Array.prototype.forEach.call(posts, function(el, i){if(el.innerHTML.indexOf("markdown") <= 1){el.innerHTML = converter.makeHtml(el.innerHTML.replace("markdown",""));}});var pres = document.querySelectorAll("pre");Array.prototype.forEach.call(pres, function(el, i){el.classList.add("prettyprint");});</script><scriptsrc="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?skin=sunburst"></script>
之後在blogger側欄加入一個javascrpit的語法區塊。(放其他區塊也可以,放側欄 是因為這個版型每頁都有側欄。
訂閱:
文章 (Atom)